54 Stimmen

Python "geschützte" Attribute

Wie kann ich von einer Unterklasse aus auf ein privates Attribut einer übergeordneten Klasse zugreifen (ohne es öffentlich zu machen)?

104voto

Ed. Punkte 449

Mein Verständnis der Python-Konvention ist

  • _Mitglied ist geschützt
  • __Mitglied ist privat

Optionen für den Fall, dass Sie die übergeordnete Klasse kontrollieren

  • Geschützt statt privat denn das scheint das zu sein, was Sie wirklich wollen
  • Verwenden Sie einen Getter (@property def _protected_access_to_member...), um den geschützten Zugriff zu begrenzen

Wenn Sie es nicht kontrollieren

  • Machen Sie die Namensverwechslung rückgängig. Wenn Sie dir(object) aufrufen, werden Sie Namen sehen etwas wie _Class__member, was was Python tut, um __ zu "es privat machen". Es gibt keine wirklich privat in Python. Dies wird wahrscheinlich als böse angesehen.

65voto

Lutz Prechelt Punkte 32254

Zwei Philosophien des Schutzes

Einige Sprachdesigner gehen von folgender Annahme aus:

"Viele Programmierer sind unverantwortlich, schwachsinnig oder beides".

Diese Sprachentwickler werden sich versucht fühlen, die Programmierer voreinander zu schützen, indem sie eine private Spezifizierer in ihre Sprache aufzunehmen. Kurze Zeit später erkennen sie, dass dies oft zu unflexibel ist und führen protected auch.

Sprachentwickler wie Guido van Rossum von Python gehen dagegen davon aus, dass Programmierer verantwortungsbewusste Erwachsene sind, die zu einem guten Urteil fähig sind (vielleicht nicht immer, aber in der Regel). Sie sind der Meinung, dass jeder in der Lage sein sollte, auf die Elemente eines Programms zuzugreifen, wenn dies erforderlich ist, so dass die Sprache dem richtigen Handeln nicht im Wege steht. (Die einzige Programmiersprache, die dem richtigen Handeln zuverlässig im Weg steht, ist mauvais Sache ist die NULL Sprache)

Deshalb, _myfield in Python bedeutet so etwas wie "Der Designer dieses Moduls macht einige nicht offensichtliche Dinge mit diesem Attribut, also ändern Sie es bitte nicht und halten Sie sich davon fern, es überhaupt zu lesen, wenn Sie können -- geeignete Wege, um auf relevante Informationen zuzugreifen, wurden bereitgestellt (so hoffen wir)."

Falls Sie nicht in der Lage sind, sich vom Zugriff auf _myfield (z. B. in speziellen Fällen in einer Unterklasse), greifen Sie einfach darauf zu.

18voto

kn3l Punkte 18187

Verwendung von @property y @name.setter zu tun, was Sie wollen

z.B.

class Stock(object):

    def __init__(self, stockName):

        # '_' is just a convention and does nothing
        self.__stockName  = stockName   # private now

    @property # when you do Stock.name, it will call this function
    def name(self):
        return self.__stockName

    @name.setter # when you do Stock.name = x, it will call this function
    def name(self, name):
        self.__stockName = name

if __name__ == "__main__":
      myStock = Stock("stock111")

      myStock.__stockName  # It is private. You can't access it.

      #Now you can myStock.name
      N = float(raw_input("input to your stock: " + str(myStock.name)+" ? "))

14voto

Noam Manos Punkte 12442

Keiner scheint die ursprüngliche Frage zu beantworten

wie man von einer Unterklasse aus auf ein privates Attribut einer übergeordneten Klasse zugreift

Hier ist also ein einfacher Anwendungsfall, der zwei Optionen demonstriert - Zugriff auf die übergeordnete Klasse __private Variablen und mit @Eigenschaftsdekorator :

class Family:

    def __init__(self, name):
        self.__family_name = name

    @property
    def name(self):
        return self.__family_name

class Child(Family):

    def __init__(self, first_name, last_name):
        super(Child, self).__init__(last_name)
        self.__child_name = first_name

    @property
    def name(self):
        return (self.__child_name, super(Child, self).name)

if __name__ == '__main__':
    my_child = Child("Albert", "Einstein")

    # print (my_child.__child_name)         # AttributeError - trying to access private attribute '__child_name'
    # print (my_child.__family_name)        # AttributeError - trying to access private attribute '__family_name'
    print (my_child._Child__child_name)     # Prints "Albert" - By accessing __child_name of Child sub-class
    print (my_child._Family__family_name)   # Prints "Einstein" - By accessing __family_name in Family super-class
    print (" ".join(my_child.name))         # Prints "Albert Einstein" - By using @property decorators in Child and Family

4voto

Wenn der Variablenname "__secret" und der Klassenname "MyClass" lautet, können Sie auf eine Instanz namens "var" wie folgt zugreifen

var._MyClass__secret

Die Konvention, um einen Schutz zu suggerieren/emulieren, ist die Benennung mit einem führenden Unterstrich: self._protected_variable = 10

Natürlich kann es jeder ändern, wenn er wirklich will.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X