python装饰器详解

python之装饰器详解

一、装饰器定义

定义一个函数,可以接受一个函数作为参数,对该函数进行一些包装,不改变函数的本身。

二、装饰器四部曲(分解)

1、函数可赋值给变量。若赋值给变量的是调用后的函数,变量的值就是return的返回值。

切记:函数赋值给变量,只看return的值。分清楚函数是处于调用状态还是未被调用状态。若函数没有写return,默认return为None。

例如:

python装饰器详解

解释:把函数foo赋值给a和b,a赋值的是调用后的函数,变量的值就是返回值。b赋值的是调用前的函数,所以b就是那个赋值的函数。函数本身+(),就是调用。

可以用callable判断某个东西是否可以被调用,call是调用的意思,able是“能的”形容词后缀,翻译就是可调用的。b是函数本身,可以被调用,a是函数的结果,不能被调用。

小技巧:

我们可以用.name看一个函数的信息,例如:b函数其实就是‘foo’函数。

python装饰器详解

2、函数可以作为参数传递,在函数内部仍可进行调用。可以将函数在内部定义理解为一个变量在内部定义。

python装饰器详解

解释:我先定义一个函数foo,然后再定义一个函数bar,我调用foo的时候,即foo(),没有设置传递参数,打印了1234.我调用bar的时候,传递了一个函数foo作为参数,即bar(foo),得到的结果就是func(),调用函数本身,所以得到1234的结果。

3、函数可嵌套定义,并可在内部直接调用。且可调用外层函数传递的参数。这一步很关键。

python装饰器详解

解释:内层函数可以调用外层函数传递的参数,f(1234)传递给了内层函数。内层没有找到x变量的值,就要去临近的外层变量寻找。外层传递一个1234,就传递给内层了。最后一行的bar()是在外层函数的内部直接调用内层函数。

函数嵌套定义就是可以把函数看成定义一个变量,类似于b=1,还有就是内层函数可以调用外层函数传递的参数,记住这两点就可以了。

4、函数可以作为return的返回值

python装饰器详解

解释:上面定义了一个函数,下面定义了一个函数返回函数。对变量a进行赋值,可以使用a.__name__看到a的函数名,a就是bar,为什么是bar呢,因为第一条:给变量a赋值的时候,只看return,return的是函数的函数func,所以是bar。

三、组合起来就是装饰器

python装饰器详解

解释:最后的foo就是wrapper,就是deco(foo),是内层函数“g()”,可以用foo.name查看,就是wrapper,callable(foo),可以看到它可以调用。

还有一点,如下图,笔者在学习过程中碰到的一点疑问:

python装饰器详解

上面的三个过程,第一个是给变量赋值的过程,第二个是打印变量的过程,第三个是函数调用的过程。变量赋值看return,不要看他出现什么结果,这个时候就是把return的1赋值给a,所以打印a才会出来1,函数调用的过程,就是执行函数内部程序的过程,函数内部有一个打印,一个return,所以才会出现这样的结果。

这样,我们就很好理解上面的结果了。

python装饰器详解

上面的这个“函数赋值给变量”就是装饰器的核心原理,装饰器接受函数作为参数完成调用,再将返回结果赋值给该函数同名的变量。以后再通过该变量名调用,就是被装饰器装饰过的函数。

四、python装饰器用法:@

python装饰器详解

解释:@deco相当于foo=deco(foo)。

1、内层函数也可以定义参数:

python装饰器详解

解释:参数的传递是先传给wrapper,wrapper在把这个参数传递给func进行调用。wrapper接受的参数的个数要跟foo的一样,我要通过wrapper转给foo。

2、装饰器方法总结:

通常最内层函数的倒数第二层函数,定义接受一个函数参数

装饰器内部嵌套定义了什么函数,就要讲该函数作为return返回值,未调用的。

最内层函数的参数定义最好和传人的参数定义一致,或者使用(*arg,*kwargs)这种可变参数的定义方式。

python装饰器详解

装饰器外层函数只会执行一次。外层的操作执行完成后,就不会再输出了。执行的都是内层函数wrapper。

python装饰器详解

