2013-11-01 46 views
0

我有一個設置name變量的方法,但在第一行沒有global name,它使用本地name變量,因此它永遠不會更改全局變量name。 有沒有什麼辦法通過裝潢set_name強迫它使用全球name通過修飾器改變局部變量的作用域?

name = "John" 

def set_name(): 
    name = "Sara" 

def print_name(): 
    global name 
    print(name) 

def decorator(func): 
    def wrapper(*args, **kwargs): 
     ## Problem: 
     # Force set_name to use global 'name' 
     func(*args, **kwargs) 

    return wrapper 

print_name() 
#Output: John 

decorator(set_name)() 

print_name() 
# Prints John, but I want to prints Sara 
+4

也許有某種深的Python魔法做這個,但簡短的答案是否定的。裝飾者不會改變他們包裹的功能。 –

+1

我不認爲你可以這樣做...... tbh我很難看出你爲什麼要這樣做 –

+0

你似乎是用'set_name'和'print_name'方法定義一個類,而沒有實際聲明一個類。 – chepner

回答

2

否,除非裝飾取功能的代碼(字節碼從該函數的代碼對象,或使用inspect源代碼),改變它,創建從所述改變後的代碼的新代碼對象,並用它取代該函數的代碼。當然,這是非常不可靠的,黑客,具體實現和深奧的魔法。只需添加global name(或完全消除全局變量)。

2

簡短的回答是:不。

有點擴展的答案:不,不是以便攜的方式。從技術上講,你可以玩的CPython的字節碼,但

  • ,不會對任何其他解釋器中運行,
  • 沒有人能夠理解的代碼,
  • 頭痛不會是值得的。
0
name = "John" #global name 

和內部set_name名():

name = "Sara" #local name 

要使用全局名稱內部功能set_name()不喜歡:

def set_name(): 
    global name 
    name = "Sara" 
+0

謝謝,但我的意思是裝飾。 – Farhadix

0

定義一個包裝name類:

class Person(object): 
    def __init__(self): 
     self.name = "John" 

    def set_name(self): 
     self.name = "Sara" 

    def print_name(self): 
     print(name) 

p = Person() 
p.print_name() # Prints John 
p.set_name()  # Changes name to Sara 
p.print_name() # Prints Sara 

這樣硬編碼其屬性值的類當然有點愚蠢,但是這證明了類的目的:封裝對其進行操作的數據(name)和函數(set_name, print_name)。

0

不確定,你爲什麼要裝飾二傳手。

你可以做這樣的事,但我不會推薦它作爲編碼的一貫風格:

name = "John" 

def print_name(): 
    print name 

def decorator(func, tmp_name): 
    def wrapper(*args, **kwargs): 
     global name 
     old_name = name 
     name = tmp_name 
     func(*args, **kwargs) 
     name = old_name 
    return wrapper 

print_name() 
decorator(print_name, 'Sarah')() 
print_name() 

輸出:

John 
Sarah 
John