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

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"。我希望它能看到脚本各个部分的当前属性。


当前回答

使用__dict__或vars是无效的,因为它会遗漏__slots__。 使用__dict__和__slots__不能工作,因为它从基类中遗漏了__slots__。 使用dir不能工作,因为它包含类属性,如方法或属性,以及对象属性。 使用vars相当于使用__dict__。

这是我最好的:

from typing import Dict

def get_attrs( x : object ) -> Dict[str, object]:
    mro      = type( x ).mro()
    attrs    = { }
    has_dict = False
    sentinel = object()

    for klass in mro:
        for slot in getattr( klass, "__slots__", () ):
            v = getattr( x, slot, sentinel )

            if v is sentinel:
                continue

            if slot == "__dict__":
                assert not has_dict, "Multiple __dicts__?"
                attrs.update( v )
                has_dict = True
            else:
                attrs[slot] = v

    if not has_dict:
        attrs.update( getattr( x, "__dict__", { } ) )

    return attrs

其他回答

>>> ', '.join(i for i in dir(a) if not i.startswith('__'))
'multi, str'

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

请参见以下Python shell脚本执行顺序,它将给出从创建类到提取实例字段名的解决方案。

>>> class Details:
...       def __init__(self,name,age):
...           self.name=name
...           self.age =age
...       def show_details(self):
...           if self.name:
...              print "Name : ",self.name
...           else:
...              print "Name : ","_"
...           if self.age:
...              if self.age>0:
...                 print "Age  : ",self.age
...              else:
...                 print "Age can't be -ve"
...           else:
...              print "Age  : ","_"
... 
>>> my_details = Details("Rishikesh",24)
>>> 
>>> print my_details
<__main__.Details instance at 0x10e2e77e8>
>>> 
>>> print my_details.name
Rishikesh
>>> print my_details.age
24
>>> 
>>> my_details.show_details()
Name :  Rishikesh
Age  :  24
>>> 
>>> person1 = Details("",34)
>>> person1.name
''
>>> person1.age
34
>>> person1.show_details
<bound method Details.show_details of <__main__.Details instance at 0x10e2e7758>>
>>> 
>>> person1.show_details()
Name :  _
Age  :  34
>>>
>>> person2 = Details("Rob Pike",0)
>>> person2.name
'Rob Pike'
>>> 
>>> person2.age
0
>>> 
>>> person2.show_details()
Name :  Rob Pike
Age  :  _
>>> 
>>> person3 = Details("Rob Pike",-45)
>>> 
>>> person3.name
'Rob Pike'
>>> 
>>> person3.age
-45
>>> 
>>> person3.show_details()
Name :  Rob Pike
Age can't be -ve
>>>
>>> person3.__dict__
{'age': -45, 'name': 'Rob Pike'}
>>>
>>> person3.__dict__.keys()
['age', 'name']
>>>
>>> person3.__dict__.values()
[-45, 'Rob Pike']
>>>

除了这些答案之外,我还将包括一个函数(python 3),用于输出任何值的几乎整个结构。它使用dir来建立属性名的完整列表,然后对每个名称使用getattr。它会显示值的每个成员的类型,如果可能的话还会显示整个成员:

import json

def get_info(obj):

  type_name = type(obj).__name__
  print('Value is of type {}!'.format(type_name))
  prop_names = dir(obj)

  for prop_name in prop_names:
    prop_val = getattr(obj, prop_name)
    prop_val_type_name = type(prop_val).__name__
    print('{} has property "{}" of type "{}"'.format(type_name, prop_name, prop_val_type_name))

    try:
      val_as_str = json.dumps([ prop_val ], indent=2)[1:-1]
      print('  Here\'s the {} value: {}'.format(prop_name, val_as_str))
    except:
      pass

现在,以下任何一项都应该让你有所了解:

get_info(None)
get_info('hello')

import numpy
get_info(numpy)
# ... etc.

如前所述,使用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类属性,可能会省略所需的类属性。 有时,我们可能认为属性是实例成员,但它不是,也不会在本例中显示。

你可以使用dir(your_object)来获取属性,使用getattr(your_object, your_object_attr)来获取值

用法:

for att in dir(your_object):
    print (att, getattr(your_object,att))

如果你的对象没有__dict__,这特别有用。如果不是这样,你也可以尝试var(your_object)