Home  >  Article  >  Backend Development  >  Detailed explanation of python magic method

Detailed explanation of python magic method

高洛峰
高洛峰Original
2016-10-20 09:22:141268browse

Preparation

To ensure that the class is a new type, you should put _metaclass_=type at the beginning of your module.

class NewType(Object):
  mor_code_here
class OldType:
  mor_code_here


Among these two classes, NewType is the new class and OldType belongs to the old class. If _metaclass_=type is added in front, then both classes belong to the new class.

Constructor

Constructor is different from its method. When an object is created, the constructor will be called immediately. Creating a Python constructor is very simple. Just convert the init method from the simple init method to the magic version of the _init_ method.

class FooBar:
    def __init__(self):
        self.somevar = 42
          
>>> f =FooBar()
>>> f.somevar
42


Override a general method

Every class may have one or more superclasses (parent classes), and they inherit behavior methods from the superclasses.

class A:
    def hello(self):
        print 'hello . I am A.'
class B(A):
  pass
>>> a = A()
>>> b = B()
>>> a.hello()
hello . I am A.


Because class B does not have a hello method and class B inherits class A, the hello method of class A will be called.

The most basic way to add functionality to a subclass is to add methods. But you can also override some superclass methods to customize inherited behavior. As follows:

class A:
    def hello(self):
        print 'hello . I am A.'
class B(A):
    def hello(self):
        print 'hello . I am  B'
>>> b = B()
>>> b.hello()
hello . I am  B


Special and constructor methods

Overriding is an important part of the inheritance mechanism, especially for constructors. Look at the following example:

class Bird:
    def __init__(self):
        self.hungry = True
    def eat(self):
        if self.hungry:
            print 'Aaaah...'
            self.hungry = False
        else:
            print 'No, thanks!'
>>> b = Bird()
>>> b.eat()
Aaaah...
>>> b.eat()
No, thanks!


This class defines the bird’s ability to eat. After it eats once, it will no longer be hungry again. You can clearly see it through the above execution results.

Then use the SongBird class to inherit the Bird class and add the singing method to it:

class Bird:
    def __init__(self):
        self.hungry = True
    def eat(self):
        if self.hungry:
            print 'Aaaah...'
            self.hungry = False
        else:
            print 'No, thanks!'
              
class SongBird(Bird):
         def __init__(self):
                 self.sound = 'Squawk!'
         def sing(self):
                 print self.sound
>>> s = SongBird()
>>> s.sing()
Squawk!
>>> s.eat()
Traceback (most recent call last):
  File "<pyshell#26>", line 1, in <module>
    s.eat()
  File "C:/Python27/bird", line 6, in eat
    if self.hungry:
AttributeError: &#39;SongBird&#39; object has no attribute &#39;hungry&#39;


The exception clearly illustrates the error: SongBird does not have the hungry feature. The reason is this: in SongBird, the constructor is rewritten, but the new constructor does not have any code about initializing the hungry properties. In order to achieve the desired effect, the constructor of SongBird must call the constructor of its superclass Bird to ensure basic initialization.

Two methods to implement:

1. Call the unbound superclass constructor

class Bird:
    def __init__(self):
        self.hungry = True
    def eat(self):
        if self.hungry:
            print &#39;Aaaah...&#39;
            self.hungry = False
        else:
            print &#39;No, thanks!&#39;
              
class SongBird(Bird):
         def __init__(self):
                 Bird.__init__(self)
                 self.sound = &#39;Squawk!&#39;
         def sing(self):
                 print self.sound
>>> s = SongBird()
>>> s.sing()
Squawk!
>>> s.eat()
Aaaah...
>>> s.eat()
No, thanks!


Add a line of code Bird.__init__(self) to the SongBird class. When a method on an instance is called, the method's self parameter is automatically bound to the instance (this is called a bound method). But if you call the class method directly, then no instance will be bound. This allows you to freely provide the required self parameters (such methods are called unbound methods).

By providing the current instance as the self parameter to the unbound method, SongBird can use all implementations of its superclass constructor, which means that the hungry attribute can be set.

2. Use the super function

__metaclass__ = type  #表明为新式类
class Bird:
    def __init__(self):
        self.hungry = True
    def eat(self):
        if self.hungry:
            print &#39;Aaaah...&#39;
            self.hungry = False
        else:
            print &#39;No, thanks!&#39;
              
class SongBird(Bird):
         def __init__(self):
                 super(SongBird,self).__init__()
                 self.sound = &#39;Squawk!&#39;
         def sing(self):
                 print self.sound
>>> s.sing()
Squawk!
>>> s.eat()
Aaaah...
>>> s.eat()
No, thanks!


The super function can only be used in new-style classes. The current class and object can be used as parameters of the super function. Any method that calls the object returned by the function calls the method of the super class, not the current class. Then you can use super(SongBird, self) directly instead of using Bird in the constructor of SongBird.

Property

The accessor is a simple method that can use names like getHeight and setHeight to get or rebind some properties. Encapsulating state variables like this is important if some action must be taken when a given feature is accessed. As follows:

class Rectangle:
    def __init__(self):
        self.width = 0
        self.height = 0
    def setSize(self,size):
        self.width , self.height = size
    def getSize(self):
        return self.width , self.height
>>> r = Rectangle()
>>> r.width = 10
>>> r.height = 5
>>> r.getSize()
(10, 5)
>>> r.setSize((150,100))
>>> r.width
150


In the above example, the getSize and setSize methods are accessor methods of an imaginary property called size, where size is a tuple consisting of width and height.

property function

property function is very simple to use. If you have already written a class like Rectangle in the previous section, then just add a line of code:

__metaclass__ = type
class Rectangle:
    def __int__(self):
        self.width = 0
        self.height = 0
    def setSize(self,size):
        self.width, self.height = size
    def getSize(self):
        return self.width ,self.height
    size = property(getSize ,setSize)
>>> r = Rectangle()
>>> r.width = 10
>>> r.height = 5
>>> r.size
(10, 5)
>>> r.size = 150,100
>>> r.width
150


In this new version of Retangle , the property function creates a property in which the accessor function is used as a parameter (first gets the value, then assigns the value), and the property is named size. This way you no longer need to worry about how it is implemented, you can handle width, height and size in the same way.


Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn