提问人:William Pursell 提问时间:1/20/2012 更新时间:7/12/2022 访问量:18776
遍历对象的“公共”属性 [duplicate]
Iterate over an object's "public" attributes [duplicate]
问:
最近,我发现自己在写这样的代码:
for name in dir( object ): if name.startswith( '__' ) : continue ...
有没有一种更 pythonic 的方式来访问对象的“公共”命名空间?
答:
22赞
srgerg
1/20/2012
#1
您可以改用 vars
函数。
例如:
>>> class C(object):
... def __init__(self):
... self.__foo = 'foo'
...
>>> c = C()
>>> dir(c)
['_C__foo', '__class__', '__delattr__', '__dict__', '__doc__', '__format__',
'__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__',
'__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__',
'__weakref__']
>>> vars(c)
{'_C__foo': 'foo'}
请注意,正如 Niklas R 所指出的,带有单个下划线的变量也被视为私有变量。但是,该函数的优点是消除了除实例变量之外的所有变量。vars()
评论
2赞
wim
1/20/2012
我在其他一些物体上尝试这个时得到TypeError: vars() argument must have __dict__ attribute
3赞
srgerg
1/20/2012
是的,该函数只能用于具有 .因此,例如,如果在类上定义了 Force,则无法使用该函数。vars()
__dict__
__slots__
vars()
2赞
Joe Kington
1/20/2012
还要注意的是,这不会得到任何属性,所以不仅仅是那些不起作用的东西。__slots__
2赞
wim
1/20/2012
#2
与使用关键字的排除分支相比,直接迭代对公共名称的理解似乎更像是 Pythonic。但这可能只是一个品味问题,诚然,它并不比你已经拥有的好多少。continue
public_names = (n for n in dir(object) if not n.startswith('_'))
for attr in public_names:
...
注意:单个下划线属性也不是“公共”属性。
19赞
Tadeck
1/20/2012
#3
您可以在以下情况下准备“public”属性列表(作为列表或生成器):
>>> public_props = (name for name in dir(object) if not name.startswith('_'))
>>> for name in public_props:
print name
但请阅读文档中有关函数的注释:dir()
注意由于提供它主要是为了方便在交互式提示下使用,因此它尝试提供一组有趣的名称,而不是尝试提供一组严格或一致定义的名称,并且其详细行为可能会因版本而异。例如,当参数是类时,元类属性不在结果列表中。
dir()
您还应该知道,任何类都可以实现可能返回不一定与属性名称对应的名称列表的方法。换言之,不保证结果将返回 的属性。__dir__()
dir(something)
something
评论
1赞
Dave
4/15/2015
有没有理由更喜欢?dir(object)
object.__dict__
1赞
James Lin
6/1/2016
object.__dict__不一定返回您想要的属性,至少从我的测试结果来看是这样。
评论
for name in filter( lambda x: not x.startswith('_'), dir(obj)):
_
for name in ( x for x in dir(obj) if not x.startswith('_') ):