马上注册,结交更多好友,享用更多功能^_^
您需要 登录 才可以下载或查看,没有账号?立即注册
x
包结构:
.
├── test_folder
test_folder
├── test_demo
├── test_lib
├── test_run.py
test_demo
├── demo.py
test_lib
├── common.py
test_run的代码如下:import test_folder.test_demo.demo as demo
demo.test()
demo.py的代码如下:import test_folder.test_lib.common as common
l1 = {'a': 1}
@common.test_auth
def test():
print('这是函数内的l1:', l1)
print('这是函数内的l1的内存地址:', id(l1['a']))
return l1
if __name__ == '__main__':
res = test()
print(res)
common.py的代码如下:def test_auth(func):
import test_folder.test_demo.demo as demo
def inner(*args, **kwargs):
if demo.l1['a'] == 1:
demo.l1['a'] = 2
print('这是装饰器内的l1[a]的值:', demo.l1['a'])
print('这是装饰器内的l1:', demo.l1)
print('这是装饰器内的l1的内存地址:', id(demo.l1['a']))
res = func(*args, **kwargs)
return res
else:
res = func(*args, **kwargs)
return res
return inner
直接运行test_run.py的结果如下:
这是装饰器内的l1[a]的值: 2
这是装饰器内的l1: {'a': 2}
这是装饰器内的l1的内存地址: 140730700886304
这是函数内的l1: {'a': 2}
这是函数内的l1的内存地址: 140730700886304
--------装饰器内的l1的值和函数内展示的l1的值一致
直接运行demo.py的结果如下:
这是装饰器内的l1[a]的值: 2
这是装饰器内的l1: {'a': 2}
这是装饰器内的l1的内存地址: 140730700886304
这是函数内的l1: {'a': 1}
这是函数内的l1的内存地址: 140730700886272
{'a': 1}
--------装饰器内的l1的值和函数内展示的l1的值不一致
为什么运行test_run.py的结果和直接运行demo.py跑出来的结果不一致?求各位大佬讲解一下
问题解析:
根据提供的代码,运行 test_run.py脚本和直接运行 demo.py脚本,会得到不同的结果。原因在于函数 test_run.py中导入了装饰器函数 test_auth,而直接运行 demo.py时并没有导入该装饰器函数。
问题原因:
在Python中,模块的导入是一次性的。当一个模块第一次被导入后,它会被缓存起来,再次导入该模块时,Python会直接使用缓存中的对象,而不会再次执行模块的代码。
在 demo.py中,使用了装饰器 @common.test_auth修饰函数 test()。而装饰器是在函数定义阶段就会被调用的,即在 demo.py被导入时就会执行装饰器函数。因此,当直接运行 demo.py时,装饰器会修改 common.py中的 demo.l1['a']的值,导致函数 test()内的 l1字典发生了变化。
但是,当运行 test_run.py时, demo.py是通过模块导入的方式被引入的,此时 demo.py中的代码只会在第一次导入时执行一次,并将其缓存。因此, test_run.py中导入的 demo.py使用的是缓存中的 demo.py模块,而不会再次执行其中的代码。所以在 test_run.py中, demo.py的装饰器函数没有被调用,导致 common.py中的 demo.l1['a']的值没有被修改,从而导致结果不一致。
解决方法:
为了保证结果的一致性,可以考虑将装饰器函数的导入放在函数调用前面,即将 import test_folder.test_lib.common as common语句放在 test()函数之前。
修改后的 demo.py代码如下: import test_folder.test_lib.common as common@common.test_authdef test(): print('这是函数内的l1:', l1) print('这是函数内的l1的内存地址:', id(l1['a'])) return l1l1 = {'a': 1}if __name__ == '__main__': res = test() print(res)
这样修改后,无论通过直接运行 demo.py还是通过导入方式运行 test_run.py,都会得到一致的结果。
希望对你有所帮助!如果还有其他问题,请随时提问。
球一个最佳答案谢谢啦!这对我非常重要!
|