对装饰的函数进行属性传递:被装饰的函数的name,名称,doc注释等等,都无法保留,都是内层函数的,这个时候就要把wrapper的属性改掉,改成我们接受函数的属性。也有一个专门的模块:from functools import wraps。用法@wraps(func)

python装饰器详解

python装饰器详解

nonlocal:python可以使用外部函数变量,无法修改外部函数自身。此时可以用nonlocal关键字标记需要修改的变量就可以修改该变量的值了。例如统计函数的次数:

python装饰器详解

带参数的装饰器:无非就是再加一层,内部可以不用动。如下,增加一个参数123.

python装饰器详解

原创文章,作者:N24_yezi,如若转载,请注明出处:http://www.178linux.com/67878

(11)
N24_yeziN24_yezi
上一篇 2017-02-08 16:15
下一篇 2017-02-08 20:06

相关推荐

  • N28-第三周作业

    1、列出当前系统上所有已经登录的用户的用户名,注意:同一个用户登录多次,则只显示一次即可。
    2、取出最后登录到当前系统的用户的相关信息。
    3、取出当前系统上被用户当作其默认shell的最多的那个shell。
    4、将/etc/passwd中的第三个字段数值最大的后10个用户的信息全部改为大写后保存至/tmp/maxusers.txt文件中。
    5、取出当前主机的IP地址,提示:对ifconfig命令的结果进行切分。
    6、列出/etc目录下所有以.conf结尾的文件的文件名,并将其名字转换为大写后保存至/tmp/etc.conf文件中。
    7、显示/var目录下一级子目录或文件的总个数。
    8、取出/etc/group文件中第三个字段数值最小的10个组的名字。
    9、将/etc/fstab和/etc/issue文件的内容合并为同一个内容后保存至/tmp/etc.test文件中。
    10、请总结描述用户和组管理类命令的使用方法并完成以下练习:
    (1)、创建组distro,其GID为2016;
    (2)、创建用户mandriva, 其ID号为1005;基本组为distro;
    (3)、创建用户mageia,其ID号为1100,家目录为/home/linux;
    (4)、给用户mageia添加密码,密码为mageedu;
    (5)、删除mandriva,但保留其家目录;
    (6)、创建用户slackware,其ID号为2002,基本组为distro,附加组peguin;
    (7)、修改slackware的默认shell为/bin/tcsh;
    (8)、为用户slackware新增附加组admins;

    2017-12-17
  • grep与基本正则表达式基本用法

    正则表达式:Regual Expression  REGEXP      由一类特殊字符及文本字符所编写的模式,其中有些字符不表示其字母意义,而是用于表示控制或通配的功能;       分两类:             &nbsp…

    Linux干货 2016-11-03
  • N25-第5周博客作业

    N25-第5周博客作业 1、显示/boot/grub/grub.conf中以至少一个空白字符开头的行; grep -E "^[[:space:]]+[[:alnum:]]+" /boot/grub/grub.conf    grep "^[[:space:]]…

    Linux干货 2016-12-31
  • samba服务实现:linux和windows之间共享

    1,首先在linux(centos6,7)安装好samba程序:     yum -y install samba   samba-common        主配置文件:/etc/samba/smb.conf   ~]# groupadd share_gro…

    2017-03-05
  • root用户密码破解

    方法一:进入单用户模式破解root密码 (1)编辑grub菜单(选定要编辑的title,而后使用e命令) (2)在选定的kernel后附加 1,s,S或single都可以 (3)在kernel所在行键入"b"命令即可进入单用户模式 (4)运行passwd命令修改root用户密码 并重启 (5)输入密码即可登录 方法二:进入救援模…

    Linux干货 2016-09-15
  • Nginx

        Nginx(发音同engine x)是一个 Web服务器,也可以用作反向代理,负载平衡器和 HTTP缓存。Nginx 可以部署在网络上使用 FastCGI,脚本,SCGI 处理程序,WSGI 应用服务器或 Phusion 乘客模块的动态 HTTP 内容,并可作为软件负载均衡器。Nginx 使…

    Linux干货 2017-08-29

评论列表(1条)

  • luoweiro
    luoweiro 2017-02-23 07:40

    原理分解的很详细,步骤完善。