我是C#我们通过反思来做到这一点。在Javascript中它很简单:
for(var propertyName in objectName)
var currentPropertyValue = objectName[propertyName];
如何在Python中完成?
答案 0 :(得分:124)
for property, value in vars(theObject).iteritems():
print property, ": ", value
请注意,在极少数情况下会有__slots__
属性,此类通常没有__dict__
。
答案 1 :(得分:64)
请参阅inspect.getmembers(object[, predicate])
。
返回按名称排序的(名称,值)对列表中对象的所有成员。如果提供了可选的谓词参数,则仅包含谓词返回true值的成员。
>>> [name for name,thing in inspect.getmembers([])]
['__add__', '__class__', '__contains__', '__delattr__', '__delitem__',
'__delslice__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__',
'__getitem__', '__getslice__', '__gt__', '__hash__', '__iadd__', '__imul__', '__init__', '__iter__',
'__le__', '__len__', '__lt__', '__mul__', '__ne__', '__new__', '__reduce__','__reduce_ex__',
'__repr__', '__reversed__', '__rmul__', '__setattr__', '__setitem__', '__setslice__',
'__sizeof__', '__str__', '__subclasshook__', 'append', 'count', 'extend', 'index',
'insert', 'pop', 'remove', 'reverse', 'sort']
>>>
答案 2 :(得分:50)
dir()
是一种简单的方法。见这里:
答案 3 :(得分:12)
对象的__dict__
属性是其所有其他已定义属性的字典。请注意,Python类可以覆盖getattr
并使事物看起来像属性但不在__dict__
。还有内置函数vars()
和dir()
,这些函数在细微方面有所不同。 __slots__
可以在某些不常见的类中替换__dict__
。
Python中的对象很复杂。 __dict__
是反思式编程的正确起点。如果您在交互式shell中进行黑客攻击,dir()
就是您的起点。
答案 4 :(得分:11)
georg scholly更短的版本
print vars(theObject)
答案 5 :(得分:9)
如果你正在寻找所有属性的反映,那么上面的答案都很棒。
如果您只想获取对象的密钥,请使用
my_dict.keys()
my_dict = {'abc': {}, 'def': 12, 'ghi': 'string' }
my_dict.keys()
> ['abc', 'def', 'ghi']
答案 6 :(得分:5)
其他答案完全涵盖了这一点,但我会明确指出。 一个对象可能具有类属性以及静态和动态实例属性。
class foo:
classy = 1
@property
def dyno(self):
return 1
def __init__(self):
self.stasis = 2
def fx(self):
return 3
stasis
是静态的,dyno
是动态的(参见属性装饰器),而classy
是类属性。如果我们只做__dict__
或vars
,我们只会得到静态的。
o = foo()
print(o.__dict__) #{'stasis': 2}
print(vars(o)) #{'stasis': 2}
因此,如果我们希望其他人__dict__
将获得一切(甚至更多)。
这包括魔术方法和属性以及法线绑定方法。因此,请避免这些情况:
d = {k: getattr(o, k, '') for k in o.__dir__() if k[:2] != '__' and type(getattr(o, k, '')).__name__ != 'method'}
print(d) #{'stasis': 2, 'classy': 1, 'dyno': 1}
使用属性修饰方法(动态属性)调用的type
将为您提供返回值的类型,而不是method
。为了证明这一点,让我们用json将其字符串化:
import json
print(json.dumps(d)) #{"stasis": 2, "classy": 1, "dyno": 1}
如果这是一种可能会崩溃的方法。
TL; DR。尝试为所有这三个调用extravar = lambda o: {k: getattr(o, k, '') for k in o.__dir__() if k[:2] != '__' and type(getattr(o, k, '')).__name__ != 'method'}
,但不要调用方法或魔术。
答案 7 :(得分:1)
我认为值得一提的是,提到的各种选择之间的区别-通常一张图片值一千字。
>>> from pprint import pprint
>>> import inspect
>>>
>>> class a():
x = 1 # static class member
def __init__(self):
self.y = 2 # static instance member
@property
def dyn_prop(self): # dynamic property
print('DYNPROP WAS HERE')
return 3
def test(self): # function member
pass
@classmethod
def myclassmethod(cls): # class method; static methods behave the same
pass
>>> i = a()
>>> pprint(i.__dict__)
{'y': 2}
>>> pprint(vars(i))
{'y': 2}
>>> pprint(dir(i))
['__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__',
'dyn_prop',
'myclassmethod',
'test',
'x',
'y']
>>> pprint(inspect.getmembers(i))
DYNPROP WAS HERE
[('__class__', <class '__main__.a'>),
('__delattr__',
<method-wrapper '__delattr__' of a object at 0x000001CB891BC7F0>),
('__dict__', {'y': 2}),
('__dir__', <built-in method __dir__ of a object at 0x000001CB891BC7F0>),
('__doc__', None),
('__eq__', <method-wrapper '__eq__' of a object at 0x000001CB891BC7F0>),
('__format__', <built-in method __format__ of a object at 0x000001CB891BC7F0>),
('__ge__', <method-wrapper '__ge__' of a object at 0x000001CB891BC7F0>),
('__getattribute__',
<method-wrapper '__getattribute__' of a object at 0x000001CB891BC7F0>),
('__gt__', <method-wrapper '__gt__' of a object at 0x000001CB891BC7F0>),
('__hash__', <method-wrapper '__hash__' of a object at 0x000001CB891BC7F0>),
('__init__',
<bound method a.__init__ of <__main__.a object at 0x000001CB891BC7F0>>),
('__init_subclass__',
<built-in method __init_subclass__ of type object at 0x000001CB87CA6A70>),
('__le__', <method-wrapper '__le__' of a object at 0x000001CB891BC7F0>),
('__lt__', <method-wrapper '__lt__' of a object at 0x000001CB891BC7F0>),
('__module__', '__main__'),
('__ne__', <method-wrapper '__ne__' of a object at 0x000001CB891BC7F0>),
('__new__', <built-in method __new__ of type object at 0x00007FFCA630AB50>),
('__reduce__', <built-in method __reduce__ of a object at 0x000001CB891BC7F0>),
('__reduce_ex__',
<built-in method __reduce_ex__ of a object at 0x000001CB891BC7F0>),
('__repr__', <method-wrapper '__repr__' of a object at 0x000001CB891BC7F0>),
('__setattr__',
<method-wrapper '__setattr__' of a object at 0x000001CB891BC7F0>),
('__sizeof__', <built-in method __sizeof__ of a object at 0x000001CB891BC7F0>),
('__str__', <method-wrapper '__str__' of a object at 0x000001CB891BC7F0>),
('__subclasshook__',
<built-in method __subclasshook__ of type object at 0x000001CB87CA6A70>),
('__weakref__', None),
('dyn_prop', 3),
('myclassmethod', <bound method a.myclassmethod of <class '__main__.a'>>),
('test', <bound method a.test of <__main__.a object at 0x000001CB891BC7F0>>),
('x', 1),
('y', 2)]
总结:
vars()
和__dict__
仅返回实例本地属性; dir()
返回所有内容,但仅作为字符串成员名称列表返回;动态属性不被调用; inspect.getmembers()
返回所有内容,作为元组列表(name, value)
;它实际上运行动态属性,并接受可选的predicate
参数,该参数可以按值过滤成员。因此,除非有特殊的性能考虑,否则我的常识性方法通常是在命令行上使用dir()
,在程序中使用getmembers()
。
请注意,为了使内容更整洁,我没有添加__slots__
-如果存在,则明确地将其放置在{em> 中进行查询,应直接使用。我也没有介绍元类,因为元类会有点毛病(大多数人永远不会使用它们)。