【问题标题】:Attributes which aren't valid python identifiers不是有效 python 标识符的属性
【发布时间】:2014-10-23 18:15:40
【问题描述】:

属性访问的常用方法要求属性名称为valid python identifiers

但属性不必是有效的 Python 标识符:

>>> class Thing:
...     def __init__(self):
...         setattr(self, '0potato', 123)
...         
>>> t = Thing()
>>> Thing.__getattribute__(t, '0potato')
123
>>> getattr(t, '0potato')
123

当然,t.0potato 仍然是 SyntaxError,但属性仍然存在:

>>> vars(t)
{'0potato': 123}

允许这样做的原因是什么?对于带有空格、空字符串、python 保留关键字等的属性,真的有任何有效的用例吗?我认为原因是属性只是对象/命名空间字典中的键,但这没有意义,因为不允许其他作为有效字典键的对象:

>>> setattr(t, ('tuple',), 321)
TypeError: attribute name must be string, not 'tuple'

【问题讨论】:

  • 为什么允许这样做的答案可以在@poke 的答案here 中找到。我不认为你的问题应该被欺骗,因为它要求合法的用例,而另一个只问为什么允许这样做。
  • 首先请参阅 Martin v. Löwis 在Python Issue 14029 中的回复。所以它主要取决于__setattr__ 的底层实现,它可以接受非标识符。尽管如此,尽管可以创建一个接受元组的__setattr__,但在通过setattr 调用时仍然失败。因此,似乎内置方法不只是盲目地将其参数传递给对象的 __setattr__ 方法。
  • 这是Guido van Rossum considering你的问题。

标签: python attributes


【解决方案1】:

因此,为了回答用例问题,看看 Python 在上述 cmets 的引用中的工作原理,我们可以推断出一些可能使这个 Pythonic 怪癖有用的情况。

  1. 您希望对象具有无法使用点符号访问的属性,例如,以保护它免受天真的用户的侵害。 (引用 Guido 的话:“有些人可能会使用它来隐藏他们不希望使用常规属性表示法 (x.foo) 访问的状态”。当然,他接着说,“但这对我来说就像滥用命名空间, 还有很多其他 管理这种状态的方法。”)
  2. 您希望对象的属性名称与您无法控制的外部数据相对应。因此,您必须能够将外部数据中出现的任何字符串用作属性名称,即使它与 Python 保留字匹配或包含嵌入的空格或破折号等。

【讨论】:

    【解决方案2】:

    帖子上comment 的详细信息完全回答了这个问题,所以我将其发布为答案:

    Guido 说:

    ...这是一个 feature,您可以使用任意字符串 使用 getattr() 和 setattr()。然而,这些功能应该(并且做!) 拒绝非字符串。

    可能的用例包括隐藏属性以防止常规点访问,以及使属性与外部数据源相对应(可能与 Python 关键字冲突)。所以,争论似乎是没有充分的理由禁止它。

    至于禁止非字符串的原因,这似乎是一个合理的限制,可以确保实现更好的性能:

    虽然 Python 的 dicts 已经有一些仅字符串的优化——一旦第一个非键字符串出现,它们只是动态地适应更通用且稍微慢一些的方法。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-11-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-09-08
      • 1970-01-01
      • 2017-08-14
      • 1970-01-01
      相关资源
      最近更新 更多