Python reflection and double down method
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)
1.1 reflection of 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 an attribute is included 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
1.2 reflection on class
class Foo(object): staticField = "old boy" 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')
1.3 reflection of current module
import sys def s1(): print 's1' def s2(): print 's2' this_module = sys.modules[__name__] hasattr(this_module, 's1') getattr(this_module, 's2')
1.4 reflection of other modules
#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')()
1.5 application of reflection
Understand the four functions of reflection. So what's the use of reflection? What are its application scenarios?
Now let's open the browser and visit a website. You click login to jump to the login interface, you 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.
I didn't learn the solution before reflection
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()
Learn the solution after reflection
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....')
In this way, you can clearly feel the benefits of reflection
2, Double down method
Definition: Double underline method is a special method. It is provided by the interpreter. The method name is underlined and 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, such as init
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))
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))
If a class is defined__ str__ Method, the return value of this method will be output by default when printing objects.
class A: def __init__(self): pass def __str__(self): return 'Baoyuan' a = A() print(a) print('%s' % a)
If a class is defined__ repr__ Method, the return value of the method is output by default when repl (object).
class A: def __init__(self): pass def __repr__(self): return 'Baoyuan' a = A() print(repr(a)) print('%r'%a)
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 (); The execution of call 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__
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)
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 memory allocation and release 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.
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)
Use__ new__ Implement singleton mode
class A: __instance = None def __new__(cls, *args, **kwargs): if cls.__instance is None: obj = object.__new__(cls) cls.__instance = obj return cls.__instance Singleton mode
Specific analysis of single case mode:
Singleton pattern is a common software design pattern. Its core structure contains only 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.
[motivation and reason for adopting single case mode]
For some classes in the system, only one instance is very important. For example, there can be multiple print tasks in a system, but only one working task can exist; A system can only have one window manager or file system; A system can only have one timing tool or ID (sequence number) generator. For example, only one task manager can be opened in Windows. 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, they are duplicate objects and waste 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, it is sometimes 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 ensures that objects can be accessed at any time, but it does not 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]
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.
Because the class controls the instantiation process, the class can flexibly change the instantiation process.
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 instantiate objects with the new keyword. 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 languages that provide memory management (such as those based on the. NET Framework), only a singleton class can cause an instance to be deallocated because it contains a private reference to the instance. In some languages (such as C + +), other classes can delete object instances, but this will lead to floating references in singleton classes
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']='alex' print(f1.__dict__)