An example is used to analyze the parameter passing process of method in Python

  • 2020-05-05 11:23:56
  • OfStack

What is ?

function is a piece of code that can be called by name, and we can pass in parameters to get the return value. All parameters are passed explicitly.
method is a combination of function and objects. When we call a method, some arguments are passed implicitly. More on that later.
instancemethod
 


In [5]: class Human(object):
  ...:   def __init__(self, weight):
  ...:     self.weight = weight
  ...:   def get_weight(self):
  ...:     return self.weight
  ...:  
 
In [6]: Human.get_weight
Out[6]: <unbound method Human.get_weight>

This tells us that get_weight is an unbound method. What is unbound? Keep reading.
 


In [7]: Human.get_weight()
---------------------------------------------------------------------------
TypeError                 Traceback (most recent call last)
/home/yao/learn/insight_python/<ipython-input-7-a2b2c5cd2f8d> in <module>()
----> 1 Human.get_weight()
 
TypeError: unbound method get_weight() must be called with Human instance as first argument (got nothing instead)

An unbound method must be called with an Human instance as its first argument. So let's try
 


In [10]: Human.get_weight(Human(45))
Out[10]: 45

It worked, but we're used to it in general.
 


In [11]: person = Human(45)
 
In [12]: person.get_weight()
Out[12]: 45

The results are exactly the same. Let's take a look at the official documentation to explain this phenomenon.
 
When an instance attribute is referenced that isn't a data attribute, its class is searched.
If the name denotes a valid class attribute that is a function object, a method object is
created by packing (pointers to) the instance object and the function object just found together
in an abstract object: this is the method object. When the method object is called with an
argument list, a new argument list is constructed from the instance object and the argument list,
and the function object is called with this new argument list.

The usual call method (person.get_weight ()) passed the called instance hidden as a parameter self, self is just an ordinary parameter name, not a keyword.
 


In [13]: person.get_weight
Out[13]: <bound method Human.get_weight of <__main__.Human object at 0x8e13bec>>
 
In [14]: person
Out[14]: <__main__.Human at 0x8e13bec>

We see that get_weight is bound to the person instance object.
summarizes

      instance method is a combination of instance objects and functions.       USES a class call, with the first parameter explicitly passed to an instance.       is called using an instance, which is implicitly passed as the first parameter.

classmethod
 


In [1]: class Human(object):
  ...:   weight = 12
  ...:   @classmethod
  ...:   def get_weight(cls):
  ...:     return cls.weight
 
In [2]: Human.get_weight
Out[2]: <bound method type.get_weight of <class '__main__.Human'>>

We see that get_weight is an method bound to the Human class. So let's call
 


In [3]: Human.get_weight()
Out[3]: 12
In [4]: Human().get_weight()
Out[4]: 12

Both the class and the instance of the class can call get_weight and the result is exactly the same.
We see that weight is a property of the Human class, and of course an instance of Human. Is cls a class or an instance?
 


In [1]: class Human(object):
  ...:   weight = 12
  ...:   @classmethod
  ...:   def get_weight(cls):
  ...:     print cls
 
In [2]: Human.get_weight()
<class '__main__.Human'>
 
In [3]: Human().get_weight()
<class '__main__.Human'>

We see that all the objects passed are Human classes, not instances of Human, and the results are no different. cls is just a normal function parameter that is implicitly passed when called.
summed up

      classmethod is a combination of class objects and functions.       can be called with classes and instances of classes, but both pass the class as an implicit parameter.       avoids the overhead of instantiating a class by calling classmethod with a class.

staticmethod
 


In [1]: class Human(object):
  ...:   @staticmethod
  ...:   def add(a, b):
  ...:     return a + b
  ...:   def get_weight(self):
  ...:     return self.add(1, 2)
 
In [2]: Human.add
Out[2]: <function __main__.add>
 
In [3]: Human().add
Out[3]: <function __main__.add>
 
In [4]: Human.add(1, 2)
Out[4]: 3
 
In [5]: Human().add(1, 2)
Out[5]: 3

We see that add is just a normal function on both classes and instances, and is not bound to any particular class or instance. It can be called using a class or an instance of a class without any implicit arguments being passed in.
 


In [6]: Human().add is Human().add
Out[6]: True
 
In [7]: Human().get_weight is Human().get_weight
Out[7]: False

add is also the same object on both instances. instancemethod, on the other hand, creates a new get_weight object each time.
summarizes

      is used when a function logically belongs to a class but does not depend on its properties. Using       avoids the overhead of creating an object every time you use staticmethod.       staticmethod can be invoked using classes and instances of classes. But it does not depend on the state of the class and its instances.

Related articles: