對於自項目,我想這樣做:試圖複製Python的字符串實習的功能對於非字符串
class Species(object): # immutable.
def __init__(self, id):
# ... (using id to obtain height and other data from file)
def height(self):
# ...
class Animal(object): # mutable.
def __init__(self, nickname, species_id):
self.nickname = nickname
self.species = Species(id)
def height(self):
return self.species.height()
正如你所看到的,我並不真正需要的多個實例物種(ID)每個ID,但我會創建一個每次我創建一個動物對象與該ID,我可能需要多個呼叫,如Animal(somename, 3)
。
爲了解決這個問題,我想要做的就是讓一個類,以便爲它的兩個實例,讓我們假設A和B,以下是總是正確的:
(a == b) == (a is b)
這事Python使用字符串文字,並且被稱爲實習。例如:
a = "hello"
b = "hello"
print(a is b)
打印將產生真實(只要字符串足夠短,如果我們直接使用python shell)。
我只能猜測CPython如何做到這一點(它可能涉及一些C魔術),所以我正在做我自己的版本。到目前爲止,我已經有了:
class MyClass(object):
myHash = {} # This replicates the intern pool.
def __new__(cls, n): # The default new method returns a new instance
if n in MyClass.myHash:
return MyClass.myHash[n]
self = super(MyClass, cls).__new__(cls)
self.__init(n)
MyClass.myHash[n] = self
return self
# as pointed out on an answer, it's better to avoid initializating the instance
# with __init__, as that one's called even when returning an old instance.
def __init(self, n):
self.n = n
a = MyClass(2)
b = MyClass(2)
print a is b # <<< True
我的問題是:
一)是我的問題,甚至值得解決?因爲我的目標物種物體應該是相當輕的重量和動物可以稱爲最大次數,而非常有限(想象一個口袋妖怪遊戲:不超過1000個實例,上衣)
b)如果是,這是一個有效的方法來解決我的問題? c)如果無效,請您詳細說明一個更簡單/更清潔/更Pythonic的方式來解決這個問題嗎?
你可以看到一個非常類似的代碼排序在Python實現的各種['functools.lru_cache'的封裝](https://hg.python.org/cpython/file/3.5/Lib/functools.py#l453)。碰巧,當完成的工作是原子的時候,他們不會鎖定「原子」操作,這支持了我上面的評論,但他們使用相同的「嘗試從鎖定緩存中獲取,如果失敗,釋放鎖定,執行昂貴工作,重新獲取鎖定並更新緩存(如果沒有競爭)「我上面用於緩存大小的模式是有限的(並且操作組必須以原子方式執行)。 – ShadowRanger