Seite 1 von 1

zugriff auf class-variable aus superklasse

Verfasst: Dienstag 27. Februar 2007, 17:19
von Dill
tja, wie macht man das?
(siehe exception unten)

danke schonmal :)

Code: Alles auswählen


class Multiton( object ):
    __instances = {}
    def __new__( cls, key ):
        if not key in cls.__instances:
            cls.__instances[key] = object.__new__(cls, key)
        return cls.__instances[key]
    def __init__(self, key):
        self.key = key
    
    @classmethod
    def debug_instances(cls):
        for k, v in cls.__instances.items():
            print v
    



class MultitonErbe( Multiton ):
    
    #(...)
    
    @classmethod
    def sth_useful(cls):
        for k, v in cls.__instances.items():
            print v

>>> Multiton.debug_instances()
funktioniert!
>>> MultitonErbe.debug_instances()
funktioniert!
>>> MultitonErbe.sth_useful()
(...)
AttributeError: type object 'MultitonErbe' has no attribute '_MultitonErbe__instances'

Verfasst: Dienstag 27. Februar 2007, 17:24
von Leonidas
Die einfachste Lösung: auf Name-Mangling verzichten und aus den ``__instances`` einfach ``_instances`` oder gar nur ``instances`` zu machen.

Verfasst: Dienstag 27. Februar 2007, 17:25
von EyDu

Code: Alles auswählen

class MultitonErbe( Multiton ): 
    
    #(...) 
    
    @classmethod 
    def sth_useful(): 
        for k, v in Multiton .__instances.items(): 
            print v 

Verfasst: Dienstag 27. Februar 2007, 17:31
von Dill
instances sollte schon private sein.

EyDu, mit deiner lösung arbeitet sth_useful() auf den instanzen aller klassen die von multiton erben, das darf nicht.

Verfasst: Dienstag 27. Februar 2007, 19:49
von Leonidas
Dill hat geschrieben:instances sollte schon private sein.
Private gibt es in Python nicht, so ein Mechanismus ist nicht eingebaut. Es gibt nur Name-Mangling oder gar nichts.

Verfasst: Dienstag 27. Februar 2007, 20:08
von Dill
Der Sinn des name mangling bei klassenvariablen ist der schutz der variable.
Und das möchte ich tun.

Wenn du es so genau nimmst, gibt es in Java auch keine privaten variablen (afaik kann man über reflection an die privaten variablen kommen) und in C++ geht das mit sicherheit auch ... wie auch immer ...

Verfasst: Dienstag 27. Februar 2007, 22:05
von BlackJack
Der Sinn des "name mangeling" ist *nicht* Zugriffsschutz, sondern dass der Name in Subklassen wiederverwendet werden kann, ohne das Kollisionen entstehen. Genau das willst Du ja offensichtlich nicht, also nimm keine zwei Unterstriche.

Verfasst: Mittwoch 28. Februar 2007, 01:14
von Dill
hmm gut zu wissen ... da hab ich wohl was falsch verstanden :oops:

...naja also kein wunder, dass das nicht geht :)

Verfasst: Mittwoch 28. Februar 2007, 23:01
von Dill
Hi,


habe jetzt also den doppelten underscore in einen einfachen geändert.
Jetzt gibt aber MultitonErbe.sth_useful() auch die instanzen von
Dummy(Multiton) aus.
Was mache ich falsch?

(ich möchte nicht explizit in sth_useful() testen ob _instances.item() instanz von MutlitonErbe ist.)

Code: Alles auswählen


class Multiton( object ):
    _instances = {}
    def __new__( cls, key ):
        if not key in cls._instances:
            cls.__instances[key] = object.__new__(cls, key)
        return cls._instances[key]
    def __init__(self, key):
        self.key = key
   
    @classmethod
    def debug_instances(cls):
        for k, v in cls._instances.items():
            print v
   

class Dummy( Multiton ):
    pass


class MultitonErbe( Multiton ):
   
    #(...)
   
    @classmethod
    def sth_useful(cls):
        for k, v in cls._instances.items():
            print v 

Verfasst: Donnerstag 1. März 2007, 10:12
von BlackJack
Da schlägt die ganz normale Vererbung zu, die Unterklassen erben `_instances` von `Multiton`. Du kannst das Attribut einfach bei Bedarf erzeugen:

Code: Alles auswählen

class Multiton( object ): 
    # _instances = {} 
    def __new__(cls, key):
        if not hasattr(cls, '_instances'):
            cls._instances = dict()
        if key not in cls._instances:
            cls._instances[key] = object.__new__(cls, key)
        return cls._instances[key]