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

Source: Internet
Author: User
In this paper, we analyze the object, method, class, instance and function usage of Python. Share to everyone for your reference. The specific analysis is as follows:

Python is a fully object-oriented language. Not only the instances are objects, classes, functions, methods are also objects.
Copy the 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 example of this class.
In C + + the type definition is done at compile time and is 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 a class object and an instance object for the interpreter.
Each object in Python has its own namespace. The variables in the space are stored in the __dict__ of the object. Thus, 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 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 CodeThe 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. And "Defining a method" is to generate a
function object, and place the object in the __dict__ of a class. The following two ways of defining the method are equivalent:
Copy the 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 simply defines two classes of objects, each with a different __dict__:
Copy the 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. For classes, stilton.taste means "find ' taste ' in stilton.__dict__." If not found, go to the parent class cheese __dict__ to find, then to the parent class, and so on. If the object is still not found, throw a attributeerror. "
Examples also have their own __dict__:
Copy the 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 will go wrong, because neither of these can touch the instance's namespace. and
The Stilton.weight search order is stilton.__dict__ = stilton.__dict__ =
cheese.__dict__ = object.__dict__. This is very similar to Stilton.taste's lookup order, just
One more step in the front.

method is slightly more complicated.
Copy the 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 function into unbound method. Functions and points that call the class namespace directly
The unbound method returned by the operation gets a different error:
Copy CodeThe code is as follows:

>>> cheese.__dict__[' Get_weight '] ()
Traceback (most recent):
File "", Line 1, in
Typeerror:get_weight () takes exactly 1 argument (0 given)
>>> Cheese.get_weight ()
Traceback (most recent):
File "", Line 1, in
Typeerror:unbound method Get_weight () must is called with Cheese instance as
First argument (got nothing instead)


But the two errors say one thing, the instance method needs an instance. The so-called "binding method" simply takes an instance object as the first parameter when invoking a method. The following invocation methods are equivalent:
Copy CodeThe 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 type of invocation, Stilton.get_weight (), is another function of the dot operator that translates stilton.get_weight () into Stilton.get_weight (Stilton).
In this way, the method call actually has two steps. First find the get_weight with the rule of the property lookup, then call this property as a function, and use the instance object as the first parameter. There is no connection between the two steps. For example, you can try this:
Copy CodeThe code is as follows:

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


Look for the weight property first, and then make weight the function call. But weight is a string, so an error occurs. Note here that the property lookup starts from the instance:
Copy CodeThe code is as follows:

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


But
Copy CodeThe code is as follows:

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


Stilton.get_weight's Lookup skips 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 benefit of getattr () is that the property name is specified in a string and can be changed at run time, compared to the dot operator.

__GETATTRIBUTE__ () is the lowest-level code. If you do not redefine this method, object.__getattribute__ () and type.__getattribute__ () are the concrete implementations of getattr (), the former used for the instance, the latter for the class. In other words, Stilton.weight is object.__getattribute__ (Stilton, ' weight '). Overwriting this method is very error-prone. For example, the dot operator causes infinite recursion:
Copy the Code code as follows:

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


There are other details in __getattribute__ (), such as the implementation of descriptor protocol, which can be easily mistaken if overridden.

__getattr__ () is a method that is called when the __dict__ lookup is not found. This is generally the dynamic generation of properties, because __getattr__ () does not interfere with attributes that are defined elsewhere in the __dict__.
Copy the Code code 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


Because the method is simply a property that can be called as a function, __getattr__ () can also be used to dynamically generate methods, but also pay attention to infinite recursion:
Copy CodeThe 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
100g
>>> Print Stilton.get_weight

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

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