2015-05-28 37 views
2

所以我試圖學會使用Python(2.x)裝飾器,並與他們混亂,我遇到......一個奇怪的事情。總結一下,我想我正在嘗試使用裝飾器將裝飾後的功能添加到其他地方的存儲器中。Python:裝飾器,範圍和模塊導入

我不知道這是否是最辛辣的做任何事情的方式,但我想明白出了什麼問題。

假設我有一個模塊(即我運行一個腳本)是這樣的:

# -*- 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'] 

但是,如果我將全班學生分成單獨的模塊

# -*- 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和手柄的作用域/模塊導入?

+3

你有一個循環導入,讓事情變得非常困難 - 嘗試將mydecorator從'main.py'移出到'module.py'或其他模塊中。 –

+0

謝謝,將所有裝飾器的東西移動到另一個模塊中(從這個意義上說,如果我然後在'main.py'中導入'b','d',它們的內容與第一種情況相同)。所以主要問題是循環導入? – kekkonen

回答

1

問題是循環導入,在module初始化後,字典d和列表b被空列表替換。

您可以通過添加一些打印語句看執行的順序:

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 {} [] 

您可以看到db被重新分配到之後的空列表和字典裝飾器被應用於類定義中。

我真的不能完全弄清楚如何解決這個問題,而不是將裝飾器和db移出主體並進入其自己的模塊來解決循環依賴問題,但我認爲大多數人會同意這種通知如果不嚴格禁止,應儘可能避免進口。