Python Enclosing作用域、闭包、装饰器话聊上篇
admin
2023-07-31 01:47:37
0

Python Enclosing作用域、闭包、装饰器话聊上篇

Jaglawz: 听讲Python一切都是对象,是吗?

Pylego: 是的,像函数也是对象。

Jaglawz: 那么函数也可以有自己的属性了?

Pylego: 当然,像下面这样写是可以的:

def foo():
    print(\'I am foo\')
    
def bar():
    print(\'I am bar\')
    
foo.bar = bar
foo.bar()

Jaglawz: 这都行,那是不是函数也可以像普通对象一样当作参数传递也可以当作对象来返回?

Pylego: 是的,比如下面的用法:

def deco(func):
    string = \'I am deco\'
    def wrapper():
        print(string)
        func()
    return wrapper
    

def foo():
    print(\'I am foo\')
    
    
foo = deco(foo)
foo()  
\"\"\"
输出:
I am deco
Iam foo
\"\"\"

Jaglawz: 好吧,当作参数传递和返回我理解了,但是我对wrapper函数的print(string)这个string的查找感到迷惑。

Pylego: 不错嘛!这都被你看出来了,那你知道Python作用域的LEGB原则吗?

Jaglawz: 我知道是知道可以我就是对那个E(Enclosing)作用域不是很理解。

Pylego: 那就对了,你可以在刚才代码的基础上运行下面的代码:

print(foo.__closure__)
# 输出:(, )

Jaglawz: 咦,这两个内存地址是啥家伙?

Pyelgo: 这就是wrapper函数引用的外层函数(就是deco函数啦)的两个变量:string和func啊!

Jaglawz: 也就是说内层函数(在本例中就是wrapper啦)会把外层函数(在本例用就是deco啦)作用域里面的对象放到__closure__属性里,以供自己查找?

Pylego: 是的,但是不是所有外层函数作用域的对象都会放到内层函数的__closure__属性里,仅限自己用到的,这个__closure__就是enclosing作用域啦!

Jaglawz: 原来enclosing作用域是这样的,明白了。

Pyelgo: 如果内部函数引用到外层函数作用域的对象,这个内部函数就称为闭包。

Jaglawz: 原来闭包就是这家伙,很简单嘛!

Jaglawz: 咦,我想到内部函数有一个妙用,你看看是不是这样啊,比如说我想输出一个函数的运行时间又不想去破坏这个函数的代码,是不是可以这样写:

import time


def time_machine(func):
    def wrapper(*args, **kwargs):
        start_time = time.time()
        func(*args, **kwargs)
        print(u\'共耗时: %s秒\' % (time.time()-start_time))
    return wrapper
    
    
def foo():
    time.sleep(3)
    
    
foo = time_machine(foo)
foo()

Pylego: 你这智商要冲出宇宙的节奏啊!但是Python的开发者早就想到每次foo = time_machine(foo)很麻烦,特地为你准备了语法糖,来接糖:

import time


def time_machine(func):
    def wrapper(*args, **kwargs):
        start_time = time.time()
        func(*args, **kwargs)
        print(u\'共耗时: %s秒\' % (time.time()-start_time))
    return wrapper
    

@time_machine
def foo():
    time.sleep(3)

\"\"\"
也就是说:
@time_machine
def foo():
    pass
相当于: foo = time_machine(foo),这里是重点,这里是重点,这里是重点,以后的谈话能不能理解就看你对这个语句可理解!
\"\"\"

foo()

Pylego: time_machine就是装饰器(decorator),名字起得多形象啊,装饰函数嘛!

Jaglawz: 你这么一说,我就觉得装饰器咋这么简单呢!问题是我看到很多人的装饰器还带参数,还有人用类当装饰器,这又是咋回事呢?

Pylego: 你问题咋恁些?我先吃个饭,下次有空再聊哈!

相关内容

热门资讯

Mobi、epub格式电子书如... 在wps里全局设置里有一个文件关联,打开,勾选电子书文件选项就可以了。
定时清理删除C:\Progra... C:\Program Files (x86)下面很多scoped_dir开头的文件夹 写个批处理 定...
scoped_dir32_70... 一台虚拟机C盘总是莫名奇妙的空间用完,导致很多软件没法再运行。经过仔细检查发现是C:\Program...
500 行 Python 代码... 语法分析器描述了一个句子的语法结构,用来帮助其他的应用进行推理。自然语言引入了很多意外的歧义,以我们...
小程序支付时提示:appid和... [Q]小程序支付时提示:appid和mch_id不匹配 [A]小程序和微信支付没有进行关联,访问“小...
pycparser 是一个用... `pycparser` 是一个用 Python 编写的 C 语言解析器。它可以用来解析 C 代码并构...
微信小程序使用slider实现... 众所周知哈,微信小程序里面的音频播放是没有进度条的,但最近有个项目呢,客户要求音频要有进度条控制,所...
65536是2的几次方 计算2... 65536是2的16次方:65536=2⁶ 65536是256的2次方:65536=256 6553...
Apache Doris 2.... 亲爱的社区小伙伴们,我们很高兴地向大家宣布,Apache Doris 2.0.0 版本已于...
项目管理和工程管理的区别 项目管理 项目管理,顾名思义就是专注于开发和完成项目的管理,以实现目标并满足成功标准和项目要求。 工...