Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/python-3.x/15.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 类型(MyClass.myclassmethod)返回;方法";,不是";classmethod";_Python_Python 3.x_Inheritance_Class Method - Fatal编程技术网

Python 类型(MyClass.myclassmethod)返回;方法";,不是";classmethod";

Python 类型(MyClass.myclassmethod)返回;方法";,不是";classmethod";,python,python-3.x,inheritance,class-method,Python,Python 3.x,Inheritance,Class Method,当方法类型在子类化过程中发生变化时,我偶然发现了这种奇怪的行为: class A: def f(self, x): return x**2 class B(A): @classmethod def f(cls, x): return x**2 如果我现在询问B.f的类型,我会得到(假定)错误的答案: In [37]: type(B.f) Out[37]: method 鉴于此项工作符合预期: In [39]:

当方法类型在子类化过程中发生变化时,我偶然发现了这种奇怪的行为:

class A:
    def f(self, x):
        return x**2

class B(A):
    @classmethod
    def f(cls, x):            
        return x**2
如果我现在询问
B.f
的类型,我会得到(假定)错误的答案:

In [37]: type(B.f)
Out[37]: method
鉴于此项工作符合预期:

In [39]: type(B.__dict__["f"])
Out[39]: classmethod
(见Python 3.4和3.6。)

这只是一个bug还是有具体的原因

属性
f
\uuuu dict\uuuu[“f”]
项之间有什么区别?我以为他们是一样的

在测试套件中,我试图在待测试的类中支持这两种类型的方法。要做到这一点,我需要知道类型,以便传递正确数量的参数。如果它是一个普通的方法(即,
self
是第一个参数),我只需显式地传递
None
,因为它不依赖于实例,所以设计上无论如何都不应该在方法内部使用它


也许有更好的方法可以做到这一点,比如duck键入对该方法的调用。但在某些情况下,这样做可能并不容易,例如,如果该方法具有
*args
**kwargs
。。。因此,我使用了显式类型检查,但在这一点上被卡住了。

不,这不是错误,这是正常行为。当对类进行访问时,
classmethod
生成一个绑定方法。这正是
classmethod
将函数绑定到访问它的类或访问它的实例的类的要点

与函数和
property
对象一样,
classmethod
是一种方法,它实现了一种
\uuuuuuu获取
方法。访问实例或类上的属性被委托给,该钩子的默认实现将不仅仅返回它在
对象中找到的内容;它还将通过调用来绑定描述符。这是Python的一个非常重要的方面,正是这种机制使方法、属性和其他东西的加载工作

classmethod
对象,当被描述符协议绑定时,返回一个方法对象。方法对象是包装器,记录绑定到的对象以及调用它们时要调用的函数;调用一个方法实际上是调用以绑定对象作为第一个参数的基础方法:

>>> class Foo:
...     pass
...
>>> def bar(*args): print(args)
...
>>> classmethod(bar).__get__(None, Foo)  # decorate with classmethod and bind
<bound method bar of <class '__main__.Foo'>>
>>> method = classmethod(bar).__get__(None, Foo)
>>> method.__self__
<class '__main__.Foo'>
>>> method.__func__
<function bar at 0x1056f0e18>
>>> method()
(<class '__main__.Foo'>,)
>>> method('additional arguments')
(<class '__main__.Foo'>, 'additional arguments')
另一方面,函数只希望绑定到实例;因此,如果
\uu get\uu
的第一个参数设置为
None
,它们只返回
self

>>> bar.__get__(None, Foo)    # access on a class
<function bar at 0x1056f0e18>
>>> bar.__get__(Foo(), Foo)   # access on an instance
<bound method bar of <__main__.Foo object at 0x105833a90>>
>>> bar.__get__(Foo(), Foo).__self__
<__main__.Foo object at 0x105833160>
>>>bar.\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
>>>bar.uu获取(Foo(),Foo)#对实例的访问
>>>酒吧。uuuuuuuuuuuuuuuuuuuuuuuu(Foo(),Foo)。uuuuuu self__
如果访问
ClassObject.classmethod\u object
会像
函数
对象一样返回
classmethod
对象本身,那么您永远无法在类上实际使用class方法。那是毫无意义的


因此,不,
object.attribute
并不总是与
对象相同。如果
object.\uuuu dict\uuu['attribute']
支持描述符协议,将调用它。

不,这不是错误,这是正常行为。当对类进行访问时,
classmethod
生成一个绑定方法。这正是
classmethod
将函数绑定到访问它的类或访问它的实例的类的要点

与函数和
property
对象一样,
classmethod
是一种方法,它实现了一种
\uuuuuuu获取
方法。访问实例或类上的属性被委托给,该钩子的默认实现将不仅仅返回它在
对象中找到的内容;它还将通过调用来绑定描述符。这是Python的一个非常重要的方面,正是这种机制使方法、属性和其他东西的加载工作

classmethod
对象,当被描述符协议绑定时,返回一个方法对象。方法对象是包装器,记录绑定到的对象以及调用它们时要调用的函数;调用一个方法实际上是调用以绑定对象作为第一个参数的基础方法:

>>> class Foo:
...     pass
...
>>> def bar(*args): print(args)
...
>>> classmethod(bar).__get__(None, Foo)  # decorate with classmethod and bind
<bound method bar of <class '__main__.Foo'>>
>>> method = classmethod(bar).__get__(None, Foo)
>>> method.__self__
<class '__main__.Foo'>
>>> method.__func__
<function bar at 0x1056f0e18>
>>> method()
(<class '__main__.Foo'>,)
>>> method('additional arguments')
(<class '__main__.Foo'>, 'additional arguments')
另一方面,函数只希望绑定到实例;因此,如果
\uu get\uu
的第一个参数设置为
None
,它们只返回
self

>>> bar.__get__(None, Foo)    # access on a class
<function bar at 0x1056f0e18>
>>> bar.__get__(Foo(), Foo)   # access on an instance
<bound method bar of <__main__.Foo object at 0x105833a90>>
>>> bar.__get__(Foo(), Foo).__self__
<__main__.Foo object at 0x105833160>
>>>bar.\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
>>>bar.uu获取(Foo(),Foo)#对实例的访问
>>>酒吧。uuuuuuuuuuuuuuuuuuuuuuuu(Foo(),Foo)。uuuuuu self__
如果访问
ClassObject.classmethod\u object
会像
函数
对象一样返回
classmethod
对象本身,那么您永远无法在类上实际使用class方法。那是毫无意义的


因此,不,
object.attribute
并不总是与
对象相同。如果
object.\uuu dict\uuu['attribute']
支持描述符协议,它将被调用。

感谢您的精彩解释,我学到了一些新东西。更新了我的帖子并给出了一个结论。@Jeronimo:很高兴我能帮上忙!不过,我已经将您的附录回滚,因为这并不是未来访问者将要寻找的问题的一部分。如果有帮助的话,我很乐意在我的答案中提供额外的链接。谢谢你的精彩解释,我学到了一些新东西。更新了我的帖子并给出了一个结论。@Jeronimo:很高兴我能帮上忙!不过,我已经将您的附录回滚,因为这并不是未来访问者将要寻找的问题的一部分。如果有帮助的话,我很乐意在我的答案中提供额外的链接。