Python装饰器abstractmethod、property、classmethod、staticmethod及自定义装饰器

本文详细介绍了Python中的装饰器,包括@abstractmethod用于确保子类覆盖抽象方法,@property用于方法伪装属性,@classmethod和@staticmethod用于类方法和静态方法的调用。此外,还讲解了自定义装饰器的实现原理,以及装饰器在日志、性能统计、权限校验等场景的应用。
摘要由CSDN通过智能技术生成

总览:

@abstractmethod:抽象方法,含abstractmethod方法的类不能实例化,继承了含abstractmethod方法的子类必须复写所有abstractmethod装饰的方法,未被装饰的可以不重写

@ property:方法伪装属性,方法返回值及属性值,被装饰方法不能有参数,必须实例化后调用,类不能调用

@ classmethod:类方法,可以通过实例对象和类对象调用,被该函数修饰的方法第一个参数代表类本身常用cls,被修饰函数内可调用类属性,不能调用实例属性

@staticmethod:静态方法,可以通过实例对象和类对象调用,被装饰函数可无参数,被装饰函数内部通过类名.属性引用类属性或类方法,不能引用实例属性

案例讲解:

@abstractmethod

用于程序接口的控制,正如上面的特性,含有@abstractmethod修饰的父类不能实例化,但是继承的子类必须实现@abstractmethod装饰的方法

from abc import ABC, abstractmethod

class A(ABC):

    @abstractmethod

    def test(self):

        pass

class B(A):

    def test_1(self):

        print("未覆盖父类abstractmethod")

class C(A):

    def test(self):

        print("覆盖父类abstractmethod")

if __name__ == '__main__':

    a = A()

    b = B()

    c = C()

@ property

将一个方法伪装成属性,被修饰的特性方法,内部可以实现处理逻辑,但对外提供统一的调用方式,实现一个实例属性的get,set,delete三种方法的内部逻辑,具体含义看示例code。

class Data(): 

    def __init__(self):

        self.number = 123

    @property

    def operation(self):

        return self.number

    @operation.setter

    def operation(self, number):

        self.number = number

        return self.number

    @operation.deleter

    def operation(self):

        del self.number

        return self.number

data=Data()

data.operation=90

print(data.operation)

@ classmethod,staticmethod

类方法classmethod和静态方法staticmethod是为类操作准备,是将类的实例化和其方法解耦,可以在不实例化的前提下调用某些类方法。两者的区别可以这么理解:类方法是将类本身作为操作对象,而静态方法是独立于类的一个单独函数,只是寄存在一个类名下。类方法可以用过类属性的一些初始化操作。

class Test():

    num = "aaaa"

    def __init__(self):

        self.number = 123

    @classmethod

    def a(cls, n):

        cls.num = n

        print(cls.num)

    @classmethod

    def b(cls, n):

        cls.a(n)

    @classmethod

    def c(cls, n):

        cls.number = n

    @staticmethod

    def d(n):

        Test.b(n)

test=Test()

test.d(11)

装饰器函数机制

谈装饰器的原理就不得不先理解Python的闭包,在函数内部再定义一个函数,并且这个函数用到了外边函数的变量,那么将这个函数以及用到的一些变量称之为闭包即内部函数对外部函数作用域里变量的引用(非全局变量),则称内部函数为闭包。

装饰器是建立在闭包的基础上,将被装饰函数传入闭包函数中执行则形成了装饰器。

闭包:
 

#闭包

def counter(start=0):

    count=[start]

    def incr():

        count[0] += 1

        return count[0]

    return incr

c=counter(5)

print(c())

print(c())

print(c())

print(c())

#非闭包

def counter(start=0):

    count=[start]

    def incr():

        count[0] += 1

        return count[0]

    return incr()

c=counter(5)

print(c)

print(c)

print(c)

print(c)
 

装饰器原型:

# -*- coding:utf-8 -*-



def B(fn):

    def b():

        return fn()+3

    return b


@B

def add():

    return 3


if __name__ == '__main__':

    str = fn()

    print(str)

----------------

6

 

当被装饰函数带参数:

# -*- coding:utf-8 -*-


