1. Reflection
The concept of reflection was first proposed by Smith in 1982. It mainly refers to the ability of a program to access, detect and modify its own state or behavior (introspection). The proposal of this concept soon triggered the research on applied reflexivity in the field of computer science. It was first adopted in the field of programming language design, and made achievements in Lisp and object-oriented.
Reflection in python object-oriented: manipulating object related properties in the form of strings. Everything in python is an object (you can use reflection)
Four functions that can realize introspection
The following methods apply to classes and objects (everything is an object, and the class itself is an object)
class Foo: f = 'Static variable of class' def __init__(self,name,age): self.name=name self.age=age def say_hi(self): print('hi,%s'%self.name) obj=Foo('huihuang',73) #Detect whether there is an attribute print(hasattr(obj,'name')) print(hasattr(obj,'say_hi')) #get attribute n=getattr(obj,'name') print(n) func=getattr(obj,'say_hi') func() print(getattr(obj,'aaaaaaaa','It doesn't exist')) #report errors #set a property setattr(obj,'sb',True) setattr(obj,'show_name',lambda self:self.name+'sb') print(obj.__dict__) print(obj.show_name(obj)) #Delete attribute delattr(obj,'age') delattr(obj,'show_name') delattr(obj,'show_name111')#If it does not exist, an error is reported print(obj.__dict__) Examples of instantiated objects
class Foo: f = 'Static variable of class' def __init__(self,name,age): self.name=name self.age=age def say_hi(self): print('hi,%s'%self.name) obj=Foo('egon',73) #Detect whether there is an attribute print(hasattr(obj,'name')) print(hasattr(obj,'say_hi')) #get attribute n=getattr(obj,'name') print(n) func=getattr(obj,'say_hi') func() print(getattr(obj,'aaaaaaaa','It doesn't exist')) #report errors #set a property setattr(obj,'sb',True) setattr(obj,'show_name',lambda self:self.name+'sb') print(obj.__dict__) print(obj.show_name(obj)) #Delete attribute delattr(obj,'age') delattr(obj,'show_name') delattr(obj,'show_name111')#If it does not exist, an error is reported print(obj.__dict__) Of instantiated objects
class Foo(object): staticField = "yan hui" def __init__(self): self.name = 'wupeiqi' def func(self): return 'func' @staticmethod def bar(): return 'bar' print getattr(Foo, 'staticField') print getattr(Foo, 'func') print getattr(Foo, 'bar')
import sys def s1(): print 's1' def s2(): print 's2' this_module = sys.modules[__name__] hasattr(this_module, 's1') getattr(this_module, 's2')
#Code in a module def test(): print('from the test') """ Program directory: module_test.py index.py Current file: index.py """ # Code in another module import module_test as obj #obj.test() print(hasattr(obj,'test')) getattr(obj,'test')() Examples of other modules
Application of reflection:
Open the browser, visit a website, click login to jump to the login interface, click registration to jump to the registration interface, etc. in fact, you click links one by one, and each link will be handled by a function or method.
class User: def login(self): print('Welcome to the login page') def register(self): print('Welcome to the registration page') def save(self): print('Welcome to the storage page') while 1: choose = input('>>>').strip() if choose == 'login': obj = User() obj.login() elif choose == 'register': obj = User() obj.register() elif choose == 'save': obj = User() obj.save()
class User: def login(self): print('Welcome to the login page') def register(self): print('Welcome to the registration page') def save(self): print('Welcome to the storage page') user = User() while 1: choose = input('>>>').strip() if hasattr(user,choose): func = getattr(user,choose) func() else: print('Input error....')
2. Function vs method
2.1 determine by printing function (method) name
def func(): pass print(func) # <function func at 0x00000260A2E690D0> class A: def func(self): pass print(A.func) # <function A.func at 0x0000026E65AE9C80> obj = A() print(obj.func) # <bound method A.func of <__main__.A object at 0x00000230BAD4C9E8>>
2.2 verification through types module
from types import FunctionType from types import MethodType def func(): pass class A: def func(self): pass obj = A() print(isinstance(func,FunctionType)) # True print(isinstance(A.func,FunctionType)) # True print(isinstance(obj.func,FunctionType)) # False print(isinstance(obj.func,MethodType)) # True
2.3 static methods are functions
from types import FunctionType from types import MethodType class A: def func(self): pass @classmethod def func1(self): pass @staticmethod def func2(self): pass obj = A() # Static methods are actually functions # print(isinstance(A.func2,FunctionType)) # True # print(isinstance(obj.func2,FunctionType)) # True
2.4 differences between functions and methods
In addition to the above differences between functions and methods, we also summarize some differences.
(1) Function is used to explicitly pass data. As we want to specify, pass some data to be processed for the len() function.
(2) Functions have nothing to do with objects.
(3) The data in the method is passed implicitly.
(4) Method can manipulate data inside a class.
(5) Methods are associated with objects. If we are using the strip() method, do we always call it through the str object? For example, we have the string s, and then s.strip() is called in this way. Yes, the strip() method belongs to the str object.
3. Double down method
Definition: double down method is a special method. It is provided by the interpreter. It is double underlined plus method name plus double underlined__ Method name__ The double down method is mainly used by python source code programmers. We try not to use the double down method in development, but an in-depth study of the double down method is more beneficial for us to read the source code.
Call: different double down methods have different trigger methods, just like the mechanism triggered during tomb theft. The double down method is triggered unconsciously, for example:__ init__
3.1 __len__
class B: def __len__(self): print(666) b = B() len(b) # Len an object will trigger__ len__ method. class A: def __init__(self): self.a = 1 self.b = 2 def __len__(self): return len(self.__dict__) a = A() print(len(a))
3.2 __hash__
class A: def __init__(self): self.a = 1 self.b = 2 def __hash__(self): return hash(str(self.a)+str(self.b)) a = A() print(hash(a))
3.3 __str__
If a class is defined__ str__ Method, the return value of this method will be output by default when printing the object
class A: def __init__(self): pass def __str__(self): return 'brilliant' a = A() print(a) print('%s' % a)
3.4 __repr__
If a class is defined__ repr__ Method, the return value of this method will be output by default when repl (object)
class A: def __init__(self): pass def __repr__(self): return 'brilliant' a = A() print(repr(a)) print('%r'%a)
3.5 __call__
Object is followed by parentheses to trigger execution.
Note: construction method__ new__ The execution of is triggered by the creation of an object, that is: object = class name (); And for__ call__ The execution of method is triggered by adding parentheses after the object, that is, object () or class () ()
class Foo: def __init__(self): pass def __call__(self, *args, **kwargs): print('__call__') obj = Foo() # Execute__ init__ obj() # Execute__ call__
3.6 __eq__
class A: def __init__(self): self.a = 1 self.b = 2 def __eq__(self,obj): if self.a == obj.a and self.b == obj.b: return True a = A() b = A() print(a == b)
3.7 __del__
Destruct method, which automatically triggers execution when the object is released in memory.
Note: this method generally does not need to be defined, because Python is a high-level language. Programmers do not need to care about the allocation and release of memory when using it, because this work is executed by the Python interpreter. Therefore, the call of destructor is automatically triggered and executed by the interpreter during garbage collection
3.8__new__
class A: def __init__(self): self.x = 1 print('in init function') def __new__(cls, *args, **kwargs): print('in new function') return object.__new__(A, *args, **kwargs) a = A() print(a.x)
Singleton pattern is a common software design pattern. In its core structure, it only contains a special class called singleton class. The single instance mode can ensure that there is only one instance of a class in the system, and the instance is easy to be accessed by the outside world, so as to facilitate the control of the number of instances and save system resources. If you want only one object of a class to exist in the system, singleton mode is the best solution. [Using single case mode [motivation, reason] For some classes in the system, only one instance is very important. For example, there can be multiple print tasks in a system, but there can only be one working task; A system can only have one window manager or file system; A system can only have one timing tool or ID(Serial number)Generator. If in Windows Only one task manager can be opened in. If you do not use the mechanism to make window objects unique, multiple windows will pop up. If the contents displayed in these windows are exactly the same, it is a duplicate object and a waste of memory resources; If the contents displayed in these windows are inconsistent, it means that there are multiple states of the system at a certain moment, which are inconsistent with the actual situation. It will also bring misunderstanding to the user and do not know which is the real state. Therefore, sometimes it is very important to ensure the uniqueness of an object in the system, that is, a class can only have one instance. How to ensure that a class has only one instance and that the instance is easy to access? Defining a global variable can ensure that objects can be accessed at any time, but it can't prevent us from instantiating multiple objects. A better solution is to let the class itself be responsible for saving its only instance. This class can ensure that no other instance is created, and it can provide a method to access the instance. This is the motivation of singleton mode. [Advantages and disadvantages of singleton mode] [Advantages] 1, Instance control Singleton mode prevents other objects from instantiating copies of their own singleton objects, ensuring that all objects have access to a unique instance. 2, Flexibility Because the class controls the instantiation process, the class can flexibly change the instantiation process. [Disadvantages] 1, Expenses Although the number is small, there will still be some overhead if you check whether there are instances of the class every time an object requests a reference. You can solve this problem by using static initialization. 2, Possible development confusion When using singleton objects (especially those defined in class libraries), developers must remember that they cannot use them new Keyword instantiates an object. Because the library source code may not be accessible, application developers may accidentally find themselves unable to instantiate this class directly. 3, Object lifetime The problem of deleting a single object cannot be solved. In a language that provides memory management (for example, based on.NET Framework Only a singleton class can cause an instance to be unassigned because it contains a private reference to the instance. In some languages (e.g C++),Deleting a single instance of an object in another class can result in a single instance being deleted Specific analysis of single case mode
3.9 __item__ series
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]Time,I execute') self.__dict__.pop(key) def __delattr__(self, item): print('del obj.key Time,I execute') self.__dict__.pop(item) f1=Foo('sb') f1['age']=18 f1['age1']=19 del f1.age1 del f1['age'] f1['name']='yan' print(f1.__dict__)
3.10 context manager related
__enter__ __exit__
# If you want to modify the object of a class with as Your operation is not good. class A: def __init__(self, text): self.text = text with A('ha-ha') as f1: print(f1.text)
class A: def __init__(self, text): self.text = text def __enter__(self): # This method is triggered when the context manager object is opened self.text = self.text + 'Here you are' return self # Returns the instantiated object to f1 def __exit__(self, exc_type, exc_val, exc_tb): # This method is triggered when the context manager object f1 is executed self.text = self.text + 'Let's go' with A('ha-ha') as f1: print(f1.text) print(f1.text)
class Diycontextor: def __init__(self,name,mode): self.name = name self.mode = mode def __enter__(self): print "Hi enter here!!" self.filehander = open(self.name,self.mode) return self.filehander def __exit__(self,*para): print "Hi exit here" self.filehander.close() with Diycontextor('py_ana.py','r') as f: for i in f: print i
Example:
class StarkConfig: def __init__(self,num): self.num = num def run(self): self() def __call__(self, *args, **kwargs): print(self.num) class RoleConfig(StarkConfig): def __call__(self, *args, **kwargs): print(345) def __getitem__(self, item): return self.num[item] v1 = RoleConfig('yan') v2 = StarkConfig('brilliant') # print(v1[1]) # print(v2[2]) v1.run() ------- class UserInfo: pass class Department: pass class StarkConfig: def __init__(self, num): self.num = num def changelist(self, request): print(self.num, request) def run(self): self.changelist(999) class RoleConfig(StarkConfig): def changelist(self, request): print(666, self.num) class AdminSite: def __init__(self): self._registry = {} def register(self, k, v): self._registry[k] = v site = AdminSite() site.register(UserInfo, StarkConfig) # 1 # obj = site._registry[UserInfo]() # 2 obj = site._registry[UserInfo](100) obj.run() ------- class UserInfo: pass class Department: pass class StarkConfig: def __init__(self,num): self.num = num def changelist(self,request): print(self.num,request) def run(self): self.changelist(999) class RoleConfig(StarkConfig): def changelist(self,request): print(666,self.num) class AdminSite: def __init__(self): self._registry = {} def register(self,k,v): self._registry[k] = v(k) site = AdminSite() site.register(UserInfo,StarkConfig) site.register(Department,RoleConfig) for k,row in site._registry.items(): row.run() ------- class A: list_display = [] def get_list(self): self.list_display.insert(0,33) return self.list_display s1 = A() print(s1.get_list()) ------- class A: list_display = [1, 2, 3] def __init__(self): self.list_display = [] def get_list(self): self.list_display.insert(0, 33) return self.list_display s1 = A() print(s1.get_list()) ------ class A: list_display = [] def get_list(self): self.list_display.insert(0,33) return self.list_display class B(A): list_display = [11,22] s1 = A() s2 = B() print(s1.get_list()) print(s2.get_list())