2015-02-09 145 views
1

我設置了一個簡單的遊戲時遇到了問題,從播放器類的實例訪問Game類的實例:Python變量範圍混亂

class Player(): 
    global game 
    print game.board # NameError: name 'game' is not defined 


class Game(): 
    def __init__(self): 
     self.board = range(9) 

    p = Player() 


if __name__ == "__main__": 
    game = Game() 

我敢肯定,這是一個簡單的修復/誤解我部分,但我錯過了什麼?

+1

您不是「從Player類實例訪問Game類實例」。您正在通過Player類定義*訪問它,該類在定義類時執行一次。如果代碼是在Player的一個方法中定義的,這段代碼就可以工作。同樣可疑的是在Game類定義中對Player'p'的類級別引用。您可能需要將其移至Game的'__init__'方法。 – 2015-02-09 04:21:29

+0

它不起作用,因爲當解釋器創建'''Player'''時,''''game'''不存在。你有一個難題,每個類都有對另一個的引用,但是因爲Python是按順序創建對象的,所以不管你如何重新排列定義,總是不會存在。你需要重新考慮設計。 – wwii 2015-02-09 04:39:29

+0

@StevenRumbalski你說得對,game.board訪問是在Player類定義中,而不是一個實例。我一直在考慮一旦Player類實例化它將被訪問,但我的措辭不正確。 – Debugging 2015-02-09 06:17:50

回答

3

解釋器將首先嚐試讓類Player,那麼類Game然後運行代碼。因此,在執行game = Game()之前,將使類Player在當時沒有變量game並導致您的錯誤。

+0

不知道爲什麼這是downvoted ...更正加入我的加號;) – alfasin 2015-02-09 04:15:59

+0

@alfasin謝謝。 – dragon2fly 2015-02-09 04:20:19

+2

@StevenRumbalski當我讀到它時,你和dragon2fly說的是完全一樣的東西。你說的方式更清楚地說明定義一個類和創建一個類的實例之間的區別,但你說的是同樣的東西。 – 2015-02-09 04:36:39

2

更好的方法是,以在初始化一個Game對象「通過」,以Player使用DI(依賴注入):

class Player(object): 
    def __init__(self, game): 
     self.game = game 

    def print_player(self): 
     print self.game.board 


class Game(object): 
    def __init__(self): 
     self.board = range(9) 


if __name__ == "__main__": 
    game = Game() 
    player = Player(game) 
    player.print_player() # prints [0, 1, 2, 3, 4, 5, 6, 7, 8] 

依託globals()not a good practice,因爲它依賴執行順序上(就像你的情況一樣),使得代碼不易讀(你必須從一個地方跳到另一個地方,而不是「流利」地閱讀),以及它可能會帶來副作用。

壞的做法(又名不要在家裏做!):
下面的代碼(雖然這是一個不好的做法),因爲減速的順序將工作當你使用globals()是有意義的: game = Game()應聲明之前Player,以便它在那裏使用:

class Game(): 
    def __init__(self): 
     self.board = range(9) 

game = Game() 

class Player(): 
    global game 
    print game.board 

p = Player() # prints [0, 1, 2, 3, 4, 5, 6, 7, 8] 
+2

@LegoStormtroopr downvote表示「沒有用的答案」。雖然它沒有解釋問題的根源,但它通過編寫更好的代碼來解釋如何避免它。這被你認爲沒用嗎? – alfasin 2015-02-09 04:07:48

+0

@LegoStormtroopr你讀過整個答案嗎? – alfasin 2015-02-09 04:23:21

+1

我知道使用全球是一個壞主意,但行爲仍然讓我感到驚訝。這種傳遞玩家遊戲實例的方法對我來說很奇怪,我認爲球員是比賽的一部分,而不是反過來。我確實知道你在說什麼,謝謝你的反饋。 – Debugging 2015-02-09 06:25:37