Analysis of object, method, class, instance, and function usage in Python

Source: Internet
Author: User
This article mainly introduces the usage of objects, methods, classes, instances, and functions in Python, and analyzes the usage skills of objects, methods, classes, instances, and functions from the object-oriented perspective, it has some reference value. if you need it, you can refer to the examples in this article to analyze Python objects, methods, classes, instances, and function usage. Share it with you for your reference. The specific analysis is as follows:

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

The code is as follows:

Class Foo (object ):
Static_attr = True
Def method (self ):
Pass
Foo = Foo ()


This code actually creates two objects: Foo and foo. Foo is also a class, and foo is an instance of this class.
In C ++, the type definition is completed during compilation and stored in static memory and cannot be modified easily. In Python, the type itself is an object, which is stored in the heap like the instance object. for the interpreter, the class object and the instance object have no fundamental difference.
In Python, each object has its own namespace. The variables in the space are stored in _ dict _ of the object. In this way, the Foo class has a _ dict __, and the foo instance also has a _ dict __, but this is two different namespaces.
The so-called "define a class" is actually a class object, and then execute a piece of code, but set the local namespace when executing this code to the _ dict _ of the class __. you can write the following code:

The code is as follows:

>>> 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

The so-called "defining a function" is actually generating a function object. "Defining a method" is to generate
And put this object in _ dict _ of a class. The following two methods are equivalent:

The code is as follows:

>>> 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 with different _ dict __:

The code is as follows:

>>> 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 complexity lies in the '.' operator. Stilton. taste means "in Stilton. in _ dict _, find 'taste '. if not, go to _ dict _ of the parent Cheese class, and then to the parent class of the parent class. If the object is still not found, an AttributeError will be thrown ."
The instance also has its own _ dict __:

The code is as follows:

>>> 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

No matter where _ init _ () is defined, stilton. _ dict _ has nothing to do with _ dict _ of the class.
Cheese. weight and Stilton. weight both have errors because they cannot touch the namespace of the instance. While
The search sequence of stilton. weight is stilton. _ dict _ => Stilton. _ dict _ =>
Cheese. _ dict _ => object. _ dict _. this is very similar to the search sequence of Stilton. taste, just
There is one more step at the beginning.

The method is slightly more complex.

The code is as follows:

>>> Print Cheese. _ dict _ ['get _ weight ']

>>> Print Cheese. get_weight

>>> Print stilton. get_weight
<__Main _. Stilton object at 0x7ff820669190>


We can see that the vertex operator converts the function into the unbound method. it directly calls the functions and vertices of the class namespace.
The unbound method returned by the operation will get different errors:

The code is as follows:

>>> 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
First argument (got nothing instead)


But these two errors are the same thing. the instance method requires an instance. The so-called "binding method" means simply using an instance object as the first parameter when calling a method. The following call methods are equivalent:

The code is as follows:

>>> Cheese. _ dict _ ['get _ weight '] (stilton)
'100g'
>>> Cheese. get_weight (stilton)
'100g'
>>> Stilton. get_weight (stilton)
'100g'
>>> Stilton. get_weight ()
'100g'


The last method is the common call method, stilton. get_weight () is another function of the vertex operator. get_weight () is translated into stilton. get_weight (stilton ).
In this way, there are actually two steps to call a method. First, use the property search rule to find get_weight, then use this property as a function call, and take the instance object as the first parameter. There is no connection between the two steps. For example, you can try it like this:

The code is as follows:

>>> Stilton. weight ()
Traceback (most recent call last ):
File "", line 1, in
TypeError: 'str' object is not callable


First Look for the weight attribute, and then use weight as a function call. However, weight is a string, so an error occurs. Note that attribute search starts from the instance:

The code is as follows:

>>> Stilton. get_weight = lambda: '200g'
>>> Stilton. get_weight ()
'200g'


However

The code is as follows:

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


The search for Stilton. get_weight skips the instance object stilton, so the searched method is not overwritten and defined in Cheese.

Getattr (stilton, 'weight ') is equivalent to stilton. weight. There is no essential difference between class objects and instance objects. getattr (Cheese, 'smel') and Cheese. smell are also equivalent. Compared with the vertex operator, getattr () has the advantage that the attribute name is specified by a string and can be changed at runtime.

_ Getattribute _ () is the underlying code. If you do not redefine this method, object. _ getattribute _ () and type. _ getattribute _ () is the specific implementation of getattr (). The former is used for instances, and the latter is used for classes. In other words, stilton. weight is object. _ getattribute _ (stilton, 'weight'). It is very error-prone to overwrite this method. For example, the vertex operator causes infinite recursion:

The code is as follows:

Def _ getattribute _ (self, name ):
Return self. _ dict _ [name]


There are other details in _ getattribute _ (), such as the implementation of the descriptor protocol. if it is rewritten, it is easy to make a mistake.

_ Getattr _ () is the method called When _ dict _ is not found. Generally, this attribute is used for dynamic generation, because _ getattr _ () does not interfere with the attribute defined elsewhere in _ dict.

The code is as follows:

>>> 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 a method can only be used as an attribute for function calling, __getattr _ () can also be used to dynamically generate a method, but also pay attention to infinite recursion:

The code is as follows:

>>> 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
100 GB
>>> Print stilton. get_weight

>>> Print stilton. get_weight ()
100 GB
>>> Print stilton. age
Traceback (most recent call last ):
File "", line 1, in
File "", line 12, in _ getattr __
AttributeError: age

I hope this article will help you with Python programming.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.