【问题标题】:Iterate over an object's "public" attributes [duplicate]迭代对象的“公共”属性[重复]
【发布时间】:2012-02-14 16:01:04
【问题描述】:

最近,我发现自己在编写这样的代码:

对于 dir(object) 中的名称: 如果 name.startswith('__') : 继续 ...

是否有更 Pythonic 的方式来访问对象的“公共”命名空间?

【问题讨论】:

  • 你首先解决了什么问题,这个结构很有用?
  • for name in filter( lambda x: not x.startswith('_'), dir(obj)): 怎么样?请注意,在 Python 中,即使是单个下划线 (_) 也旨在表示 "private" 属性。
  • @NiklasR for name in ( x for x in dir(obj) if not x.startswith('_') ): 不需要过滤器
  • 奇怪的是,该问题被标记为与 6 个月后提出的问题重复......
  • 在提出问题 5 年后发生这种情况也很奇怪!

标签: python


【解决方案1】:

您可以在之前准备“公共”属性列表(作为列表或生成器):

>>> 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的属性。

【讨论】:

  • 有理由更喜欢dir(object) 而不是object.__dict__
  • object.__dict__ 不一定会返回你想要的属性,至少从我的测试结果来看是这样的。
【解决方案2】:

我觉得迭代列表推导比使用 continue 关键字更符合 Python 风格,但这可能只是个人喜好问题。诚然,它并不比你已经拥有的优雅得多。

for attr in (a for a in dir(object) if not a.startswith('_')):
  pass

注意:单下划线属性也不是“公共的”。

【讨论】:

    【解决方案3】:

    您可以改用vars function

    例如:

    >>> 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() 函数的优势在于可以消除除实例变量之外的所有变量。

    【讨论】:

    • 我在其他一些对象上尝试这个时得到TypeError: vars() argument must have __dict__ attribute
    • 是的,vars() 函数只能用于具有__dict__ 的对象。因此,例如,如果在您的类中定义了__slots__,那么您将无法使用vars() 函数。
    • 另请注意,这不会得到任何属性,因此不仅仅是 __slots__ 不起作用。
    猜你喜欢
    • 2011-06-18
    • 2012-07-23
    • 1970-01-01
    • 2021-12-04
    • 2023-03-24
    • 1970-01-01
    • 2015-11-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多