'id' ist ein falscher Variablenname in Python

141

Warum ist es schlecht, eine Variable idin Python zu benennen ?

Brian Buck
quelle
33
Die meisten Leute fügen einen Unterstrich an Bezeichner an, die mit eingebauten / Schlüsselwörtern kollidieren: id_, map_, list_, filter_ usw.
cdleary
3
Eine hinterhältigere Lösung wäre die Verwendung einer Variablen ID.
Simon Kuang
45
Eine bessere Frage wäre ... Welches Genie hielt es für eine gute Idee, einen so gebräuchlichen generischen Namen für eine integrierte Funktion zu verwenden?
Basic

Antworten:

143

id() ist eine grundlegende eingebaute:

Hilfe zur eingebauten Funktion idim Modul __builtin__:

id(...)

    id(object) -> integer

    Return the identity of an object.  This is guaranteed to be unique among
    simultaneously existing objects.  (Hint: it's the object's memory
    address.)

Im Allgemeinen ist die Verwendung von Variablennamen, die ein Schlüsselwort oder eine integrierte Funktion in einer beliebigen Sprache in den Schatten stellen, eine schlechte Idee, selbst wenn dies zulässig ist.

Kevin Little
quelle
3
OK, für 'id' hast du recht, aber der Kommentar "im Allgemeinen ..." gilt immer noch, meinst du nicht auch?
Kevin Little
5
Ich würde es für Modulglobale sicherlich vermeiden. Für Variablen, die auf den lokalen Bereich beschränkt sind, sodass Sie sehen können, dass dieselbe Funktion niemals die integrierte Funktion verwenden muss, würde ich mir darüber keine Sorgen machen.
Bobince
@Caramdir: Guter Fang, idsollte einmal entfernt werden, aber schließlich haben sie beschlossen, ihn nicht zu entfernen. Ich kann meinen ursprünglichen Kommentar nicht mehr bearbeiten, daher werde ich ihn löschen, um künftig keine Verwirrung mehr zu stiften.
Eli Courtwright
19
@ EliCourtwright Ich wünschte, sie hätten es entfernt. Was für eine schlecht benannte Methode! Ein allgemeiner, gebräuchlicher Name, der an Tausenden von Stellen verwendet wird (wo der Kontext Bedeutung gibt). Also hat jemand beschlossen, es als globalen Namen zu verwenden, wo es keinen Kontext gibt?
Basic
2
Erstaunlicherweise wird Googles eigenes Python-Regex-Tutorial ( developer.google.com/edu/python/regular-expressions ) verwendet str = 'an example word:cat!!'. Gibt es irgendetwas in einem der PEPs, das besagt, dass Sie dies nicht tun sollen?
Worte für den
57

In PEP 8 - Style Guide für Python-Code wird die folgende Anleitung im Abschnitt Beschreibend angezeigt : Benennen von Styles :

  • single_trailing_underscore_ : Wird von Konventionen verwendet, um Konflikte mit dem Python-Schlüsselwort zu vermeiden, z

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

Um die Frage zu beantworten, ist ein Beispiel, das diese Richtlinie anwendet, Folgendes:

id_ = 42

Das Einfügen des nachfolgenden Unterstrichs in den Variablennamen macht die Absicht klar (für diejenigen, die mit den Anleitungen in PEP 8 vertraut sind).

DavidRR
quelle
1
Dies beantwortet nicht die eigentliche Frage, sondern +1 für die PEP-8-Namenskonvention
ege
Guter Rat, aber es idist ein eingebautes, kein Schlüsselwort, und dies erklärt nicht, warum es schlecht ist, ein eingebautes zu beschatten.
Wjandrea
51

idist eine integrierte Funktion, die die Identität eines Objekts angibt (die auch seine Speicheradresse in CPython ist). Wenn Sie eine Ihrer Funktionen benennen id, müssen Sie sagen builtins.id, um das Original (oder __builtins__.idin CPython) zu erhalten. Globales Umbenennen idist alles andere als ein kleines Skript verwirrend.

Die Wiederverwendung integrierter Namen als Variablen ist jedoch nicht so schlimm, solange die Verwendung lokal ist. Python hat viele eingebaute Funktionen, die (1) gebräuchliche Namen haben und (2) Sie sowieso nicht viel verwenden werden. Die Verwendung dieser Variablen als lokale Variablen oder als Mitglieder eines Objekts ist in Ordnung, da aus dem Kontext ersichtlich ist, was Sie tun:

Beispiel:

def numbered(filename):
    with open(filename) as file:
        for i, input in enumerate(file):
            print("%s:\t%s" % (i, input), end='')

Einige Einbauten mit verlockenden Namen:

  • id
  • file
  • list, dict
  • map
  • all, any
  • complex, int
  • dir
  • input
  • slice
  • buffer
  • sum
  • min, max
  • object
Nathan Shively-Sanders
quelle
8
In PEP 8 , das am 01. August 2013 aktualisiert wurde, wird jetzt empfohlen, mögliche Verwirrung zu vermeiden, indem einfach _an den Variablennamen angehängt wird. Bitte sehen Sie meine Antwort .
DavidRR
1
Es ist erwähnenswert, dass die idFunktion, die die Speicheradresse eines Objekts zurückgibt, ein CPython-Implementierungsdetail ist. Es ist auch erwähnenswert, dass die Funktion nur für zwei vorhandene Objekte eine andere Nummer zurückgeben muss . Wenn ein Objekt durch Müll gesammelt wird, kann seine ID recycelt werden.
Zac Crites
@ Zac Danke! Ich habe die Antwort bearbeitet, um diesen Punkt über die Speicheradresse und einen Link hinzuzufügen, damit die Leute mehr lesen können.
wjandrea
42

