Class decorator

In python, everything is an object, function and class are an object, so decorators can be applied to functions, and they should also be applied to classes.

#Function decorator example
def deco(func):
    print("====,Decorator operation")
    return func


@deco # Foo = deco(test)
def test():
    print("test")
#Class decorator example
def deco(func):
    print("====,Decorator operation")
    return func


@deco # Foo = deco(Foo)
class Foo:
    def __init__(self, name, age):
        self.name = name
        self.age = age


f1 = Foo("MB", 18)

The essence of decorator is to do such things as func = deco(func), so when encountering syntax sugar decorator function, it will directly execute

Verify that everything is an object

Functions and classes can be decorated by decorators, and both can perform the function of adding attributes by decorators

def deco(func):
    func.x = 1
    func.y = 2
    func.z = 3
    return func


@deco
class Foo:
    def __init__(self, name, age):
        self.name = name
        self.age = age


@deco
def test():
    pass


print(Foo.x)
print(test.x)
print(test.__dict__)

This is equivalent to dead writing. Only x, y and z can be added. Therefore, parameter transfer of decorator needs to be added another layer outside the decorator layer.

def typed(**kwargs):
    def deco(func):
        for key, value in kwargs.items():
            setattr(func, key, value)
            # func.__dict__[key] = value
            # func.key = value #Pay attention to the three methods. Only the first one can be implemented. Sometimes you need to try which one can be implemented.
        return func

    return deco


@typed(x=1, y=2, z=3)#This place is equivalent to executing typed(x=1, y=2, z=3) to get a return value of deco, so one is equivalent to @ deco.
class Foo:
    def __init__(self, name, age):
        self.name = name
        self.age = age


@typed(name="MB", age=18)
def test():
    pass


print(Foo.x)
print(test.name)
print(test.__dict__)

The application of class decorator

Requirement: implementation type limit

def deco(**kwargs):
    def wrapper(obj):
        for key, val in kwargs.items():
            setattr(obj, key, typed(key, val))
        return obj

    return wrapper


class typed:
    def __init__(self, key, val):
        self.key = key
        self.val = val

    def __set__(self, instance, value):
        if not isinstance(value, self.val):
            raise TypeError("%s The type required is %s" % (self.key, self.val))
        instance.__dict__[self.key] = value


@deco(name=str, age=int, salary=float)#This is essentially the same as the prop = Deco (name = STR, age = int, salary = float), and the decorator assigns descriptors to each attribute, so the essence is still descriptors
class People:
    def __init__(self, name, age, salary):
        self.name = name
        self.age = age
        self.salary = salary


p1 = People("MB", 18, 10000.0)
print(p1.__dict__)

Keywords: Python Attribute

Added by techwiz on Sun, 20 Oct 2019 23:18:05 +0300