Python:装饰器、作用域和模块导入
Python: Decorators, scoping and module imports
所以我在努力学习使用Python (2.x) 装饰器,在和它们打交道的过程中,我遇到了...一个奇怪的事情。总而言之,我想我正在尝试使用装饰器将装饰函数添加到其他地方的存储中。
我不知道这是否是最 Pythonic 的做事方式,但我想了解哪里出了问题。
假设我有一个像这样的模块(我 运行 作为脚本):
# -*- coding: utf-8 -*-
# main.py
d = {}
b = []
def mydecorator(name):
b.append(name)
def decorator(fun):
d[name] = fun
print 'in here', d, b
return fun
print 'and here', d, b
return decorator
class SomeClass:
@mydecorator('a thing')
def working_func(self, params):
# do stuff
pass
def main():
# do stuff
print 'out there', d, b
if __name__ == '__main__':
main()
按预期打印:
and here {} ['a thing']
in here {'a thing': <function working_func at 0x7fd6b69e0758>} ['a thing']
out there {'a thing': <function working_func at 0x7fd6b69e0758>} ['a thing']
但是,如果我将 class 移动到一个单独的模块中
# -*- coding: utf-8 -*-
# module.py
from main import mydecorator
class AnotherClass:
@mydecorator('boo')
def not_workin_func(self, params):
# do stuff
pass
并将其导入 main.py
# -*- coding: utf-8 -*-
# main.py
import module
d = {}
b = []
def mydecorator(name):
b.append(name)
def decorator(fun):
d[name] = fun
print 'in here', d, b
return fun
print 'and here', d, b
return decorator
def main():
# do stuff
print 'out there', d, b
if __name__ == '__main__':
main()
列表和字典中的更改不会持久化:
and here {} ['boo']
in here {'boo': <function not_workin_func at 0x7fd1009917d0>} ['boo']
out there {} []
我想这与 python 处理作用域/模块导入的方式有关?
问题是循环导入,字典 d
和列表 b
在 module
初始化后被空列表替换。
你可以通过添加一些打印语句来查看执行顺序:
module.py:
# -*- coding: utf-8 -*-
# module.py
print(' module - init')
print(' module - importing from main')
from main import mydecorator
#import main
print(' module - definiting class')
class AnotherClass:
@mydecorator('boo')
def not_workin_func(self, params):
# do stuff
pass
main.py:
# -*- coding: utf-8 -*-
# main.py
print('main - importing module')
import module
print('main - making empty d,b')
d = {}
b = []
print('main - definiting mydecorator')
def mydecorator(name):
b.append(name)
def decorator(fun):
d[name] = fun
print 'in here', d, b
return fun
print 'and here', d, b
return decorator
print('main - defining main')
def main():
# do stuff
print 'out there', d, b
if __name__ == '__main__':
print('main - running main')
main()
现在当您 运行 python main.py
时,您可以看到按什么顺序发生的事情:
main - importing module
module - init
module - importing from main
main - importing module
main - making empty d,b
main - definiting mydecorator
main - defining main
module - definiting class
and here {} ['boo']
in here {'boo': <function not_workin_func at 0x100ca4aa0>} ['boo']
main - making empty d,b
main - definiting mydecorator
main - defining main
main - running main
out there {} []
您可以看到 d
和 b
被重新分配给空列表和字典 在 装饰器被应用到 class 定义之后.
老实说,除了将装饰器和 d
和 b
移出 main 并移入其自己的模块以解决循环依赖之外,我真的不知道如何解决这个问题,但是我想大多数人都会同意,如果不是严格禁止的话,应该尽可能避免循环导入。
所以我在努力学习使用Python (2.x) 装饰器,在和它们打交道的过程中,我遇到了...一个奇怪的事情。总而言之,我想我正在尝试使用装饰器将装饰函数添加到其他地方的存储中。
我不知道这是否是最 Pythonic 的做事方式,但我想了解哪里出了问题。
假设我有一个像这样的模块(我 运行 作为脚本):
# -*- coding: utf-8 -*-
# main.py
d = {}
b = []
def mydecorator(name):
b.append(name)
def decorator(fun):
d[name] = fun
print 'in here', d, b
return fun
print 'and here', d, b
return decorator
class SomeClass:
@mydecorator('a thing')
def working_func(self, params):
# do stuff
pass
def main():
# do stuff
print 'out there', d, b
if __name__ == '__main__':
main()
按预期打印:
and here {} ['a thing']
in here {'a thing': <function working_func at 0x7fd6b69e0758>} ['a thing']
out there {'a thing': <function working_func at 0x7fd6b69e0758>} ['a thing']
但是,如果我将 class 移动到一个单独的模块中
# -*- coding: utf-8 -*-
# module.py
from main import mydecorator
class AnotherClass:
@mydecorator('boo')
def not_workin_func(self, params):
# do stuff
pass
并将其导入 main.py
# -*- coding: utf-8 -*-
# main.py
import module
d = {}
b = []
def mydecorator(name):
b.append(name)
def decorator(fun):
d[name] = fun
print 'in here', d, b
return fun
print 'and here', d, b
return decorator
def main():
# do stuff
print 'out there', d, b
if __name__ == '__main__':
main()
列表和字典中的更改不会持久化:
and here {} ['boo']
in here {'boo': <function not_workin_func at 0x7fd1009917d0>} ['boo']
out there {} []
我想这与 python 处理作用域/模块导入的方式有关?
问题是循环导入,字典 d
和列表 b
在 module
初始化后被空列表替换。
你可以通过添加一些打印语句来查看执行顺序:
module.py:
# -*- coding: utf-8 -*-
# module.py
print(' module - init')
print(' module - importing from main')
from main import mydecorator
#import main
print(' module - definiting class')
class AnotherClass:
@mydecorator('boo')
def not_workin_func(self, params):
# do stuff
pass
main.py:
# -*- coding: utf-8 -*-
# main.py
print('main - importing module')
import module
print('main - making empty d,b')
d = {}
b = []
print('main - definiting mydecorator')
def mydecorator(name):
b.append(name)
def decorator(fun):
d[name] = fun
print 'in here', d, b
return fun
print 'and here', d, b
return decorator
print('main - defining main')
def main():
# do stuff
print 'out there', d, b
if __name__ == '__main__':
print('main - running main')
main()
现在当您 运行 python main.py
时,您可以看到按什么顺序发生的事情:
main - importing module
module - init
module - importing from main
main - importing module
main - making empty d,b
main - definiting mydecorator
main - defining main
module - definiting class
and here {} ['boo']
in here {'boo': <function not_workin_func at 0x100ca4aa0>} ['boo']
main - making empty d,b
main - definiting mydecorator
main - defining main
main - running main
out there {} []
您可以看到 d
和 b
被重新分配给空列表和字典 在 装饰器被应用到 class 定义之后.
老实说,除了将装饰器和 d
和 b
移出 main 并移入其自己的模块以解决循环依赖之外,我真的不知道如何解决这个问题,但是我想大多数人都会同意,如果不是严格禁止的话,应该尽可能避免循环导入。