Python Magic method

Source: Internet
Author: User

Isinstance and Issubclass

Isinstance (obj,cls) checks if obj is an object of class CLS

Class Foo (object):    passobj = Foo () print (Isinstance (obj, Foo)) # True

Issubclass (sub, super) check if the sub class is a derived class of super class

Class Foo (object):    passclass Bar (Foo):    passprint (Issubclass (Bar,foo)) # True
Two secondary processing standard type (packing)

Packaging: Python provides standard data types and a rich set of built-in methods, but in many scenarios we need to customize our own data types based on standard data types.

New/rewritten method, which uses the inheritance/derivation knowledge we just learned (other standard types can be processed two times in the following way)

Class List: #继承list所有的属性, you can also derive your own new, such as Append and mid    def append (self,p_object):        if Isinstance (P_object, int):            raise TypeError (' must is int ')        super (). Append (p_object)    @property    def mid (self):        ' Add your own property '        index = len (self)//2        return self[index]l=list ([1,2,3,4]) print (L) l.append (5) print (L) # l.append (' 1111111 ') #报错, the Int type print (L.MID) must #其余的方法都继承list的l. Insert (0,-123) print (L) l.clear () print (L)
__getattr__ and __getattribute__

Object.__getattr__ (self, name)
When attribute is not found in the general position, GetAttr is called, returning a value or Attributeerror exception.

Import Timeclass filehandle:    def __init__ (self,filename,mode= ' R ', encoding= ' Utf-8 '):        Self.file=open ( filename,mode,encoding=encoding)    def write (self,line):        t=time.strftime ('%y-%m-%d%T ')        Self.file.write ('%s%s '% (t,line))    def __getattr__ (self, item):        print (' Execute __getattr__item%s '%item)        Return GetAttr (Self.file,item) f1=filehandle (' B.txt ', ' w+ ') f1.write (' Hello ') f1.seek (0) # Execute __getattr__item seekprint ( F1.read ()) # executed __getattr__item  read 2018-06-11 21:04:32 Hello F1.close () # Execute __getattr__item Close
F1.xxxxxx #不存在的属性访问, triggering __getattr__

object.__getattribute__ (self, name)
is called unconditionally, accessing properties through an instance. If __getattr__ () is defined in class, __getattr__ () is not called (unless the call is displayed or the Attributeerror exception is thrown)

Class Foo:    def __init__ (self,x):        self.x=x    def __getattribute__ (self, item):        print (' I'll do it regardless of whether it exists) ' F1=foo (f1.x) # no matter if it exists, I will execute the f1.xxxxxx # no matter if it exists, I will execute it

Both appear

Class Foo:    def __init__ (self,x):        self.x=x    def __getattr__ (self, item):        print (' Executed by Me ')        # return Self.__dict__[item]    def __getattribute__ (self, item):        print (' I will do whatever it is ')        raise Attributeerror (' Haha ') f1=foo () f1.xf1.xxxxxx#------output-----------No matter whether it exists or not, I will execute the execution is I regardless of existence, I will execute is I # when __getattribute__ and __ GETATTR__ exists at the same time, only __getattrbute__ is executed unless __getattribute__ throws an exception during execution Attributeerror

 

Descriptor (__GET__,__SET__,__DELETE__)

What is the 1 descriptor: The descriptor is essentially a new class, in which at least one of the __get__ (), __set__ (), __delete__ () is implemented, which is also known as the Descriptor Protocol __get__ ():

When a property is called, __set__ () is triggered: When a property is assigned a value, __delete__ () is triggered when the property is deleted with Del

Define a descriptor

#_ *_coding:utf-8_*___author__ = ' Linhaifeng ' class Foo: #在python3中Foo是新式类, it implements three methods, this class is called a descriptor    def __get__ (self , instance, owner):        Pass    def __set__ (self, instance, value):        pass    def __delete__ (self, Instance):        Pass

What is a 2 descriptor for: The function of the descriptor is to proxy the properties of another class (the descriptor must be defined as a class attribute of the class and cannot be defined in the constructor)

