是否有一种方法可以获取类实例上存在的属性列表?

class new_class():
    def __init__(self, number):
        self.multi = int(number) * 2
        self.str = str(number)

a = new_class(2)
print(', '.join(a.SOMETHING))

期望的结果是输出"multi, str"。我希望它能看到脚本各个部分的当前属性。


当前回答

人们经常提到,要列出一个完整的属性列表,应该使用dir()。但是请注意,与普遍观点相反,dir()并没有显示所有属性。例如,你可能会注意到__name__可能在类的dir()列表中缺失,即使你可以从类本身访问它。从dir()的文档(Python 2, Python 3):

因为提供dir()主要是为了方便在 交互式提示符,它试图提供一组有趣的名称 它不仅仅是试图提供一个严格或一致定义的集合 的名称,其详细行为可能在不同版本之间更改。为 属性时,元类属性不在结果列表中 参数是一个类。

像下面这样的函数往往更完整,尽管不能保证完整性,因为dir()返回的列表可能受到许多因素的影响,包括实现__dir__()方法,或在类或其父类之一上自定义__getattr__()或__getattribute__()。详情请参阅所提供的链接。

def dirmore(instance):
    visible = dir(instance)
    visible += [a for a in set(dir(type)).difference(visible)
                if hasattr(instance, a)]
    return sorted(visible)

其他回答

做这件事的方法不止一种:

#! /usr/bin/env python3
#
# This demonstrates how to pick the attiributes of an object

class C(object) :

  def __init__ (self, name="q" ):
    self.q = name
    self.m = "y?"

c = C()

print ( dir(c) )

当运行时,这段代码产生:

jeffs@jeff-desktop:~/skyset$ python3 attributes.py 
['__class__', '__delattr__', '__dict__', '__dir__', '__doc__',      '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'm', 'q']

jeffs@jeff-desktop:~/skyset$

__attrs__给出了一个实例的属性列表。

>>> import requests
>>> r=requests.get('http://www.google.com')
>>> r.__attrs__
['_content', 'status_code', 'headers', 'url', 'history', 'encoding', 'reason', 'cookies', 'elapsed', 'request']
>>> r.url
'http://www.google.com/'
>>>
>>> ', '.join(i for i in dir(a) if not i.startswith('__'))
'multi, str'

这当然会打印类定义中的任何方法或属性。你可以通过将i.startwith('__')更改为i.startwith('_')来排除“私有”方法。

如前所述,使用obj。__dict__可以处理常见情况,但有些类没有__dict__属性,而使用__slots__(主要是为了提高内存效率)。

举个更有弹性的例子:

class A(object):
    __slots__ = ('x', 'y', )
    def __init__(self, x, y):
        self.x = x
        self.y = y


class B(object):
    def __init__(self, x, y):
        self.x = x
        self.y = y


def get_object_attrs(obj):
    try:
        return obj.__dict__
    except AttributeError:
        return {attr: getattr(obj, attr) for attr in obj.__slots__}


a = A(1,2)
b = B(1,2)
assert not hasattr(a, '__dict__')

print(get_object_attrs(a))
print(get_object_attrs(b))

这段代码的输出:

{'x': 1, 'y': 2}
{'x': 1, 'y': 2}

注一: Python是一种动态语言,它总是更好地了解你试图从中获取属性的类,因为即使这些代码也可能错过一些情况。

注2: 这段代码只输出实例变量,这意味着不提供类变量。例如:

class A(object):
    url = 'http://stackoverflow.com'
    def __init__(self, path):
        self.path = path

print(A('/questions').__dict__)

代码输出:

{'path': '/questions'}

这段代码不打印url类属性,可能会省略所需的类属性。 有时,我们可能认为属性是实例成员,但它不是,也不会在本例中显示。

>>> class new_class():
...   def __init__(self, number):
...     self.multi = int(number) * 2
...     self.str = str(number)
... 
>>> a = new_class(2)
>>> a.__dict__
{'multi': 4, 'str': '2'}
>>> a.__dict__.keys()
dict_keys(['multi', 'str'])

您可能还会发现pprint有帮助。