是否有一种方法可以获取类实例上存在的属性列表?
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"。我希望它能看到脚本各个部分的当前属性。
是否有一种方法可以获取类实例上存在的属性列表?
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"。我希望它能看到脚本各个部分的当前属性。
当前回答
检查模块:
inspect模块提供了几个有用的函数来帮助获取 有关活动对象的信息,如模块、类、方法、 函数、回溯、帧对象和代码对象。
使用getmembers()可以看到类的所有属性及其值。要排除私有或受保护的属性,请使用. startwith('_')。要排除方法或函数,请使用inspect.ismethod()或inspect.isfunction()。
import inspect
class NewClass(object):
def __init__(self, number):
self.multi = int(number) * 2
self.str = str(number)
def func_1(self):
pass
inst = NewClass(2)
for i in inspect.getmembers(inst):
# Ignores anything starting with underscore
# (that is, private and protected attributes)
if not i[0].startswith('_'):
# Ignores methods
if not inspect.ismethod(i[1]):
print(i)
注意,ismethod()用于i的第二个元素,因为第一个元素只是一个字符串(它的名字)。
跑题:类名使用CamelCase。
其他回答
使用__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
dir(instance)
# or (same value)
instance.__dir__()
# or
instance.__dict__
然后可以用type()测试类型是什么,或者用callable()测试是否为方法。
>>> ', '.join(i for i in dir(a) if not i.startswith('__'))
'multi, str'
这当然会打印类定义中的任何方法或属性。你可以通过将i.startwith('__')更改为i.startwith('_')来排除“私有”方法。
上面所有的答案都是正确的,你有三个选项可以选择
dir () vars () __dict__
>>> dir(a)
['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'multi', 'str']
>>> vars(a)
{'multi': 4, 'str': '2'}
>>> a.__dict__
{'multi': 4, 'str': '2'}
如前所述,使用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类属性,可能会省略所需的类属性。 有时,我们可能认为属性是实例成员,但它不是,也不会在本例中显示。