Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/319.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 如何理解这个uu getattr_uu作为元类方法的示例_Python - Fatal编程技术网

Python 如何理解这个uu getattr_uu作为元类方法的示例

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

下面是Mark Lutz的书“学习Python”中的一个示例片段。我发现很难理解名称访问如何转换为元类中的getattr()调用:

>>> 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”对象不支持索引
我有以下问题:

  • B.upper()如何产生“垃圾邮件”?是因为B.upper()=>
    A.uu getattr\uuuu(B,upper())
    =>getattr(B.data,upper())?但是像getattr('spam',upper())这样的调用会给出错误“NameError:name'upper'未定义”

  • B.upper到yiled的路径是什么。它是否也通过getattr,参数的真实值是多少

  • B.append(4)是否经过
    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