2012-03-30 87 views
6

是否可以向模塊添加屬性和特殊方法?我想定義一個模塊,以便導入它的行爲類似於一個類實例,並且該實體充當類定義。基本上,這是爲了避免醜陋的語法:模塊可以有屬性嗎?

import game 
if game.Game().paused: 
    print("The game is paused") 

E.g.遊戲模塊是這樣的:

_Speed = 1 

@property 
def paused(): 
    return _Speed == 0 

,並用它的文件:

import game 
if game.paused: 
    print("The game is paused") 

而且,是可以定義特殊的方法(如__call__)?

要清楚,我沒有區分類/實例方法,因爲我將game.Game用作單例/ borg類。

我已經使用@property進行了測試並定義了__bool__,但都沒有按照我所希望的那樣行事。

編輯(爲什麼我想用一個屬性信息):

我有一個屬性game.speed,功能game.paused()和功能game.pause(bool)。基本上,我有一個臨時變量,用於在遊戲暫停時存儲遊戲速度。當遊戲暫停時,私人速度變量被設置爲零。我不希望用戶看到速度爲零,並且能夠在遊戲暫停時修改速度,以便在遊戲恢復時使用新速度。

+2

爲什麼不直接使用'from game import Game'? – 2012-03-30 05:09:37

+0

屬性如何工作?元類?元類如何引用Game類? – Darthfett 2012-03-30 05:11:52

+2

我在說,如果你使用'from ... import'語法,你*不需要模塊上的*屬性。使用你的模塊的人不會期望它有屬性,所以如果你從模塊中刪除屬性,並且只需在你自己的代碼中使用'form ... import',你將獲得相同的可讀性,但是你的API會更好符合其他程序員的期望,這是一件好事。 – 2012-03-30 05:14:22

回答

11

的Python Soemthing不關心什麼是在sys.modules實際上是一個模塊。所以你可以:

# game.py 
class Game(object): 
    pass 

import sys 
sys.modules["game"] = Game() 

現在其他模塊import game將得到Game實例,而不是原來的模塊。

我不知道我推薦它,但它會做你想做的。

+4

哇。這是一些黑魔法。 – bukzor 2012-03-30 06:09:42

+0

太好了,謝謝! :) – Darthfett 2012-03-30 06:10:43

+1

它有一定的意義。畢竟,模塊本身就是一個類的實例('types.ModuleType')。實際上,你可以將你的'Game'類寫成模塊類型的子類,實例化它,然後你就可以擁有基本上是模塊的東西。但正如我所說,Python實際上並沒有檢查類型。 – kindall 2012-03-30 06:17:10

0

我不認爲這是行得通的。您需要多次導入模塊,Python將不止一次執行其內容。這將重新設置速度變量。我認爲你最好使用存儲遊戲狀態的單個Game類。它還會讓您的代碼更清晰易懂。

+0

我希望模塊被執行一次,我遇到的問題是創建一個屬性接口「已暫停」。 – Darthfett 2012-03-30 05:24:59

+0

這就是爲什麼你的方法不起作用。你需要一個具有屬性的類來存儲或計算狀態 – 2012-03-30 05:37:26

+0

我不反對擁有一個類,如果我不必將它用作singleton/borg,並且每次我想要使用一個實例時都創建一個實例值。 – Darthfett 2012-03-30 05:52:39

2

看來你想避免通過模塊訪問項目。這很容易做到。

這兩者是等價的:

import game 
if game.Game().paused: 
    print("The game is paused") 

from game import Game 
if Game().paused: 
    print("The game is paused") 

那好吧,這個怎麼樣:

# game.py 

class Game(object): 
    @property 
    def paused(): 
     return True 

game = Game() 

# from your module 
from game import game 
game.paused 
+0

這個語法很醜。它需要我編寫一個類來使用單例/ borg模式,方法將引用成員的方法稱爲'self。*'或'Game。*',並且(對於borg模式)使用初始化方法hack(避免每次調用'__init__'時重新設置成員)。 – Darthfett 2012-03-30 05:28:10

+0

爲了迴應你的第二個問題,這是我一開始想要做的事情,但是當我有遊戲需要一個模塊時,結果是有問題的,然後該模塊需要遊戲中的類實例。它給你一個這樣的錯誤:'ImportError:無法導入名稱遊戲' – Darthfett 2012-03-30 05:50:20

+0

@Darthfett循環依賴?或者我誤解了你?遊戲進口X和X進口遊戲? – 2012-03-30 05:53:21

3

如果你正在尋找的是你提到的語法,那麼你可以定義一個類和使用類級別的屬性

a1.py

class Game(object): 
    paused = True 


>>> from a1 import Game 
>>> Game.paused 
True 
>>> Game.paused = False 
>>> Game.paused 
False 

那麼,當你問到關於Properties on Class,那麼你可以做一些與屬性裝飾器和classmethod。這樣

class ClassProperty(property): 
    def __get__(self, cls, owner): 
     return self.fget.__get__(None, owner)() 

class Game(object): 
    stage = True 
    @ClassProperty 
    @classmethod 
    def paused(cls): 
     return Game.stage == True 

>>> from a1 import Game 
>>> Game.paused 
True 
+0

問題在於使用屬性。我想'暫停'計算,因爲它永遠不會被存儲。 – Darthfett 2012-03-30 05:23:40

+0

@Darthfett - 明白了。更新了我的答案。 – 2012-03-30 05:33:38

+1

根據你連接的答案,它不適用於setter。我試圖給出一個[SSCCE](http://sscce.org/)這就是爲什麼我沒有提到這一點,但我也需要其他成員的遊戲引擎。 – Darthfett 2012-03-30 05:43:50

相關問題