In Python, se si dispone di un classvar, è accessibile da un'istanza, ma se si imposta la variabile sull'istanza in realtà non cambia il classvar, piuttosto assegna un nuovo nome che ombreggia il valore genitore:
>>> class Foo:
... classvar = 10
...
>>> f = Foo()
>>> (Foo.classvar, f.classvar)
(10, 10)
>>> f.classvar = 30
>>> (Foo.classvar, f.classvar)
(10, 30)
>>> Foo.classvar = 9
>>> (Foo.classvar, f.classvar, Foo().classvar)
(9, 30, 9)
Questo è esattamente simile all'ereditarietà del prototipo in JavaScript:
> var proto = {x: 10};
> function Bar() { }
> Bar.prototype = proto;
> var b = new Bar();
> [proto.x, b.x]
[10, 10]
> b.x = 30
> [proto.x, b.x]
[10, 30]
> proto.x = 9
> [proto.x, b.x, (new Bar()).x]
[9, 30, 9]
Naturalmente, se il bambino modifica il valore , viene visualizzato nel genitore, poiché la variabile non è stata nuovamente assegnata e quindi non si è verificato alcuno shadowing:
>>> class Foo:
... classvar = [10]
...
>>> f = Foo(); f.classvar
[10]
>>> f.classvar[0] = 30
>>> (Foo.classvar, f.classvar)
([30], [30])
La mia domanda è: c'è qualche buona ragione per questo? Sembra che sarebbe meno un "getcha" se la semantica di assegnazione fosse "assegna a qualsiasi genitore se il valore esiste lì, altrimenti crea il nuovo valore".
Te lo chiedo perché sto progettando la mia lingua e, non appena avrò scelto cosa sia la semantica, mi chiederò se dovrei rompere dalla mandria e fare quello che sembra meno di un trucchetto.