def B(fn):

    def b(*args, **kwargs):

        return str(fn(*args, **kwargs))+"装饰"

    return b


@B
def fn(*args, **kwargs):

    num = 0

    for i in args:

        num +=i

    for i in kwargs.values():

        num += i

    return num


if __name__ == '__main__':

    num = fn(1, 2, 3, a=4, b=5)

    print(num)

----------------
15装饰

 

当装饰函数带额外参数,应该在装饰函数外再包裹一层函数

# -*- coding:utf-8 -*-


def A(n):

    def B(fn):

        def b(*args, **kwargs):

            return n+str(fn(*args, **kwargs))+"装饰"

        return b

    return B


@A("包裹前缀")
def fn(*args, **kwargs):

    num = 0

    for i in args:

        num +=i

    for i in kwargs.values():

        num += i

    return num


if __name__ == '__main__':

    num = fn(1, 2, 3, a=4, b=5)

    print(num)




----------------

包裹前缀15装饰

 

当多个装饰函数装饰一个函数时的执行顺序

# -*- coding:utf-8 -*-


def A(fn):


    print(1)


    def run():

        print(2)

        fn()

    print('a')

    return run


def B(fn):

    print(3)


    def run():

        print(4)

        fn()


    print('b')

    return run


def C(fn):

    print(5)


    def run():

        print(6)

        fn()


    print('c')

    return run

@A
@B
@C
def test():

    print(7)


if __name__ == '__main__':

    test()





----------------
5

c
3

b
1

a
2
4
6
7

 

由此可以得出多装饰情况下的运行情况:初始化运行从下到上,内部执行顺序从内到外。因为开始执行时会按照装饰顺序,组装成一个函数,而这个函数从最外层的return执行到最内层,故有上述顺序,就像剥洋葱一样。

 

类装饰器

# -*- coding:utf-8 -*-


class Add:


    def __init__(self, fn):

        print("初始化")

        self.num = 44

        self.fn = fn


    def __call__(self, *args, **kwargs):

        print("类装饰器开始工作")

        return self.fn(self.num)



@Add
def test(n):

    return 4+n


if __name__ == '__main__':

    num = test()

    print(num)

----------------

初始化

类装饰器开始工作
48

 

类装饰器使用地方较少,核心是通过复写类的回调方法__call__.

 

装饰器应用场景

  1. 引入日志

  2. 函数执行时间统计

  3. 执行函数前预备处理

  4. 执行函数后清理功能

  5. 权限校验等场景

  6. 缓存

 

 

 


 

@propertyPython 中的一个装饰器,用于将一个方法转换为属性。通过使用 @property 装饰器,我们可以将一个方法像访问属性一样进行调用,而不需要使用括号。这样可以使代码更加简洁易读。 @cacheproperty 是一个自定义装饰器,用于实现属性的缓存功能。当使用 @cacheproperty 装饰器修饰一个方法时,该方法的返回值会被缓存起来,下次再次访问该属性时,直接返回缓存的值,而不需要重新计算。 除了 @property 和 @cachepropertyPython 还有其他一些高级装饰器,如下所示: 1. @staticmethod:将一个方法转换为静态方法。静态方法不需要访问类或实例的属性,可以直接通过类名或实例名调用。 2. @classmethod:将一个方法转换为类方法。类方法可以访问类属性,并且第一个参数是类本身而不是实例。 3. @abstractmethod:定义一个抽象方法。抽象方法只有方法的声明而没有具体的实现,在子类中必须被重写。 4. @staticmethod 和 @classmethod 的区别: - 静态方法使用 @staticmethod 装饰器修饰,不需要传入额外的参数,可以直接通过类名或实例名调用。 - 类方法使用 @classmethod 装饰器修饰,第一个参数是类本身,通常命名为 cls,可以访问类属性。 5. @abstractmethod 和 @abc.abstractmethod 的区别: - @abstractmethodPython 内置的装饰器,用于定义抽象方法。 - @abc.abstractmethod 是 abc 模块中的装饰器,用于定义抽象方法,并且需要配合 abc.ABCMeta 元类一起使用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值