Python数据模型文档:未绑定的用户定义方法对象和类方法对象
在参考资料的数据模型中,作者花了很多精力解释用户定义的方法是如何创建和操作的:(参见http://docs.python.org/reference/datamodel.html#the-standard-type-hierarchy 并向下滚动)
获取属性时可能会创建用户定义的方法对象 一个类的(也许通过该类的一个实例),如果 attribute 是一个用户定义的函数对象,一个未绑定的用户定义 方法对象,或类方法对象。当属性是 用户定义的方法对象,只有在以下情况下才会创建新的方法对象 从中检索它的类与它相同或派生 class of,原方法对象中存储的类;否则, 原始方法对象按原样使用。
那么未绑定的用户定义方法对象和类方法对象有什么区别呢?
In Data Model of the reference, writer spent lots of effort explaining how User-defined methods are created and operated:(See http://docs.python.org/reference/datamodel.html#the-standard-type-hierarchy and roll down)
User-defined method objects may be created when getting an attribute
of a class (perhaps via an in- stance of that class), if that
attribute is a user-defined function object, an unbound user-defined
method object, or a class method object. When the attribute is a
user-defined method object, a new method object is only created if the
class from which it is being retrieved is the same as, or a derived
class of, the class stored in the original method object; otherwise,
the original method object is used as it is.
So what's the difference between an unbound user-defined method object and a class method object?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
从“用户”的角度来看,Python 中的类方法是一种接收其类作为其第一个参数的方法 - 与接收类的实例作为其第一个参数的“普通”方法不同 - 按照惯例称为
自我。
如果您从类中检索“普通”方法,而不是从该类的实例中检索,您将获得“未绑定方法” - 即作为函数包装器的对象,但不会自动添加类本身,也没有任何实例作为调用时的第一个参数。因此,如果要调用“未绑定方法”,则必须手动传递其类的实例作为其第一个参数。
另一方面,如果您手动调用类方法,则该类将作为您的第一个参数填写:
在幕后,或多或少是这样的 - 使用“新样式类”:
当定义类主体时,这些方法只是普通函数 - 当类主体结束时,Python 调用类的元类(通常是内置
type
) - 并将名称、基类和类作为参数传递给它身体词典。这个调用产生一个类——在Python中,它是一个对象,它是一个类,因为一切都是对象。现在,Python 有一些自定义属性访问的巧妙方法 - 所谓的“描述符”。描述符是定义名为
__get__
的方法的任何对象(或__set__
或__del__
但我们在这里不关心这些)。当在 Python 中访问类或对象的属性时,将返回该属性引用的对象 - 除非它是类属性,并且该对象是描述符。在这种情况下,Python 不会返回对象本身,而是调用该对象的 __get__ 方法,并返回其结果。例如,内置的property
只是一个根据需要实现__set__
、__get__
和__del__
的类。现在,检索属性时会发生的情况是,其主体上的任何函数(或类方法或未绑定方法,如数据模型所述)确实具有
__get__
方法,这使其成为描述符。基本上,一个描述符在每个属性访问中检索在函数体上定义的名为函数的对象,围绕该函数创建一个新对象 - 一个在调用时将自动填充第一个参数的对象 - 这是也就是说,一个方法
。例如:
如果你想检索函数对象,而不转换为方法对象,你可以通过类的
__dict__
属性来实现,这不会触发描述符:至于“类方法”,这些只是不同类型的对象,它们显式地用内置的
classmethod
修饰 - 调用其__get__
时返回的对象是原始函数的包装器,该函数将填充在cls
中作为调用时的第一个参数。From the "user" point of view, a class method in Python is a method that receives its class as its first parameter - unlike "ordinary" methods which receive an instance of the class as its first parameter - which by convention is called
self
.If you retrieve an "ordinary" method from a class, instead of from an instace of that class, you get an "unbound method" - i.e. an object that is a wrapper around a function, but that does not automatically adds either the class itself, nor any instance as the first parameter when it is called. Threfore if you are to call the "unbound method" you have to manually pass an instance of its class as its first parameter.
If you manually call a class method, on the other hand, the class is filled in as the first parameter for you:
Under the hood what goes is more or less like this - with "new style classes":
When one defines a class body, the methods are just ordinary functions - when the class body is over, Python calls the class's metaclass (which ordinarily is the builtin
type
) - and pass to it as parameters the name, base classes, and class body dictionary. This call yields a class - which in Python is, an object which is a class, since everything is an object.Now, Python has some nifty ways of customizing attribute access - the so called "descriptors". A descriptor is any object that defines a method named
__get__
(or__set__
or__del__
but we don't care about those here). When one access an attribute of a class or object in Python, the object referred by that attribute is returned - except if it is a class attribute, and the object is a descriptor. In that case, instead of returning the object itself, Python calls the__get__
method on that object, and returns its results instead. For example, theproperty
built-in is just a class that implements both__set__
,__get__
and__del__
as appropriate.Now, what happens when the attribute is retrieved, is that any function (or class method or unbound method, as the data model states) on its body, does have a
__get__
method, which makes it a descriptor. Basically, a descriptor that at each attribute access to retrieve the object named as the function as it is defined on the function body, creates a new object around that function - an object that when called will have the first parameter automatically filled in - which is to say, amethod
.Ex.:
If you want to retrieve the function object, without conversion to a method object, you can do so through the class's
__dict__
attribute, which does not trigger the descriptor:As for "class methods", these are just different type of objects, which are explicitly decorated with the builtin
classmethod
- The object it returns when its__get__
is called is a wrapper around the original function that will fill in thecls
as the first parameter on call.