Documento de modelo de datos de Python: un objeto de método definido por el usuario independiente y un objeto de método de clase

In Modelo de datos of the reference, writer spent lots of effort explaining how Métodos definidos por el usuario are created and operated:(See 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.

Entonces, ¿cuál es la diferencia entre an unbound user-defined method object y la a class method object?

preguntado el 01 de febrero de 12 a las 04:02

1 Respuestas

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:

>>> class A(object):
...   def b(self):
...      pass
...   @classmethod
...   def c(cls):
...      pass
>>> A.b
<unbound method A.b>
>>> A.c
<bound method type.c of <class '__main__.A'>>
>>> A.c()
>>> A.b()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unbound method b() must be called with A instance as first argument (got nothing instead)

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__ (o __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, the property built-in is just a class that implements both __set__, __get__ y la __del__ según sea apropiado.

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, a method.

Por ejemplo:

>>> class B(object):
...    def c(self):
...      pass
...    print c
<function c at 0x1927398>
>>> print B.c
<unbound method B.c>
>>> b = B()
>>> b.c
<bound method B.c of <__main__.B object at 0x1930a10>

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:

>>> B.__dict__["c"]
<function c at 0x1927398>
>>> B.__dict__["c"].__get__
<method-wrapper '__get__' of function object at 0x1927398>
>>> B.__dict__["c"].__get__(b, B)
<bound method B.c of <__main__.B object at 0x1930a10>>
>>> B.__dict__["c"].__get__(None, B)
<unbound method B.c>

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 the cls as the first parameter on call.

Respondido el 10 de diciembre de 13 a las 05:12

so a bound/unbound user-defined method is "Method of an instance", while a classmethod is "Method of an class, right? - Determinante

In other words, if you try call unbound method directly from class you are get exception, and for call this method you must create object at first, and then call method "from" object. If you want call method directly from class you can use decorator @staticmethod - Denis

@Denis Well, when getting the attribute which is a method decorated with @classmethod, can we say that it is a bound method to the class? - Determinante

Yes - it is then a classmethod, bound to the class. - jsbueno

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.