前言


在还未正式发布的python3.9中,有一个新功能值得关注,那就是任意表达式可以作为装饰器,如果你还不知道装饰器是什么,没关系,跟着本文一个例子搞明白,不过需要你对Python中的类(Class)有一定的了解,因为我们一般在类中使用。

一个例子


关于装饰器是什么,随便一搜都能找到一堆解释。我们让那些看着头疼的名词、定义去一边吃灰,看下面这个例子

class Blog():
    
    def __init__(self,name,title):
        self.author = name
        self.article = title
        self.information = self.author + ' ' + self.article
    
    def url(self):
        return f"The author url is {self.author}.{self.article}.com "


这段代码不难理解吧,定义了一个Blog类,这个类包含authorarticleinformation属性,并拥有一个url方法。

现在我们来创建一个实例

>>> user = Blog('liuzaoqi','Python')


这行代码不难看懂吧,创建了一个user,姓名是liuzaoqi,标题是Python。OK现在来打印一下相关属性

>>> print(user.author)
#liuzaoqi
>>> print(user.article)
#Python
>>> print(user.information)
#liuzaoqi Python
>>> print(user.url())
#The author url is liuzaoqi.Python.com


没问题吧,到目前为止还与装饰器没啥太大关系,现在问题来了,如果我想修改这个userarticle,这样写可以吧

>>> user.article = 'study'
>>> print(user.article)
>>> print(user.information)
>>> print(user.url())


来猜一下结果,我们将article修改了:将'Python'改为'study'

informationurl都与article有关,因此它们都应该随之修改,来看看结果

study
liuzaoqi Python
The author url is liuzaoqi.study.com


你神奇的事情发生了,都是由article生成的,但是只有url修改了,information并没有发生变化,这是因为:在Python中如果我们更改了类中的一个属性的值,那么从刚刚更改的属性生成的其他属性不会自动更新。


那要怎么解决呢?我们注意到url能够正确的改变,那我们将information由属性改为方法不就OK了,因此代码就改成了这样

class Blog():
    
    def __init__(self,name,title):
        self.author = name
        self.article = title
    
    def information(self):
        return self.author + ' ' + self.article
    
    def url(self):
        return f"The author url is {self.author}.{self.article}.com "


能看懂吧,不就是将information由属性改为方法,现在再来试一下


>>> user = Blog('liuzaoqi','Python')
>>> print(user.information())
#liuzaoqi Python
>>> user.article = 'study'
>>> print(user.information())
#liuzaoqi study


还是同样的操作,但是现在information就可以随着article修改而自动更新了。

等等,到这里好像与装饰器没啥关系啊。但是你有没有发现,我们之前调用information使用的是user.information但是现在变成了user.information(),多了一个(),别小瞧这个括号,如果我们正在开发一个大型项目,那么我们这样一修改,哦吼,所有使用了user.information的代码都将崩溃。


这是就需要装饰器登场了,Python中内置装饰器@property可以在方法的定义之前添加装饰器将方法转换为属性

class Blog():
    
    def __init__(self,name,title):
        self.author = name
        self.article = title
    
    @property 
    def information(self):
        return self.author + ' ' + self.article
    
    def url(self):
        return f"The author url is {self.author}.{self.article}.com "


不用仔细看,就加了一句@property在方法上面,OK,现在再来看看

>>> user = Blog('liuzaoqi','Python')
>>> print(user.information)
#liuzaoqi Python
>>> user.article = 'study'
>>> print(user.information)
#liuzaoqi study


现在我们就能使用访问属性的方法来调用information,这就是装饰器,它就是负责把一个方法变成属性调用。但是这是可能还有一个问题,现在修改name、article之后information会自动更新,但是如果我们修改information属性则name和article自动更新吗,就像这样

>>> user.information = 'zaoqi python'
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-57-00cd34ab7d23> in <module>
----> 1 user.information = 'zaoqi python'

AttributeError: can't set attribute


很遗憾,并不能如我们预想的一样,当然解决这个问题并不困难,使用setter/deleter方法就可以,这会在之后的文章中讲解,至少读到这里我们已经学会装饰器是个什么玩意,不是吗?


©著作权归作者所有:来自51CTO博客作者mb5fe18e32e4691的原创作品,如需转载,请注明出处,否则将追究法律责任

更多相关文章

  1. 便捷搭建 Zookeeper 服务器的方法,好用,收藏~
  2. 自学系列 | 就谈自学方法!
  3. php性能优化的方法介绍
  4. PHP操作Redis数据库常用方法(总结)
  5. php中比较两个数组差异的方法
  6. 关于CentOS6.x/6.5/6.4/6.3/6.2/7.x 64位安装php5.2的方法详解
  7. Mac+Apache+PHP安装Xdebug方法步骤
  8. php中常用的正则表达式使用方法
  9. php中mkdir的使用方法介绍

随机推荐

  1. Android(安卓)sdk manager更新 下载API源
  2. 【Android】Android和PHP开发最佳实践完
  3. Android studio--将项目生成为jar包
  4. Android 酷炫 倒计时的实现
  5. android删除android拦截短信并删除该条短
  6. Android之Animation
  7. RK3288[android 7.1]调试笔记 强制横屏
  8. No IDEA annotations attached to the JD
  9. Android:BroadcastReceiver 随记
  10. android开发积累4-android使用HttpURLCon