Intro: the instance generated by the Descriptor class performs property operations and does not trigger execution of three methods

Class Foo:    def __get__ (self, instance, owner):        print (' Trigger get ')    def __set__ (self, instance, value):        Print (' trigger set ')    def __delete__ (self, Instance):        print (' trigger delete ') #包含这三个方法的新式类称为描述符, the invocation/assignment/deletion of the property by the instance generated by this class , and does not trigger these three methods F1=foo () f1.name= ' Egon ' F1.namedel f1.name# doubt: When, where, will trigger the execution of these three methods

Descriptor application

#描述符Strclass str:def __get__ (self, instance, owner): print (' Str call ') def __set__ (self, instance, value):    Print (' str settings ... ') def __delete__ (self, Instance): Print (' str delete ... ')        #描述符Intclass int:def __get__ (self, instance, owner): print (' Int call ') def __set__ (self, instance, value):    Print (' int set ... ') def __delete__ (self, Instance): print (' int delete ... ') class People:name=str () Age=int () def __init__ (self,name,age): #name被Str类代理, age is represented by int class, Self.name=name self.age=age# where? : A class attribute that is defined as another class # when? : And see the following demo p1=people (' Alex ') #描述符Str的使用p1. Namep1.name= ' Egon ' del p1.name# descriptor int using P1.agep1.age=18del p1.age# Let's just look at what happened. Print (p1.__dict__) print (people.__dict__) #补充print (Type (p1) = = people) #type (obj) is to see which class the obj is instantiated by, print (Type p1). __dict__ = = people.__dict__) # Output str settings ... int set ... STR calls STR settings ... STR delete ... int calls int setting ... int delete ... {} {' __module__ ': ' __main__ ', ' name ': <__main__. Str object at 0x0000000014b0a470>, ' age ': <__main__. Int objECT at 0x0000000014b0a7b8>, ' __init__ ': <function people.__init__ at 0x0000000014b2e1e0>  
' __dict__ ': <attribute ' __dict__ ' of ' people ' objects>, ' __weakref__ ': <attribute ' __weakref__ ' of ' People ' Obje Cts>, ' __doc__ ': none}truetrue

Descriptor uses

As we all know, Python is a weakly typed language, that is, there are no type restrictions on the assignment of parameters, and we implement the type limiting function by descriptor mechanisms.

class typed:def __init__ (self,name,expected_type): Self.name=name        Self.expected_type=expected_type def __get__ (self, instance, owner): print (' Get---> ', instance,owner) If instance is None:return self return instance.__dict__[self.name] def __set__ (self, instance, Valu E): Print (' Set---> ', instance,value) if not isinstance (value,self.expected_type): Raise Typeerr        Or (' expected%s '%str (Self.expected_type)) Instance.__dict__[self.name]=value def __delete__ (self, Instance): Print (' Delete---> ', instance) Instance.__dict__.pop (Self.name) class people:name=typed (' name ', str) age =typed (' name ', int) salary=typed (' name ', float) def __init__ (self,name,age,salary): Self.name=name self. Age=age self.salary=salary# P1=people (123,18,3333.3) # p1=people (' Egon ', ' ', 3333.3) p1=people (' Egon ', 18,3333) 

  Decorator for class: no reference

def decorate (CLS):    print (' class adorners start running------> ')    return cls@decorate #无参:P eople=decorate (People) class People:    def __init__ (self,name,age,salary):        self.name=name        self.age=age        self.salary=salaryp1= People (' Egon ', 18,3333.3)

  Decorator for class: parametric

def typeassert (**kwargs):    def decorate (CLS):        print (' class adorner starts running------> ', Kwargs)        return CLS    Return Decorate@typeassert (name=str,age=int,salary=float) #有参: 1. Run the Typeassert (...) The returned result is decorate, at which point the parameters are passed to Kwargs 2.people=decorate (People) class people:    def __init__ (self,name,age,salary):        Self.name=name        self.age=age        self.salary=salaryp1=people (' Egon ', 18,3333.3)

