Object, method, class, instance, function usage analysis in Python _python

Source: Internet
Author: User
Tags instance method

This article analyzes the objects, methods, classes, instances, and function usages in Python. Share to everyone for your reference. The specific analysis is as follows:

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

Copy Code code 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 + +, type definitions are done at compile time and are stored in static memory and cannot be easily modified. In Python the type itself is an object, stored in the heap as an instance object, and there is no fundamental difference between the class object and the instance object for the interpreter.
In Python, each object has its own namespace. The variables within the space are stored in the __dict__ of the object. This way, the Foo class has a __dict__, and the Foo instance also has a __dict__, but this is two different namespaces.
The term "Define a class" is actually a class object, then executes a piece of code, but sets the local namespace that executes the code to the __dict__ of the class. So you can write code like this:
Copy Code code 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

So-called "Defining a function" is actually generating a function object. And "Define a method" is to generate a
function object and place the object in the __dict__ of a class. The following two forms of defined methods are equivalent:

Copy Code code 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 is a simple definition of two class objects, each with a different __dict__:

Copy Code code 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 complex place is on the operator of '. '. For a class, stilton.taste means "find ' taste ' in stilton.__dict__." If not, go to the parent class cheese __dict__, and then to the parent class, and so on. If the object is still not found, then throw a attributeerror.
The example also has its own __dict__:

Copy Code code 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

Regardless of where __init__ () is defined, stilton.__dict__ has nothing to do with the __dict__ of the class.
Both Cheese.weight and stilton.weight are wrong because neither of them can touch the namespace of the instance. and
The Stilton.weight lookup order is stilton.__dict__ => stilton.__dict__ =>
cheese.__dict__ => object.__dict__. This is very similar to the stilton.taste search order, just
One more step in the front.

The method is slightly more complicated.

Copy Code code 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 dot operator turns the function into unbound method. Functions and points that call a class namespace directly
The unbound method returned by the operation will get a different error:
Copy Code code 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 is called with Cheese instance as
The argument (got nothing instead)

But these two errors are the same thing, the instance method requires an instance. The so-called "binding method" simply takes an instance object as the first argument when invoking a method. The following invocation methods are equivalent:
Copy Code code as follows:
>>> cheese.__dict__[' get_weight '] (Stilton)
' 100g '
>>> Cheese.get_weight (Stilton)
' 100g '
>>> Stilton.get_weight (Stilton)
' 100g '
>>> Stilton.get_weight ()
' 100g '

The last one is the usual invocation, stilton.get_weight (), another function of the dot operator, which translates stilton.get_weight () into Stilton.get_weight (Stilton).
In this way, the method call actually has two steps. First find get_weight with the rule of attribute lookup, then call this property as a function and take the instance object as the first parameter. There is no connection between the two steps. For example, you can try this:
Copy Code code as follows:
>>> Stilton.weight ()
Traceback (most recent call last):
File "", Line 1, in
TypeError: ' str ' object is not callable

Find the Weight property first, and then make the weight a function call. But weight is a string, so there is an error. Notice that the attribute lookup starts here from the instance:
Copy Code code as follows:
>>> stilton.get_weight = lambda: ' 200g '
>>> Stilton.get_weight ()
' 200g '

But
Copy Code code as follows:
>>> Stilton.get_weight (Stilton)
' 100g '

The Stilton.get_weight lookup skips the instance object Stilton, so it finds a method that is not overwritten and defined in cheese.

GetAttr (Stilton, ' weight ') and stilton.weight are equivalent. There is no essential difference between a class object and an instance object, and GetAttr (Cheese, ' smell ') and Cheese.smell are equally equivalent. The advantage of GetAttr () is that the property name is specified with a string and can be changed at run time.

__GETATTRIBUTE__ () is the lowest code. If you do not redefine this method, object.__getattribute__ () and type.__getattribute__ () are the concrete implementations of GetAttr (), which are used for instances and the latter for classes. In other words, Stilton.weight is object.__getattribute__ (Stilton, ' weight '). Overwriting this method is prone to error. For example, the dot operator can cause infinite recursion:

Copy Code code as follows:
def __getattribute__ (self, name):
return Self.__dict__[name]

__GETATTRIBUTE__ () also has other details, such as the implementation of descriptor protocol, if the rewrite is easy to get wrong.

__getattr__ () is a method that is invoked when the __dict__ lookup is not found. In general, dynamically generated properties are used because __getattr__ () does not interfere with attributes that are defined elsewhere in the __dict__.

Copy Code code as follows:
>>> class Cheese (object):
... smell = ' good '
... taste = ' good '
...
>>> class Stilton (Cheese):
... smell = ' bad '
... def __getattr__ (self, name):
... return ' dynamically created '%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 a property that can be invoked as a function, __getattr__ () can also be used to dynamically generate the method, but the same attention is given to infinite recursion:
Copy Code code 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
100g
>>> Print Stilton.get_weight

>>> Print stilton.get_weight ()
100g
>>> Print Stilton.age
Traceback (most recent call last):
File "", Line 1, in
File "", Line, in __getattr__
Attributeerror:age

I hope this article will help you with your 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.