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

为什么Python对象可以有一个由整数表示的属性?,python,class,object,attributes,Python,Class,Object,Attributes,我想我可能对python属性实际上是什么有一个基本的误解。考虑以下事项: >>> class Test: ... pass ... >>> t = Test() >>> setattr(t, '0', 0) >>> t.0 File "<stdin>", line 1 t.0 ^ SyntaxError: invalid syntax >>>

我想我可能对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
>类测试:
...     通过
... 
>>>t=测试()
>>>setattr(t,'0',0)
>>>t.0
文件“”,第1行
t、 0
^
SyntaxError:无效语法
>>>getattr(t,'0')
0
>>>设置属性(t'一',1)
>>>t.1
1.
>>>getattr(t,‘一’)
1.

如果我不能合法地使用点符号访问属性,Python为什么允许我设置属性?我理解
t.0
毫无意义,但同时我想知道为什么它与
t.one
没有什么不同,因为我是以同样的方式创建它们的。

这只是python语法和语义的一个怪癖。任何字符串都可以用作属性名称,但是只有标识符可以与点表示法一起使用。因此,访问非标识符属性的唯一方法是使用getattr/setattr或其他一些间接函数。奇怪的是,这种做法并没有扩展到允许任何类型作为属性,只有字符串才能获得这种特权。

属性是任何Python对象都可以拥有的一种成员。通常,您希望内置语法指示接受哪种类型的属性名。为此,定义为:

因此,点后面的内容需要是一个有效的,可以很容易地限制允许的属性名称。现在忽略其他Unicode区域,这本质上意味着该属性不能以数字开头。因此
0
不是有效的标识符,因此
t.0
不是规范中的有效属性引用

但是,
getattr
和类似的函数的工作方式有点不同。它们只要求属性名为字符串。该字符串直接传递给内部函数。这些不需要有效的标识符


因此,使用
getattr
等,您基本上可以欺骗Python并将属性附加到对象,而根据语言的规范,这些对象的名称是不允许的。

“奇怪的是,这种做法没有扩展到允许任何类型成为属性的程度,只有字符串才能获得这种特权”。这是正确的,但是您可以在
\uuuu dict\uuu
中将任何哈希对象指定为键。标准库实际上在中使用了它。@dano取决于对象。插槽属性未存储在
目录中。我还可以覆盖
\uuuu getattribute\uuuu
来改变它。
attributeref ::=  primary "." identifier