![](/img/trans.png)
[英]Python - Calling Variable From (Static) Method of One Class in Method of Another Class
[英]calling class/static method from class variable in python
我正在嘗試使ImageLoader類處理圖像資源的加載和處理,如下所示:
class ImageLoader:
TileTable = __loadTileTable('image path', some other variable)
@staticmethod
def _loadTileTable(arg1, arg2):
blah blah
但是,在編譯時我得到: NameError: name '_loadTileTable' is not defined
如果我用TileTable = ImageLoader.__loadTileTable('image path', some other variable)
替換第二行,那么我得到NameError: name 'ImageLoader' is not defined
當我從C#轉到Python時,靜態類的靜態類就是我用來實現它的。 但是,我對如何在python中執行此操作持開放態度(即,僅通過其功能將調用靜態庫函數組合在一起)。
更新:閱讀完兩個答案后,我得到一張照片,我正在嘗試做的事情可能不對。 我將如何改變ImageLoader,以便我可以這樣做:
假設tile表返回了一個數組
module1.py
aTile = ImageLoader.TileTable[1]
module2.py
anotherTile = ImageLoader.TileTable[2]
理想情況下,我只會填充一次TileTable。
更新:
感謝所有的答案,我找到了我在python模塊doco中只填充一次TileTable的最后答案
“模塊可以包含可執行語句和函數定義。這些語句用於初始化模塊。它們僅在模塊第一次導入時才執行”
至於靜態類,我將放棄類並只創建一個模塊級變量。
回答剛才更新的問題,你在Python中做的是讓TileTable
成為名為tile_table
的模塊中名為imageloader
的變量。 完全沒有理由把它放在一個類中。
那么你得到:
module1.py
import imageloader
aTile = imageloader.tile_table[1]
module2.py
import imageloader
anotherTile = imageloader.tile_table[2]
和imageload.py看起來像:
def _loadTileTable(arg1, arg2):
pass # blah blah
tile_table = _loadTileTable('image path', other_var)
可以將Python模塊視為其他語言中的單例實例(事實上它就是這樣),並且您將能夠將其與從其他語言繼承的任何OO預先概念進行協調。
在Python中,首先執行類塊中的代碼,然后將生成的命名空間傳遞給類初始化程序。 你寫的代碼也可以寫成:
TileTable = _loadTileTable(arg1, arg2)
@staticmethod
def _loadTileTable(arg1, arg2):
pass # blah blah
ImageLoader = type('ImageLoader', (), {'TileTable': TileTable, '_loadTileTable': _loadTileTable})
del TileTable
del _loadTileTable
如您所見,_loadTileTable的調用出現在它的定義之前。 在您的示例中,在類定義中,對_loadTileTable的調用必須在_loadTileTable的定義之后。
一種可能的解決方法是簡單地重新安排類定義。
class ImageLoader:
def _loadTileTable(arg1, arg2):
pass # blah, blah
TileTable = _loadTileTable('image path', other_var)
請注意,我刪除了'staticmethod',因為在調用_loadTileTable時,它被稱為函數而不是方法。 如果您確實希望它在類初始化后可用,則可以在事后將其定義為靜態方法。
class ImageLoader:
def _loadTileTable(arg1, arg2):
pass # blah, blah
TileTable = _loadTileTable('image path', other_var)
_loadTileTable = staticmethod(_loadTileTable)
更新的類級變量是一件壞事,壞事。 我們的默認期望是對象實例是有狀態的,而類是無狀態的。
在這種情況下,我們試圖“神奇地”將一個集合初始化為一個類變量,這是一個非常糟糕的主意。 集合只是一個具有簡單實例級屬性的對象。
神奇的Tile Table不應該是ImageLoader的隱藏靜態部分。 沒有可能的原因。 如果您想避免多次加載它,它應該是ImageLoader的參數。
將它們分開可提高可測試性。 這不是武斷的。 這是單元測試的完成方式。
你想要的是這個。
class ImageLoader( object ):
def __init__( self, theTileTable ):
self.tile_table= theTileTable
class TileTable( object ):
def __init__( self, path, some_other_arg ):
self.tileTable= self._loadTileTable( path, some_other_arg )
def _loadTileTable(arg1, arg2):
blah blah
沒有任何靜態。 獨立單位。 更容易測試。 沒有奇怪的依賴。 沒有魔法。
您是否有使用靜態方法的設計原因? 如果是這樣,因為你沒有重載類初始化,你需要在方法定義之后聲明變量。
但是,如果你這樣做,你會得到一個新的錯誤:
NameError: name 'arg1' is not defined
這樣做的原因是因為您在類被實例化之前在類中執行該方法,因此您永遠不會有機會將參數傳遞給該方法。
因此,執行此操作的正確方法是重載__init__()
方法,以便僅在構造類時才發生對TileTable
賦值:
class ImageLoader(object):
def __init__(self, arg1, arg2):
self.TileTable = self._loadTileTable(arg1, arg2)
@staticmethod
def _loadTileTable(arg1, arg2):
print arg1, arg2
這使您能夠在沒有實例的情況下調用ImageLoader._loadTileTable()
,但是它還允許您在創建實例時創建TileTable
實例變量。
使用Class方法
在回應我關於可能需要類方法的評論時,這里有一個例子涵蓋了這個:
class ImageLoader:
@classmethod
def _loadTileTable(cls, arg1, arg2):
return arg1, arg2
# We're creating the class variable outside of the class definition. If you're doing
# this in a module, no one will ever notice.
ImageLoader.TileTable = ImageLoader._loadTileTable('foo', 'bar')
我不知道可能有更好的方法來做到這一點。 但我認為這涵蓋了您所尋找的內容:
>>> i = ImageLoader()
>>> i
<__main__.ImageLoader instance at 0x100488f80>
>>> ImageLoader.TileTable
('foo', 'bar')
>>> i.TileTable
('foo', 'bar')
在那里你有一個可以訪問類變量的實例i
,但是ImageLoader.TileTable
仍然可以從類對象中獲得,而不需要實例。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.