知行编程网知行编程网  2022-12-08 13:30 知行编程网 隐藏边栏  5 
文章评分 0 次,平均分 0.0
导语: 本文主要介绍了关于三分钟搞定Python中的装饰器的相关知识,希望可以帮到处于编程学习途中的小伙伴

三分钟搞定Python中的装饰器

Python的装饰器是python特有的高级特性之一。简单来说,它的作用就是在不改变其原有函数和类的定义的情况下,为它们增加新的功能。

装饰器存在的意义是什么?我们知道在python中,函数是可以调用的,类是可以继承的。为什么一定要保证函数和类的定义不被改动,让函数有新的功能呢?其实很容易解释。

提高代码的简洁性和封装性。如果用声明一个新函数调用原函数的思路来增加原函数的功能,但是一方面看起来使用起来并不简单,另一方面当另一个程序员使用你的代码,再用这个思路,代码的嵌套层出不穷,会让代码变得很乱。可能是哪里出了问题,改了原函数的一个参数,就会出现找不到的bug。

我们先来看一个简单的例子。

def addworld(func):
    def addfun():
        return func() + 'world'
    return addfun()

@addworld
def printhello():
    return 'hello'

print(printhello)

这段代码的最终结果是helloworld。我们发现只要在原来的函数头添加一个自己定义的添加函数的模板,以后每次添加这个都会添加一个函数,提高了开发效率,看起来更简洁。

def addnum(func):
    def addfun(*args, **kwargs):
        ret = func(*args, **kwargs)*2
        return ret
    return addfun

@addnum
def printsum(a, b):
    return (a+b)

i = printsum(7, 7)
print(i)

这是有参数时使用装饰器的效果,输出结果为28。

def addnum1(c):
    def addnum(func):
        def addfun(*args, **kwargs):
            ret = func(*args, **kwargs)*2*c
            return ret
        return addfun
    return addnum

@addnum1(5)
def printsum(a, b):
    return (a+b)

i = printsum(7, 7)
print(i)

装饰器本身也可以传递参数。在这个程序中,传入了一个常量5,最终结果为140。

接下来,我们介绍几个常用的python内置装饰器。

property

在绑定属性的时候,如果我们直接暴露属性,虽然写起来很简单,但是没有办法检查参数,所以结果可以随意改变。这显然是不可能的,那么在函数中,我们往往如何提高程序的健壮性呢?

class Student(object):

    def get_score(self):
        return self._score

    def set_score(self, value):
        if not isinstance(value, int):
            raise ValueError('score must be an integer!')
        if value < 0 or value > 100:
            raise ValueError('score must between 0 ~ 100!')
        self._score = value

s = Student()
s.set_score(60)
value = s.get_score()
print(value)

通过调用类中的函数进一步操作属性,虽然安全无误,但显得复杂,不接近人属性的自然表达。

class Student(object):

    @property
    def score(self):
        return self._score

    @score.setter
    def score(self, value):
        if not isinstance(value, int):
            raise ValueError('score must be an integer!')
        if value < 0 or value > 100:
            raise ValueError('score must between 0 ~ 100!')
        self._score = value

s = Student()
s.score = 80
print(s.score)

而加上一个@property就可以轻松解决这个问题,是不是很神奇?要把一个getter方法变成一个属性,你只需要添加@property。这时候@property自己又创建了一个装饰器@score.setter,它负责把一个setter方法变成一个属性赋值,这样我们就有了一个可控的属性操作。

也可以定义只读属性,只定义getter方法,不定义setter方法是只读属性。

class Student(object):

    @property
    def birth(self):
        return self._birth

    @birth.setter
    def birth(self, value):
        self._birth = value

    @property
    def age(self):
        return 2014 - self._birth

上面的birth是可读可写的属性,age是只读属性,因为可以根据birth和当前时间计算age。

本文为原创文章,版权归所有,欢迎分享本文,转载请保留出处!

知行编程网
知行编程网 关注:1    粉丝:1
这个人很懒,什么都没写
扫一扫二维码分享