属性不是有效的python标识符

时间:2014-10-23 18:15:41

标签: python attributes

通常的属性访问方法要求属性名称为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保留关键字等的属性,是否真的有任何有效的用例?我认为原因是属性只是对象/命名空间dict中的键,但这没有意义,因为不允许使用其他有效dict键的对象:

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

2 个答案:

答案 0 :(得分:1)

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

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

答案 1 :(得分:1)

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

Guido说:

  

... 功能可以使用任意字符串   使用getattr()和setattr()。但是这些功能应该(并且做!)   拒绝非字符串。

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

至于禁止非字符串的原因,这似乎是一个明智的限制,它确保了更高的执行性能:

  

尽管Python的dicts已经有了一些仅限字符串的优化 - 但是一旦第一个非键字符串出现,它们就会动态地适应更通用和稍慢的方法。