Implemented through reflection and adorners

Class Typed:def __init__ (self,name,expected_type): Self.name=name self.expected_type=expected_type de F __get__ (Self, instance, owner): print (' Get---> ', instance,owner) If instance is None:return Self return instance.__dict__[self.name] def __set__ (self, instance, value): Print (' Set---> ', instance, Value) if not Isinstance (value,self.expected_type): Raise TypeError (' expected%s '%str (Self.expected_typ        e) Instance.__dict__[self.name]=value def __delete__ (self, Instance): print (' Delete---> ', instance) Instance.__dict__.pop (Self.name) def typeassert (**kwargs): Def decorate (CLS): Print (' class decorators start running------> ', K Wargs) for Name,expected_type in Kwargs.items (): SetAttr (cls,name,typed (name,expected_type)) Retu RN CLS return Decorate@typeassert (name=str,age=int,salary=float) #有参: 1. Run Typeassert (...) The returned result is decorate, at which point the parameters are passed to Kwargs 2.people=decorate (people) CLPeople:def __init__ (self,name,age,salary): Self.name=name self.age=age Self.salary=salaryprin T (people.__dict__) p1=people (' Egon ', 18,3333.3)

  

__setitem__,__getitem__,__delitem__
Class Foo:    def __init__ (self,name):        self.name=name    def __getitem__ (self, item):        Print (self.__dict_ _[item])    def __setitem__ (self, Key, value):        self.__dict__[key]=value    def __delitem__ (self, key):        Print (' del Obj[key], I execute ')        self.__dict__.pop (key)    def __delattr__ (self, item):        print (' Del Obj.key, I execute ')        Self.__dict__.pop (item)
#通过字典方式访问f1 =foo (' sb ') f1[' age ']=18f1[' age1 ']=19del f1.age1del f1[' age ']f1[' name ']= ' Alex ' Print (f1.__dict__)
__str__,__repr__,__format__

Changing the object's string display __str__,__repr__
Self-Customizing formatted string __format__

format_dict={' nat ': ' {obj.name}-{obj.addr}-{obj.type} ', #学校名-school address-school type ' TNA ': ' {obj.type}:{obj.name}:{obj.addr} ', # School Type: School name: School address ' tan ': ' {obj.type}/{obj.addr}/{obj.name} ', #学校类型/school address/School name}class school:def __init__ (SELF,NAME,ADDR, Type): Self.name=name self.addr=addr self.type=type def __repr__ (self): Return ' School (%s,% s) '% (SELF.NAME,SELF.ADDR) def __str__ (self): return ' (%s,%s) '% (SELF.NAME,SELF.ADDR) def __format__ (self, fo RMAT_SPEC): # If Format_spec if not format_spec or Format_spec not in format_dict:format_spec= ' n At ' Fmt=format_dict[format_spec] return Fmt.format (obj=self) s1=school (' oldboy1 ', ' Beijing ', ' private ') print (' from repr: ', repr (S1)) print (' From str: ', str (S1)) print (S1) # call __str__#-----Output Result-----------# from Repr:school (oldboy1, Beijing) # from S TR: (Oldboy1, Beijing) # (oldboy1, Beijing) ' str function or print function--->obj.__str__ () repr or interactive interpreter--->obj.__repr__ () if __str__ is not defined, then the __repr__ is used instead of the output note: The return value of both methods must be a string, noThe exception ' Print (Format (S1, ' Nat ')) print (Format (S1, ' TNA ')) print (Format (S1, ' Tan ')) #----- Output-----------oldboy1-BEIJING-Private private: oldboy1: Beijing private/Beijing/oldboy1

 

Slots
What is 1.__slots__: A class variable, a variable value can be a list, a tuple, or an iterative object, or a string (meaning that all instances have only one data attribute) 2. Introduction: Using points to access attributes is the __dict__ property dictionary that accesses a class or object ( The dictionary of the class is shared, and each instance is independent) 3. Why use __slots__: A dictionary consumes a lot of memory, if you have a class with very few attributes, but there are many instances, in order to save memory you can use __slots__ to replace instances of __dict__ when you define __slots After __, __SLOTS__ will use a more compact internal representation for the instance. Instead of defining a dictionary for each instance, the instance is constructed from a small, fixed-size array, similar to a tuple or list. The attribute names listed in __slots__ are internally mapped to the specified small label for this array. A bad place to use __slots__ is that we can no longer add new properties to the instance, only those that are defined in __slots__. 4. Note: Many of the features of __slots__ depend on common dictionary-based implementations. In addition, classes that define __SLOTS__ no longer support some common class features, such as multiple inheritance. In most cases, you should only define __slots__ on classes that are often used as data structures, such as millions of instance objects in a program that need to create a class. A common misconception about __slots__ is that it can be used as an encapsulation tool to prevent users from adding new properties to an instance.           Although the use of __slots__ can achieve this goal, but this is not its original intention. More is used as a memory optimizer tool. "' f1=student () F1.name = ' Al ' # Binding property ' name ' F1.age = 2 # binding attribute ' age ' Print (f1.__slots__) # F1 no longer have __dict__print (f1.__dict__) # Error F1.score = 99 # Error class Student: __slots__=[' name ', ' Age ']f1=student () f1.name= ' Alex ' F1.age=18print (f1.__slots__) # [' Name ', ' Age ']f2=student () f2.name= ' Egon ' F2.age=19print (f2.__slots__) # [' Name ', ' Age ']print (student.__dict__) #f1与f2There is no attribute dictionary __dict__, unified return to __slots__ tube, save memory 

  

__next__ and __iter__ implementing an iterator protocol

Simple analog range, plus step

Class Range:    def __init__ (self,n,stop,step):        self.n=n        self.stop=stop        self.step=step    def __ Next__ (self):        if SELF.N >= self.stop:            raise stopiteration        X=SELF.N        self.n+=self.step        return X    def __iter__ (self):        return selffor i in Range (1,7,2): #    print (i)

Fibonacci sequence

Class Fib:    def __init__ (self,x):        self._a=0        self._b=1        self.x = x        self.n = 0    def __iter__ (self) :        return self    def __next__ (self):        if SELF.N >= self.x:            raise Stopiteration        self._a,self._b= Self._b,self._a + self._b        SELF.N + = 1        return Self._af1=fib () print (f1.__next__ ()) print (Next (F1)) while True:    Try:        print (Next (F1))    except stopiteration:        Pass

  

__doc__

The description of the class, which cannot be inherited

Class Foo:    ' I am description info '    passclass Bar (Foo):    passprint (foo.__doc__) # I am description message print (bar.__doc__) # None This property cannot be inherited to subclasses

  

__module__ and __class__

__MODULE__ represents the object of the current operation in that module

__CLASS__ represents the class of the object that is currently being manipulated

Class C:    def __init__ (self):        self.name = ' Alex ' obj = C () print (obj.__module__)    # output __main__, i.e.: Output module print ( obj.__class__)     # output <class ' __main__. C ';, i.e.: Output class

  

__del__

destructor, which automatically triggers execution when the object is freed in memory.

Note: If the resulting object is just a Python program-level (user-level), then there is no need to define __del__, and if the resulting object will also initiate system calls to the operating system,

That is, if an object has both user-level and kernel-level resources, such as (opening a file and creating a database link), the system resource must be reclaimed while the object is purged, which is __del__.

Class Foo:    def __del__ (self):        print (' Execute Me ') F1=foo () del f1print ('-------> ') #输出结果执行我啦------->

  

__enter__ and __exit__

We know we can write this when we manipulate the file object.

With open (' a.txt ') as F: ' code block '
The above is called the context Management Protocol, the WITH statement, in order for an object to be compatible with the WITH statement, the __enter__ and __exit__ methods must be declared in the class of the object.
Class Open:    def __init__ (self,name):        self.name=name    def __enter__ (self):        print (' Appear with statement, object's __ Enter__ is triggered, a return value is assigned to the variable ' declared as ')        # return self    def __exit__ (self, exc_type, Exc_val, EXC_TB):        print (' Execute me when the code block is finished executing with (' a.txt ') as F:    print (' =====> code block ')    # Print (f,f.name) #------------ The output-------A with statement appears, the object's __enter__ is triggered, and a return value is assigned to the variable =====> the as declaration. Execute code block with code block execute me when it's finished.

The three parameters in __exit__ () represent exception types, outliers, and trace information, and the code block in the WITH statement has an exception, and the code after it cannot be executed

Class Open:    def __init__ (self,name):        self.name=name    def __enter__ (self):        print (' Appear with statement, object's __ Enter__ is triggered, a return value is assigned to the variable ' declared as ')    def __exit__ (self, exc_type, Exc_val, EXC_TB):        print (execute me when the block of code in with is finished executing)        print (Exc_type)        print (exc_val)        print (EXC_TB) with Open (' a.txt ') as F:    print (' =====> Execute code block ')    Raise Attributeerror (' * * * fire, fire-fighting * * *) print (' 0 ' *100) #-------------------------------> will not execute    # print (f , f.name) #------------output-------# The WITH statement appears, the object's __enter__ is triggered, and the return value is assigned to the variable # declared by the as Declaration # =====> execution code block # with the code block executed when the execution is complete. <class ' Attributeerror ' ># * * * fire, Fire ah ***# <traceback object at 0x00000000126eab48>
If the __exit () return value is true, then the exception is emptied, as if nothing had happened, and the statement with the following is executed normally
Class Open:    def __init__ (self,name):        self.name=name    def __enter__ (self):        print (' Appear with statement, object's __ Enter__ is triggered, a return value is assigned to the variable ' declared as ')    def __exit__ (self, exc_type, Exc_val, EXC_TB):        print (execute me when the block of code in with is finished executing)        print (exc_type) print (        exc_val)        print (EXC_TB)        return truewith Open (' a.txt ') as F:    print (' = = = = Execute code block ')    raise Attributeerror (' * * * fire, fire, fight * * *) print (' 0 ' *10) #-------------------------------> will execute # #-- -----------Output------------------# The WITH statement appears, the object's __enter__ is triggered, and the return value is assigned to the variable # declared by the as Declaration # =====> execution code block # with the code block executed when the execution of my AH # <class ' Attributeerror ' ># * * * fire, Fire ah ***# <traceback object at 0x00000000126eab88>
# 0000000000
Analog Open 
Class Open:    def __init__ (self,file_name,mode,encoding= ' utf-8 '):        self.file_name=file_name        self.mode = Mode        self.encoding = Encoding    def __enter__ (self):        print (' Enter ')        self.f = open (Self.file_name, self.mode,encoding=self.encoding)        return SELF.F    def __exit__ (self, exc_type, Exc_val, EXC_TB):        print (" Exit ")        Self.f.close ()        return True    def __getattr__ (self, item):        print (' Executed by me ')        return GetAttr (SELF.F, item) with Open (' Test.txt ', ' W ') as F:    f.write (' Aadddda ')

  

    1. The purpose of using the WITH statement is to put the code block in with, and with the end, the cleanup work is done automatically without manual intervention

    2. In a programming environment where you need to manage resources such as files, network connections, and locks, you can customize the mechanism for automatically releasing resources in __exit__, which is useful if you don't have to deal with the problem.

__call__

The object is appended with parentheses to trigger execution.

Note: The execution of the construction method is triggered by the creation object, that is: Object = class name (), and the execution of the __call__ method is triggered by parentheses after the object, i.e.: Object () or Class () ()

Class Foo:    def __init__ (self):        pass    def __call__ (self, *args, **kwargs):        print (' __call__ ') obj = Foo () # Execute __init__obj ()       # Execute __call__

  

Python Magic method

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.