Magic methods and decorators of python class


Closure decorator

The essence of decorator is a closure. There are three elements of closure: 1. Function nesting, 2. External function returns the reference of internal function, and internal function uses the variable of external function
1. Use the decorator to simply realize a login verification function

In [1]: user = {"username": "123", "password": 123}
 def outter(func):
   ...:     def inner(*args, **kwargs):
   ...:         if user.get('token'):
   ...:             return func(*args, **kwargs)
   ...:         else:
   ...:             username = input("user:")
   ...:             password = input("pwd:")
   ...:             if user.get("username") == username:
   ...:                 user['token'] = True
   ...:                 print("login success")
   ...:                 return func(*args, **kwargs)
   ...:             else:
   ...:                 raise ValueError('login faild')
   ...:     return inner

In [8]: @outter     # func = outer(tests)
   ...: def tests(a, b):
   ...:     print('tests result:',a*b)

In [9]: tests(2,4)   # outer(tests)(2, 4)
login success
tests result: 8

In [10]: tests(2,4)
tests result: 8

In [11]: tests(2,9)
tests result: 18



After decorating the magic square of @ classmethod in the class, it belongs to the class method. The first parameter passed is the class object, which can be called directly by the class object, and the class method can also be called by the instance method, but the class method cannot call the instance method
Usage scenario: call when instantiation is not required

 class Method:
    ...:     def __init__(self):
    ...:         pass
    ...:     @classmethod       # After decorating, the decorator becomes a class method, which can be called directly by the class
    ...:     def trf(cls):
    ...:         print(cls)
    ...:     def test(self):       # Example method
    ...:         print(self)
    ...:         self.trf()

In [23]: Method.trf()
<class '__main__.Method'>

In [24]: Method.test()
TypeError                                 Traceback (most recent call last)
<ipython-input-24-23908d4c4445> in <module>
----> 1 Method.test()

TypeError: test() missing 1 required positional argument: 'self'

In [25]: s = Method()

In [26]: s.trf()
<class '__main__.Method'>

In [27]: s.test()
<__main__.Method object at 0x000001ADD8BE3C18>
<class '__main__.Method'>

@staticmethod method

The instance method modified by the staticmethod method can pass no parameters, just like the normal magic method

@property method

Setting the property decorator can call an instance just like calling properties through an instance,
Usage scenario: this decoration can be used for attributes that do not want to be modified

Class magic method

Use of new method

In a class, the first way to create an instance object is__ new__ Magic method, the new method allocates memory to the object, so one method used during initialization of each instance is the new method
Usage scenario: this magic method is often used to set a single instance

In [38]: class bdss:
    ...:     sunclss = None      # In non singleton mode, as long as the class attribute is changed, the next instance will use the changed class attribute value
    ...:     def __new__(cls, *args, **kwargs):
    ...:         print(cls.sunclss)
    ...:         from random import randint
    ...:         cls.sunclss = randint(1, 40)
    ...:         print('-------',cls.sunclss)
    ...:         return super().__new__(cls, *args, **kwargs)

In [39]: a  = bdss()
------- 2

In [40]: b = bdss()
------- 33

In [41]: c = bdss()
------- 37

# Singleton implementation
In [28]: class bdss:
    ...:     sunclss = None
    ...:     def __new__(cls, *args, **kwargs):
    ...:         if cls.sunclss:
    ...:             return cls.sunclss
    ...:         else:
    ...:             cls.sunclss = super().__new__(cls, *args, **kwargs)
    ...:             return cls.sunclss

In [29]: a = bdss()

In [30]: a
Out[30]: <__main__.bdss at 0x1add90c69b0>

In [31]: b = bdss()

In [32]: b
Out[32]: <__main__.bdss at 0x1add90c69b0>

__ call__ Use of magic methods

Class__ call__ The magic method can be called like a function to get the result

In [50]: class A:
    ...:     def __init__(self):
    ...:         pass
    ...:     def __call__(self):
    ...:         print('call method')

In [51]:

In [51]: a = A()

In [52]: a()   	# Instance properties are called like functions
call method

Use the class decorator to complete the singleton mode

1 the essence of calling decorator is that external function refers to internal function method,

Therefore, to implement the decorator with a class, it is necessary to trigger a class method when calling a class method__ call__ Method is called when calling a function, so the call method must be used when using class method as decorator

Class (getattr, setattr, delattr)

__ getattr__ And getattribute methods

1 getattribute is called when the class gets the attribute. If the attribute is not found in the class method, the getattr method will be triggered. The getattr method of the parent class will throw no exceptions. Therefore, if you want to not throw exceptions, you can rewrite the getattr method so that it does not throw exceptions

 class A:
   ...:     def __init__(self):
   ...:         self.a = 'a'
   ...:         self.b = 'b'
   ...:     def __getattr__(self, key):
   ...:         print('There is an exception calling when the value is not obtained')
   ...:         object.__getattribute__(self, key)

In [10]: x = A()

In [11]: x.c
 There is an exception calling when the value is not obtained
AttributeError                            Traceback (most recent call last)
<ipython-input-11-a693afdd9058> in <module>
----> 1 x.c

<ipython-input-9-878ca7145054> in __getattr__(self, key)
      6     def __getattr__(self, key):
      7         print('There is an exception calling when the value is not obtained')
----> 8         object.__getattribute__(self, key)

AttributeError: 'A' object has no attribute 'c'

If there are many instances of set python method to be overridden, the attribute of setatt2 can be used in the scene if there are many instances of setattr method to be overridden

n [9]: class A:
   ...:     def __init__(self):
   ...:         self.a = 'a'
   ...:         self.b = 'b'
   ...:     def __setattr__(self, item, value):
   ...:         print('__setattr__')
   ...:         object.__setattr__(self, item, value)
   ...:     def __delattr__(self, item):
   ...:         print('Property deleted')
   ...:         object.__delattr__(self, item)
   ...:     def __getattr__(self, key):
   ...:         print('There is an exception calling when the value is not obtained')
   ...:         object.__geta
   ...:         ttribute__(self, key)

In [10]: xi = A()

In [11]: del xi.a
 Property deleted

Keywords: Python

Added by Fjerpje on Tue, 08 Feb 2022 14:51:23 +0200