Object method class instance function usage analysis in Python

  • 2020-04-02 14:32:30
  • OfStack

This article analyzes object, method, class, instance, function usage in Python. Share with you for your reference. Specific analysis is as follows:

Python is a fully object-oriented language. Not only are instances objects, classes, functions, and methods objects.

class Foo(object):
    static_attr = True
    def method(self):
        pass
foo = Foo()

This code actually creates two objects, Foo and Foo. And Foo is also a class, and Foo is an instance of that class.
In C++, type definitions are done at compile time, stored in static memory, and cannot be easily modified. In Python, the type itself is an object, stored in the heap like an instance object, and there is no fundamental difference between a class object and an instance object for the interpreter.
Each object in Python has its own namespace. The spatial variables are stored in the object's s s. Thus, the Foo class has one arbitration and the Foo instance has one arbitration, but these are two different namespaces.
By "defining a class", you are essentially forming a class object and then executing a piece of code with the local namespace set as the class's s. So you can write code like this:
>>> class Foo(object):
...     bar = 1 + 1
...     qux = bar + 1
...     print "bar: ", bar
...     print "qux: ", qux
...     print locals()
...
bar:  2
qux:  3
{'qux': 3, '__module__': '__main__', 'bar': 2}
>>> print Foo.bar, Foo.__dict__['bar']
2 2
>>> print Foo.qux, Foo.__dict__['qux']
3 3

To "define a function" is to generate a function object. And "define a method" is generating one
S function object and place this object in the s/s of a class. The forms of the following two definitions are equivalent:

>>> class Foo(object):
...     def bar(self):
...         return 2
...
>>> def qux(self):
...     return 3
...
>>> Foo.qux = qux
>>> print Foo.bar, Foo.__dict__['bar'] >>> print Foo.qux, Foo.__dict__['qux'] >>> foo = Foo()
>>> foo.bar()
2
>>> foo.qux()
3

Class inheritance simply defines two class objects, each with a different type of arbitration:

>>> class Cheese(object):
...     smell = 'good'
...     taste = 'good'
...
>>> class Stilton(Cheese):
...     smell = 'bad'
...
>>> print Cheese.smell
good
>>> print Cheese.taste
good
>>> print Stilton.smell
bad
>>> print Stilton.taste
good
>>> print 'taste' in Cheese.__dict__
True
>>> print 'taste' in Stilton.__dict__
False

The complication is on the operator '. '. For classes, Stilton. Taste means "find 'taste' in Stilton. S. S. S... S... S............................ If the object is still not found, throw an AttributeError."
The instance also has its own arbitration arbitration system:

>>> class Cheese(object):
...     smell = 'good'
...     taste = 'good'
...     def __init__(self, weight):
...         self.weight = weight
...     def get_weight(self):
...         return self.weight
...
>>> class Stilton(Cheese):
...     smell = 'bad'
...
>>> stilton = Stilton('100g')
>>> print 'weight' in Cheese.__dict__
False
>>> print 'weight' in Stilton.__dict__
False
>>> print 'weight' in stilton.__dict__
True

Stilton. S. S. S. S. T. S. S. S. S.
Cheese. Weight and Stilton. Weight both fail because neither of them touches the instance namespace. while
Stilton. Weight is in the order stilton. S > Stilton. __dict__ = >
Cheese. __dict__ = > This is very similar to the order of Stilton. Taste, only
There's an extra step in the front.

The method is a little more complicated.

>>> print Cheese.__dict__['get_weight']
>>> print Cheese.get_weight
>>> print stilton.get_weight
<__main__.Stilton object at 0x7ff820669190>>

We can see that the dot operator turns function into unbound method.calls functions and points directly from the class namespace
The unbound method returned by the operation will get a different error:
>>> Cheese.__dict__['get_weight']()
Traceback (most recent call last):
  File "", line 1, in
TypeError: get_weight() takes exactly 1 argument (0 given)
>>> Cheese.get_weight()
Traceback (most recent call last):
  File "", line 1, in
TypeError: unbound method get_weight() must be called with Cheese instance as
first argument (got nothing instead)

But these two errors say the same thing, that an instance method needs an instance. A "bound method" simply takes an instance object as the first argument when a method is called. The following methods are equivalent:
>>> Cheese.__dict__['get_weight'](stilton)
'100g'
>>> Cheese.get_weight(stilton)
'100g'
>>> Stilton.get_weight(stilton)
'100g'
>>> stilton.get_weight()
'100g'

The last is the usual call, stilton.get_weight(), which is another function of the point operator, which translates stilton.get_weight() to stilton.get_weight().
In this way, the method invocation actually has two steps. First, find get_weight with the rules of the property lookup, then call the property as a function, with the instance object as the first argument. There is no connection between the two steps. For example, you could try this:
>>> stilton.weight()
Traceback (most recent call last):
  File "", line 1, in
TypeError: 'str' object is not callable

Look up the weight property, and then call weight as a function. But weight is a string, so there's an error. Note that here the property lookup starts with the instance:
>>> stilton.get_weight = lambda : '200g'
>>> stilton.get_weight()
'200g'

but
>>> Stilton.get_weight(stilton)
'100g'

The search for stilton.get_weight skieves the instance object Stilton, so it finds a method defined in Cheese that is not overwritten.

Getattr (stilton, 'weight') and stilton. Weight are equivalent. There is no essential difference between a class object and an instance object; getattr(Cheese, 'smell') and cheese.smell are equally equivalent. The advantage of getattr() over the point operator is that the property name is specified in a string and can be changed at run time.

Arbitration getattribute__() is the lowest level of code. If you don't redefine this method, object.getattribute__ () and type.getattribute__ () are the concrete implementations of getattr(), the former for instance and the latter for class. In other words, stilton. Weight is object.getattribute__ (stilton, 'weight'). Overriding this method is very error prone. For example, the point operator causes infinite recursion:

def __getattribute__(self, name):
        return self.__dict__[name]

There are other details in arbitration (), such as the implementation of descriptor protocol, which is easy to get wrong if you override it.

S/s/s/s/s/s/s/s/s/s/s/s/s/s/s/s/s/s/s/s. This is generally used for dynamic generation of attributes, as s 'getattr__ () does not interfere with the attributes defined elsewhere that are placed in s 'ral.

>>> class Cheese(object):
...     smell = 'good'
...     taste = 'good'
...
>>> class Stilton(Cheese):
...     smell = 'bad'
...     def __getattr__(self, name):
...         return 'Dynamically created attribute "%s"' % name
...
>>> stilton = Stilton()
>>> print stilton.taste
good
>>> print stilton.weight
Dynamically created attribute "weight"
>>> print 'weight' in stilton.__dict__
False

Since the method is simply an attribute that can be called as a function, s getattr__() can also be used to dynamically generate the method, but again note the infinite recursion:
>>> class Cheese(object):
...     smell = 'good'
...     taste = 'good'
...     def __init__(self, weight):
...         self.weight = weight
...
>>> class Stilton(Cheese):
...     smell = 'bad'
...     def __getattr__(self, name):
...         if name.startswith('get_'):
...             def func():
...                 return getattr(self, name[4:])
...             return func
...         else:
...             if hasattr(self, name):
...                 return getattr(self, name)
...             else:
...                 raise AttributeError(name)
...
>>> stilton = Stilton('100g')
>>> print stilton.weight
100g
>>> print stilton.get_weight >>> print stilton.get_weight()
100g
>>> print stilton.age
Traceback (most recent call last):
  File "", line 1, in
  File "", line 12, in __getattr__
AttributeError: age

I hope this article has helped you with your Python programming.


Related articles: