Python 如何理解这个uu getattr_uu作为元类方法的示例
下面是Mark Lutz的书“学习Python”中的一个示例片段。我发现很难理解名称访问如何转换为元类中的getattr()调用:Python 如何理解这个uu getattr_uu作为元类方法的示例,python,Python,下面是Mark Lutz的书“学习Python”中的一个示例片段。我发现很难理解名称访问如何转换为元类中的getattr()调用: >>> class A(type): def __getattr__(cls, name): return getattr(cls.data, name) >>> class B(metaclass=A): data = 'spam
>>> class A(type):
def __getattr__(cls, name):
return getattr(cls.data, name)
>>> class B(metaclass=A):
data = 'spam'
>>> B.upper()
'SPAM'
>>> B.upper
<built-in method upper of str object at 0x029E7420>
>>> B.__getattr__
<bound method A.__getattr__ of <class '__main__.B'>>
>>> B.data = [1, 2, 3]
>>> B.append(4)
>>> B.data
[1, 2, 3, 4]
>>> B.__getitem__(0)
1
>>> B[0]
TypeError: 'A' object does not support indexing
>>A类(类型):
def_u_getattr__(cls,名称):
返回getattr(cls.data,name)
>>>B类(元类=A):
数据='垃圾邮件'
>>>B.上()
“垃圾邮件”
>>>上
>>>B.uu getattr__
>>>B.数据=[1,2,3]
>>>B.3(4)
>>>B.数据
[1, 2, 3, 4]
>>>B.uu获取项目(0)
1.
>>>B[0]
TypeError:“A”对象不支持索引
我有以下问题:
A.uu getattr\uuuu(B,upper())
=>getattr(B.data,upper())?但是像getattr('spam',upper())这样的调用会给出错误“NameError:name'upper'未定义”A.\uu getattr\uuu(cls,name)
?如果是,在这种情况下,getattr(cls.data,name)中参数的真实值是多少B.\uuu getitem\uuuu(0)
如何产生1?在本例中,getattr(cls.data,name)中参数的真实值是什么B.upper()
首先查找B.upper
,然后无参数调用它B.upper
是通过按特定顺序尝试多个选项来查找的,最终尝试键入(B)。\uuu getattr\uuuu(B,'upper')
,在本例中是a.\uu getattr\uuuu(B,'upper')
,返回'spam'。upper
B.upper
通过几个选项,在本例中达到类型(B)。\uuuu getattr\uuuuuuub(upper')
即A.\uu getattr\uuuub(upper')
B.append
将到达A.。\uuu getattr\uuuuu(B,'append')
将返回B.data.append
B.。\uuuuGetItem\uuuuuuuuuu0)
在这种情况下将查找B.\uuuuuuuGetItem\uuuuuuuuuuuuuu
并通过A.\uuuuuuuuuGetAttr\uuuuuuuuuuu(B),\uuuuuuuuuuuuuuu getitem\uuuuuuuuuuu')
找到它,它将返回数据
另外,请注意最后一个例子,
B[0]
,它不起作用,因为B
类没有直接定义\uuu getitem\uuu
方法。这是因为“特殊”方法,如\uuu getitem\uuu
,在通过其特殊语法使用时,会以不同的方式进行查找,例如本例中的B[0]
。首先,您不需要添加通常的元类混淆来获得此行为,您可以轻松地使用常规类和实例作为示例:
class A():
def __getattr__(cls, name):
return getattr(cls.data, name)
B = A()
B.data = "spam"
>>> B.data
'spam'
>>> B.upper
<built-in method upper of str object at 0x1057da730>
>>> B.upper()
'SPAM'
>>> B.__getitem__
<method-wrapper '__getitem__' of str object at 0x1057da730>
>>> B.__getitem__(0)
's'
>>> B[0]
Traceback (most recent call last):
File "<pyshell#135>", line 1, in <module>
B[0]
TypeError: 'A' object does not support indexing
第3条和第4条的答案都是添加以下打印语句:
>>> B.data = [1,2,3,4]
>>> B.append(5)
calling __getattr__ for this name: 'append'
>>> B.__getitem__(0)
calling __getattr__ for this name: '__getitem__'
1
使用
B[0]
不会查找B.\uu getitem\uuuuuuuuuuuuuuu
而是类型(B)。\uuuu getitem\uuuuuuuuuuuub(B,0)
,所有其他内容都由B.upper()
解释。我的困难在于格式,或者各种名称访问被转换成的元类中getattr()调用的参数的真实值。谢谢spectras。这回答了我的问题1和3。你能解释一下问题2和4吗?我想这回答了我的问题1、3和4。请你解释一下问题2好吗?我的问题2是:B.upper是如何工作的?它是通过一个.\uuuu getattr\uuuuu,然后再通过getattr吗?如果是这样,getattr参数的真实值是什么。事实上,问题1和问题2是一样的#2生成该方法,而#1通过添加括号调用该方法。括号在python中不是一种特殊的语法,它们的意思是“取左边的内容,并尝试将其作为函数调用,传递这些参数”。@AlexL,如果您发现这个答案确实回答了您的问题,请接受它。
>>> B.data = [1,2,3,4]
>>> B.append(5)
calling __getattr__ for this name: 'append'
>>> B.__getitem__(0)
calling __getattr__ for this name: '__getitem__'
1