为什么Python对象可以有由整数表示的属性?

3 投票
2 回答
542 浏览
提问于 2025-04-18 18:24

我觉得我可能对Python中的属性有一些基本的误解。考虑以下内容:

 >>> class Test:
 ...     pass
 ... 
 >>> t = Test()
 >>> setattr(t, '0', 0)
 >>> t.0
   File "<stdin>", line 1
     t.0
       ^
 SyntaxError: invalid syntax
 >>> getattr(t, '0')
 0
 >>> setattr(t, 'one', 1)
 >>> t.one
 1
 >>> getattr(t, 'one')
 1

为什么Python允许我设置一个属性,但我却不能用点号(.)的方式合法地访问它呢?我明白t.0没有意义,但同时我也在想,为什么它和t.one没有什么不同,因为我创建它们的方式是一样的。

2 个回答

2

属性是任何Python对象都可以拥有的一种成员。通常,你会认为Python的语法会规定什么样的属性名称是可以接受的。关于这一点,定义是相当清楚的:

attributeref ::=  primary "." identifier

在点号后面跟着的内容必须是一个有效的标识符,这就限制了可以使用的属性名称。暂时不考虑其他Unicode字符,这基本上意味着属性名称不能以数字开头。所以像0这样的名称就不是有效的标识符,因此t.0在规范中也不是一个有效的属性引用

不过,getattr等函数的工作方式有点不同。它们只要求属性名称是一个字符串。这个字符串会直接传递给内部的PyObject_GetAttr函数,而这些函数并不需要一个有效的标识符。

所以通过使用getattr等函数,你实际上可以“欺骗”Python,给对象添加一些在语言规范中不被允许的属性名称。

1

这只是Python语法和语义的一个小特点。任何字符串都可以用作属性名称,但只有标识符(也就是符合命名规则的名称)才能用点号来访问。因此,访问那些不是标识符的属性,唯一的方法就是使用getattr/setattr或者其他一些间接的函数。奇怪的是,这种做法并不意味着任何类型都可以作为属性,只有字符串才有这个特权。

撰写回答