608 Stimmen

Warum haben einige Funktionen Unterstriche "__" vor und nach dem Funktionsnamen?

Diese "Unterstreichung" scheint häufig aufzutreten, und ich habe mich gefragt, ob dies eine Anforderung in der Sprache Python oder lediglich eine Frage der Konvention war?

Kann mir jemand erklären, bei welchen Funktionen die Unterstriche verwendet werden und warum ( __init__ zum Beispiel)?

11 Stimmen

@AustinHenley: Nicht für doppelte Unterstreichungen vor und nach den Namen. Sie denken dabei nur an Unterstriche vor den Namen.

4 Stimmen

812voto

Michael Burr Punkte 320591

Von der Python PEP 8 -- Style Guide für Python-Code :

Beschreibend: Benennungsstile

Die folgenden Sonderformen mit führenden oder nachgestellten Unterstrichen sind anerkannt (diese können generell mit jeder Groß- und Kleinschreibung kombiniert werden):

  • _single_leading_underscore Schwacher Indikator für "internen Gebrauch". z.B. from M import * importiert keine Objekte, deren Name mit einem Unterstrich beginnt.

  • single_trailing_underscore_ : wird per Konvention verwendet, um Konflikte mit Python-Schlüsselwörtern zu vermeiden, z. B.

    Tkinter.Toplevel(master, class_='ClassName')

  • __double_leading_underscore Bei der Benennung eines Klassenattributs wird die Namensvermischung aufgerufen (innerhalb der Klasse FooBar, __boo wird _FooBar__boo (siehe unten).

  • __double_leading_and_trailing_underscore__ : "magische" Objekte oder Attribute, die in benutzergesteuerten Namensräumen leben. z.B. __init__ , __import__ ou __file__ . Erfinden Sie niemals solche Namen, sondern verwenden Sie sie nur wie dokumentiert.

Beachten Sie, dass Namen mit doppelten führenden und abschließenden Unterstrichen im Wesentlichen für Python selbst reserviert sind: "Erfinde niemals solche Namen; verwende sie nur wie dokumentiert".

14 Stimmen

Raymond erklärt auch, warum Sie das Verhalten der Namensverstümmelung ab etwa 34 Minuten in diesem Video wünschen: youtube.com/watch?v=HTLu2DFOdTg

8 Stimmen

Die Wahl zwischen einfachem und doppeltem Unterstrich in einem Namen ist also ein bisschen wie die Wahl zwischen protected und private in C++ und Java? _single_leading_underscore kann von Kindern geändert werden, aber __double_leading_underscore kann das nicht?

4 Stimmen

__double_leading_underscore es noch öffentlich wird die Variable einfach umbenannt, um eine Kollision zu vermeiden.

89voto

Raymond Hettinger Punkte 197261

Die anderen Befragten haben Recht, wenn sie die doppelten führenden und abschließenden Unterstriche als eine Namenskonvention für "besondere" oder "magische" Methoden bezeichnen.

Während Sie diese Methoden direkt aufrufen können ( [10, 20].__len__() zum Beispiel), ist das Vorhandensein der Unterstriche ein Hinweis darauf, dass diese Methoden indirekt aufgerufen werden sollen ( len([10, 20]) zum Beispiel). Die meisten Python-Operatoren haben eine zugehörige "magische" Methode (zum Beispiel, a[x] ist die übliche Art des Aufrufs von a.__getitem__(x) ).

34voto

Namen, die von doppelten Unterstrichen umgeben sind, sind für Python "besonders". Sie sind in der Liste Python Sprachreferenz, Abschnitt 3, "Datenmodell" .

3 Stimmen

Endlich, ein schneller Hinweis von Google auf den richtigen Teil des Python-Referenzhandbuchs. Vielen Dank dafür.

14voto

Hitesh Sahu Punkte 37527

Ein Beispiel hinzugefügt, um die Verwendung von __ in Python zu verstehen. Hier ist die Liste aller __

https://docs.python.org/3/genindex-all.html#_

Bestimmte Klassen von Bezeichnern (neben Schlüsselwörtern) haben besondere Bedeutungen. Jede Verwendung von * Namen, in einem anderen Zusammenhang, der nicht explizit dokumentierten Gebrauch folgt, unterliegt einem Bruch ohne Warnung

Zugangsbeschränkung mittels __

"""
Identifiers:
-  Contain only (A-z, 0-9, and _ )
-  Start with a lowercase letter or _.
-  Single leading _ :  private
-  Double leading __ :  strong private
-  Start & End  __ : Language defined Special Name of Object/ Method
-  Class names start with an uppercase letter.
-

"""

class BankAccount(object):
    def __init__(self, name, money, password):
        self.name = name            # Public
        self._money = money         # Private : Package Level
        self.__password = password  # Super Private

    def earn_money(self, amount):
        self._money += amount
        print("Salary Received: ", amount, " Updated Balance is: ", self._money)

    def withdraw_money(self, amount):
        self._money -= amount
        print("Money Withdraw: ", amount, " Updated Balance is: ", self._money)

    def show_balance(self):
        print(" Current Balance is: ", self._money)

account = BankAccount("Hitesh", 1000, "PWD")  # Object Initalization

# Method Call
account.earn_money(100)

# Show Balance
print(account.show_balance())

print("PUBLIC ACCESS:", account.name)  # Public Access

# account._money is accessible because it is only hidden by convention
print("PROTECTED ACCESS:", account._money)  # Protected Access

# account.__password will throw error but account._BankAccount__password will not
# because __password is super private
print("PRIVATE ACCESS:", account._BankAccount__password)

# Method Call
account.withdraw_money(200)

# Show Balance
print(account.show_balance())

# account._money is accessible because it is only hidden by convention
print(account._money)  # Protected Access

2 Stimmen

Gibt es einen Ort, an dem die Verwendung von führenden __ als strong private ? Ich sehe es weder in dem verlinkten Dokument noch unter dem Link in diesem Dokument zu __ Kennungen . Einfacher führender Unterstrich ist dort dokumentiert; doppelter führender Unterstrich für private Klassennamen unter Verwendung von Name Mangling ist dort dokumentiert; aber es scheint, dass der Aufruf von __ "superprivat" ist irreführend und kann dazu führen, dass es bei Funktionen auf Dateiebene verwendet wird, wo es meines Wissens eigentlich keine Bedeutung hat.

7voto

Omadbek Onorov Punkte 69

Eigentlich verwende ich _-Methodennamen, wenn ich zwischen Eltern- und Kind-Klassennamen unterscheiden muss. Ich habe einige Codes gelesen, die diese Art der Erstellung von Eltern-Kind-Klassen verwenden. Als Beispiel kann ich diesen Code anbieten:

class ThreadableMixin:
   def start_worker(self):
       threading.Thread(target=self.worker).start()

   def worker(self):
      try:
        self._worker()
    except tornado.web.HTTPError, e:
        self.set_status(e.status_code)
    except:
        logging.error("_worker problem", exc_info=True)
        self.set_status(500)
    tornado.ioloop.IOLoop.instance().add_callback(self.async_callback(self.results))

...

und das Kind, das eine _worker-Methode hat

class Handler(tornado.web.RequestHandler, ThreadableMixin):
   def _worker(self):
      self.res = self.render_string("template.html",
        title = _("Title"),
        data = self.application.db.query("select ... where object_id=%s", self.object_id)
    )

...

1 Stimmen

Ist der doppelte Unterstrich nicht genau dafür gedacht?

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