首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Python:装饰器、作用域和模块导入

Python:装饰器、作用域和模块导入
EN

Stack Overflow用户
提问于 2015-05-28 16:58:57
回答 1查看 298关注 0票数 2

因此,我正在尝试学习如何使用Python2.x装饰器,在与它们打交道时,我遇到了一些奇怪的事情。总之,我想我正在尝试使用一个装饰器来将装饰函数添加到其他地方的存储中。

我不知道这是否是做任何事情的最毕不过的方式,但我想了解哪里出了问题。

假设我有一个模块(作为脚本运行),如下所示:

代码语言:javascript
复制
# -*- 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()

印刷品如预期:

代码语言:javascript
复制
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']

但是,如果我将类移动到单独的模块中

代码语言:javascript
复制
# -*- coding: utf-8 -*-
# module.py

from main import mydecorator

class AnotherClass:
    @mydecorator('boo')
    def not_workin_func(self, params):
        # do stuff
        pass

并在main.py中导入

代码语言:javascript
复制
# -*- 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()

列表和dict中的更改不会持久:

代码语言:javascript
复制
and here {} ['boo']
in here {'boo': <function not_workin_func at 0x7fd1009917d0>} ['boo']
out there {} []

我认为这与python如何处理作用域/模块导入有关吗?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2015-05-28 17:33:40

问题是循环导入,在初始化d和list b之后,字典module和list b被替换为空列表。

您可以通过添加一些print语句来查看执行顺序:

module.py:

代码语言:javascript
复制
# -*- 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:

代码语言:javascript
复制
# -*- 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时,您可以看到按什么顺序发生的情况:

代码语言:javascript
复制
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 {} []

您可以看到,在类定义中应用了装饰符之后,db被重新分配到空列表和字典中。

老实说,除了将装饰器、db从main转移到自己的模块中以解决循环依赖之外,我实在想不出如何解决这个问题,但我认为大多数人都会同意,应该尽可能避免循环导入,如果不是严格禁止的话。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/30512766

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档