Ich könnte hier etwas Unbeliebtes sagen: id()ist eine ziemlich spezialisierte integrierte Funktion, die in der Geschäftslogik selten verwendet wird. Daher sehe ich kein Problem darin, es als Variablennamen in einer engen und gut geschriebenen Funktion zu verwenden, in der klar ist, dass id nicht die integrierte Funktion bedeutet.

Sebastian Rittau
quelle
1
Als Antwort auf:> id ist eine ziemlich spezialisierte integrierte Funktion, die in der> Geschäftslogik selten verwendet wird. Daher sehe ich kein Problem darin, es als Variablennamen in einer engen und gut geschriebenen Funktion zu verwenden, wenn klar ist, dass id nicht die eingebaute Funktion bedeutet. Während dies wahr ist, ist es wahrscheinlich eine gute Idee, mit diesem Variablennamen spezifischer zu sein als einfach "id". Viele Dinge haben IDs (besonders wenn Sie mit einem RDBMS arbeiten), und wie die zweite Zeile von Tim Peters ' The Zen of Python sagt:> Explizit ist besser als implizit. Sehen Sie den Rest, indem Sie laufen:import this
Ross
9
Ich würde es trotzdem vermeiden, wenn es überhaupt möglich wäre. Auch wenn es keinen anderen Grund gibt, als Mitarbeiter nicht beschweren zu hören. :-)
Jason Baker
1
Ich stimme vollkommen zu: Die Benennung einer Variablen "id" in einer kleinen Funktion (und damit im Bereich) ist harmlos. Sehr wenige Leute benutzen das ideingebaute sowieso. Das heißt, es hat eine Weile gedauert, bis ein Kollege das listeingebaute mit einer lokalen Variablen überschrieben hat. Die allgemeine Regel, die andere Leute erwähnen, ist also immer noch sinnvoll.
Silviot
5

Es ist schlecht, eine Variable nach einer eingebauten Funktion zu benennen. Einer der Gründe ist, dass es für einen Leser verwirrend sein kann, der nicht weiß, dass der Name überschrieben wird.

Toni Ruža
quelle
2

idist eine in Python integrierte Funktion. Durch Zuweisen eines Werts zu idwird die Funktion überschrieben. Es ist am besten, entweder ein Präfix wie in hinzuzufügen some_idoder es in einer anderen Groß- und Kleinschreibung wie in zu verwenden ID.

Die integrierte Funktion verwendet ein einzelnes Argument und gibt eine Ganzzahl für die Speicheradresse des übergebenen Objekts zurück (in CPython).

>>> id(1)
9787760
>>> x = 1
>>> id(x)
9787760
Brian Buck
quelle
2
Beachten Sie, dass Sie ein Klassenattribut oder eine Methode 'id' benennen können, die die integrierte Funktion nicht berührt.
Toni Ruža
0

Weil es der Name einer eingebauten Funktion ist.

Ahockley
quelle
0

Andere haben erwähnt, dass es verwirrend ist, aber ich möchte näher darauf eingehen, warum . Hier ist ein Beispiel, das auf einer wahren Begebenheit basiert. Grundsätzlich schreibe ich eine Klasse, die einen idParameter akzeptiert, aber später versuche, den eingebauten zu verwenden id.

class Employee:
    def __init__(self, name, id):
        """Create employee, with their name and badge id."""
        self.name = name
        self.id = id
        # ... lots more code, making you forget about the parameter names
        print('Created', type(self).__name__, repr(name), 'at', hex(id(self)))

tay = Employee('Taylor Swift', 1985)

Erwartete Ausgabe:

Created Employee 'Taylor Swift' at 0x7efde30ae910

Tatsächliche Ausgabe:

Traceback (most recent call last):
  File "company.py", line 9, in <module>
    tay = Employee('Taylor Swift', 1985)
  File "company.py", line 7, in __init__
    print('Created', type(self).__name__, repr(name), 'at', hex(id(self)))
TypeError: 'int' object is not callable

Huh? Wo versuche ich einen Int aufzurufen? Das sind alles eingebaute ...

Wenn ich es benannt hätte badge_idoder id_, hätte ich dieses Problem nicht gehabt.

wjandrea
quelle
-6

Da Python eine dynamische Sprache ist, ist es normalerweise keine gute Idee, einer Variablen und einer Funktion den gleichen Namen zu geben. id () ist eine Funktion in Python, daher wird empfohlen, keine Variable mit dem Namen id zu verwenden. Vor diesem Hintergrund gilt dies für alle Funktionen, die Sie möglicherweise verwenden. Eine Variable sollte nicht denselben Namen wie eine Funktion haben.

Kitty
quelle
3
"Da Python eine dynamische Sprache ist, ist es normalerweise keine gute Idee, einer Variablen und einer Funktion den gleichen Namen zu geben." - Sie können einer Variablen und einer Funktion nicht denselben Namen geben. Nichts damit zu tun, dass es eine dynamische Sprache ist. Wenn Sie damit meinen, Eigenschaften dieselben Namen wie anderen Objekten im selben Bereich zu geben, bin ich auch anderer Meinung. Möglicherweise haben Sie eine Klasse namens "Key", eine Instanz dieser Klasse namens "key" und eine Eigenschaft eines anderen Objekts namens "key", z. B. "door.key".
Purrell