Un modello di progettazione comune quando si utilizzano i descrittori python consiste nel mantenere il descrittore in un dizionario delle istanze che utilizza tale descrittore. Ad esempio, supponiamo che io voglio fare un attributo che conta il numero di volte che è accessibile:Utilizzo di descrittori in classi non modificabili - python
class CountingAttribute(object):
def __init__(self):
self.count = 0
self.value = None
class MyDescriptor(object):
def __init__(self):
self.instances = {} #instance -> CountingAttribute
def __get__(self, inst, cls):
if inst in self.instances:
ca = self.instances[inst]
else:
ca = CountingAttribute()
self.instances[inst] = ca
ca.count += 1
return ca
class Foo(object):
x = MyDescriptor()
def main():
f = Foo()
f.x
f.x
print("f.x has been accessed %d times (including the one in this print)"%(f.x.count,))
if __name__ == "__main__":
main()
Questo è un esempio del tutto stupido che non fa nulla di utile; Sto cercando di isolare il punto principale.
Il problema è che non posso usare questo descrittore in una classe che non è hashable, perché la linea
self.instances[inst] = ca
utilizza casi come chiave del dizionario. C'è un modo saggio per gestire questo tipo di caso? Ad esempio, si pensa immediatamente di usare l'istanza id
, ma non sono sicuro che se ciò dovesse accadere si interromperà qualcosa su come si suppone che gli hash vengano usati.
EDIT: Mi rendo conto che instances
dovrebbe essere qualcosa come un weakref.WeakKeyDictionary
ma sto cercando di mantenere qui semplice concentrarsi sul problema dell'habhability.
Il mio primo pensiero è stato quello di provare a usare ['WeakKeyDictionary'] (https://docs.python.org/3.4/library/weakref.html#weakref.WeakKeyDictionary) per' instance'. Sfortunatamente, questo non sembra risolvere il problema sottostante di disabilità, ma è comunque una buona idea. (Altrimenti, il descrittore manterrebbe vivo un oggetto altrimenti morto.) – icktoofay
Sì, nella mia implementazione effettiva uso un WeakKeyDictionary. Non l'ho fatto qui perché sto cercando di mantenere l'attenzione sulla domanda in questione. – DanielSank