2016-07-28 13 views
1

Ich bin etwas neu in OOP in Python (und Python im Allgemeinen), und ich stehe auf ein Problem, wenn ich versuche, auf eine private Instanz von Instanzen innerhalb von einem zuzugreifen der Methoden und Verwendung einer Zeichenfolge als Eigenschaftsname.Aufrufen einer privaten Eigenschaft einer Python-Instanz mit einer Zeichenfolge

Das Ziel hier ist im Grunde eine Liste von Eigenschaften, die angezeigt werden (in einem Schlüssel - Wert Format), wenn die Objekte getDetails() -Methode aufgerufen wird. Und es funktioniert gut, solange alle Eigenschaften in der Liste keine privaten Eigenschaften im Objekt sind. Wenn alle Eigenschaften nicht privat sind, dann scheint es gut zu funktionieren.

Im folgenden Beispiel können Sie sehen, ich habe 3 Eigenschaften, foo, _bar und __baz. Im TheClass.getDetails() Verfahren, wenn die __baz Line-Out wird kommentiert, funktioniert es völlig in Ordnung:

class TheClass(object): 
    def __init__(self): 
     self.foo = 'One..' 
     self._bar = 'Two..' 
     self.__baz = 'Three..' 

    def getDetails(self): 
     display = [ 
      'foo' 
      ,'_bar' 
      #,'__baz' 
     ] 

     print "DebugInfo:" 
     for key in display: 
      print '{0:<15}: {1:<20}'.format(key, self.__dict__[ key ] or 'N/A') 

TheClass().getDetails() 

""" Output: 
DebugInfo: 
foo   : One.. 
_bar   : Two.. 
""" 

Allerdings, wenn ich den __baz Eintrag in dem display Array Kommentar-, ich eine Ausnahme erhalten geworfen:

DebugInfo: 
foo   : One.. 
_bar   : Two.. 
Traceback (most recent call last): 
    File "getattr.py", line 18, in <module> 
    TheClass().getDetails() 
    File "getattr.py", line 16, in getDetails 
    print '{0:<15}: {1:<20}'.format(key, self.__dict__[ key ] or 'N/A') 
KeyError: '__baz' 

Ich habe versucht, zu ändern, wie die Eigenschaft referenziert wurde, die self.__dict__[ key ] mit getattr(self, key), aber das hat nur zu dem gleichen Fehler geführt:

DebugInfo: 
foo   : One.. 
_bar   : Two.. 
Traceback (most recent call last): 
    File "getattr.py", line 18, in <module> 
    TheClass().getDetails() 
    File "getattr.py", line 16, in getDetails 
    print '{0:<15}: {1:<20}'.format(key, getattr(self, key) or 'N/A') 
AttributeError: 'TheClass' object has no attribute '__baz' 

Wenn ich nur die Eigenschaften codieren, dann arbeiten, dass offensichtlich gut:

class TheClass(object): 
    def __init__(self): 
     self.foo = 'One..' 
     self._bar = 'Two..' 
     self.__baz = 'Three..' 

    def getDetails(self): 
     print "DebugInfo:" 
     print '{0:<15}: {1:<20}'.format('foo', self.foo or 'N/A') 
     print '{0:<15}: {1:<20}'.format('_bar', self._bar or 'N/A') 
     print '{0:<15}: {1:<20}'.format('__baz', self.__baz or 'N/A') 

TheClass().getDetails() 

""" Output: 
DebugInfo: 
foo   : One.. 
_bar   : Two.. 
__baz   : Three.. 
""" 

Aber ich brauche das ein bisschen mehr Dynamik. Also weiß jemand, ob ein Weg, um das zu funktionieren?

Danke!

P.S. Ich verwende Python 2.7.11

Antwort

1

doppelten Unterstrichen Python aufrufen name-mangling:

>>> class Foo(object): 
... def __init__(self): 
...  self.__private = 1 
... 
>>> f = Foo() 
>>> vars(f) 
{'_Foo__private': 1} 

Sie können sehen, dass es __property-_<classname>__property geändert. Der Grund, warum Python diesen Mangling darstellt, ist, dass der Programmierer Konflikte mit Unterklassen vermeiden kann, die eine Methode mit demselben Namen definieren möchten (aber die Methode in der Basisklasse nicht überschreiben). Also, das ist, wenn Sie sollten Double-Unterstrich Präfix-Attribute verwenden. Wenn Sie diese Situation nicht haben, dann ist es wahrscheinlich besser, wenn Sie nur einzelne Unterstriche verwenden (es ist idiomatischer).

2

Attribute mit einem doppelten Unterstrich (z. B. __foo) sind mangled, um den Zugriff darauf zu erschweren. Die Regeln sind wie folgt:

Since there is a valid use-case for class-private members (namely to avoid name clashes of names with names defined by subclasses), there is limited support for such a mechanism, called name mangling. Any identifier of the form __spam (at least two leading underscores, at most one trailing underscore) is textually replaced with _classname__spam, where classname is the current class name with leading underscore(s) stripped. This mangling is done without regard to the syntactic position of the identifier, as long as it occurs within the definition of a class.

daher in der Lookup-Tabelle, müssen Sie für das Symbol sehen _TheClass__baz statt nur __baz.

Verwandte Themen