'id' è un nome variabile errato in Python


141

Perché è male nominare una variabile idin Python?


33
La maggior parte delle persone aggiunge un trattino basso agli identificatori che si scontrano con builtin / parole chiave: id_, map_, list_, filter_, ecc.
cdleary,

3
Una soluzione più subdola sarebbe quella di utilizzare una variabile ID.
Simon Kuang,

46
Una domanda migliore sarebbe ... Quale genio pensava che fosse una buona idea usare un nome così comune e generico per una funzione integrata?
Base il

Risposte:


143

id() è un built-in fondamentale:

Aiuto sulla funzione idintegrata nel modulo __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.)

In generale, utilizzare nomi di variabili che eclissano una parola chiave o una funzione integrata in qualsiasi lingua è una cattiva idea, anche se è consentita.


3
OK, per "id" hai ragione, ma il commento "in generale ..." si applica ancora, non credi?
Kevin Little,

5
Lo eviterei sicuramente per i moduli globali. Per le variabili limitate all'ambito locale, in modo da poter vedere la stessa funzione non sarà mai necessario utilizzare il builtin, non è qualcosa di cui mi preoccuperei.
mercoledì

@Caramdir: buona cattura, è idstato programmato per la rimozione in una sola volta, ma alla fine hanno deciso di non rimuoverlo. Non sono più in grado di modificare il mio commento originale, quindi lo eliminerò per evitare di confondere le persone in futuro.
Eli Courtwright

20
@EliCourtwright Vorrei che lo avessero rimosso. Che metodo mal chiamato! Un nome generico generico usato in migliaia di luoghi (dove il contesto dà significato). Quindi qualcuno ha deciso di usarlo come nome globale dove non c'è contesto?
Base il

2
Sorprendentemente, il tutorial regex di Python di Google ( developers.google.com/edu/python/regular-expressions ) utilizza str = 'an example word:cat!!'. C'è qualcosa in qualcuno dei PEP che dice di non farlo?
parole per il

57

In PEP 8 - Guida allo stile per Python Code , la seguente guida appare nella sezione Descrittiva: Stili di denominazione :

  • single_trailing_underscore_ : utilizzato per convenzione per evitare conflitti con la parola chiave Python, ad es

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

Quindi, per rispondere alla domanda, un esempio che applica questa linea guida è:

id_ = 42

Includere il carattere di sottolineatura finale nel nome della variabile chiarisce l'intento (per coloro che hanno familiarità con la guida in PEP 8).


1
Questo non risponde alla domanda reale, ma +1 per la convenzione di denominazione PEP-8
ege

Un buon consiglio, ma idè un built-in, non una parola chiave, e questo non spiega perché è male ombreggiare un built-in.
wjandrea,

51

idè una funzione integrata che fornisce l'identità di un oggetto (che è anche il suo indirizzo di memoria in CPython). Se nominate una delle vostre funzioni id, dovrete dire builtins.idper ottenere l'originale (o __builtins__.idin CPython). Rinominareid livello globale è fonte di confusione in tutto tranne che in una piccola sceneggiatura.

Tuttavia, riutilizzare i nomi predefiniti come variabili non è poi così male purché l'uso sia locale. Python ha molto funzioni integrate che (1) hanno nomi comuni e (2) non userete molto comunque. Usarli come variabili locali o come membri di un oggetto è OK perché è ovvio dal contesto cosa stai facendo:

Esempio:

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

Alcuni built-in con nomi allettanti:

  • id
  • file
  • list, dict
  • map
  • all, any
  • complex, int
  • dir
  • input
  • slice
  • buffer
  • sum
  • min, max
  • object

8
PEP 8 , che è stato aggiornato il 01-ago-2013, ora consiglia di evitare potenziali confusioni semplicemente aggiungendo _il nome della variabile. Si prega di vedere la mia risposta .
DavidRR,

1
Vale la pena notare che la idfunzione che restituisce l'indirizzo di memoria di un oggetto è un dettaglio dell'implementazione di CPython. Vale anche la pena notare che la funzione è richiesta solo per restituire un numero diverso per due oggetti esistenti . Se un oggetto viene raccolto in modo inutile, il suo ID può essere riciclato.
Zac Crites,

@Zac Grazie! Ho modificato la risposta per aggiungere quel punto sull'indirizzo di memoria e un link in modo che le persone possano leggere di più.
wjandrea,

42

Potrei dire qualcosa di impopolare qui: id()è una funzione integrata piuttosto specializzata che viene raramente utilizzata nella logica aziendale. Pertanto, non vedo alcun problema nell'usarlo come nome di variabile in una funzione ben scritta, in cui è chiaro che id non significa la funzione integrata.


1
In risposta a:> id è una funzione integrata> piuttosto specializzata che viene raramente utilizzata nella> logica aziendale. Quindi non vedo> un problema nell'usarlo come variabile> nome in una funzione> ben scritta>, dove è chiaro che id> non significa la funzione integrata. Anche se questo è vero, è probabilmente una buona idea essere più specifici con questo nome di variabile piuttosto che semplicemente "id". Molte cose hanno ID (specialmente se stai lavorando con un RDBMS), e come dice la seconda riga di The Zen of Python di Tim Peters :> Explicit è meglio di implicito. Guarda il resto correndo:import this
Ross,

9
Lo eviterei comunque, se possibile, comunque. Anche se non altro per non sentire i colleghi lamentarsi. :-)
Jason Baker,

1
Sono completamente d'accordo: nominare una variabile "id" in una piccola funzione (e quindi ambito) è innocuo. Pochissime persone usano idcomunque il builtin. Detto questo, ci è voluto un po 'di tempo quando un collega ha scavalcato l' listintegrato con una variabile locale. Quindi la regola generale menzionata da altre persone ha ancora senso.
silviot,

5

È male nominare una variabile dopo una funzione integrata. Uno dei motivi è perché può essere fonte di confusione per un lettore che non sa che il nome viene ignorato.


2

idè una funzione integrata in Python. L'assegnazione di un valore a idsovrascriverà la funzione. È meglio aggiungere un prefisso come in some_ido usarlo in una diversa maiuscola come inID .

La funzione integrata accetta un singolo argomento e restituisce un numero intero per l'indirizzo di memoria dell'oggetto passato (in CPython).

>>> id(1)
9787760
>>> x = 1
>>> id(x)
9787760

2
nota che puoi nominare un attributo di classe o un metodo 'id', che non toccherà la funzione integrata.
Toni Ruža,


0

Altri hanno detto che è confuso, ma voglio ampliare il perché . Ecco un esempio, basato su una storia vera. Fondamentalmente, scrivo una classe che accetta un idparametro ma poi provo a usare il builtin in idseguito.

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)

Uscita prevista:

Created Employee 'Taylor Swift' at 0x7efde30ae910

Uscita effettiva:

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

Eh? Dove sto cercando di chiamare un int? Quelli sono tutti incorporati ...

Se lo avessi chiamato badge_ido id_, non avrei avuto questo problema.


-6

Poiché python è un linguaggio dinamico, di solito non è una buona idea assegnare una variabile e una funzione allo stesso nome. id () è una funzione in Python, quindi si consiglia di non utilizzare una variabile denominata id. Tenendo presente ciò, questo vale per tutte le funzioni che potresti usare ... una variabile non dovrebbe avere lo stesso nome di una funzione.


3
"Poiché python è un linguaggio dinamico, di solito non è una buona idea assegnare una variabile e una funzione allo stesso nome." - Non è possibile assegnare una variabile e una funzione con lo stesso nome. Niente a che fare con l'essere un linguaggio dinamico. Se intendi dare alle proprietà gli stessi nomi di altri oggetti nello stesso ambito, non sono d'accordo. Potresti avere una classe chiamata "Chiave", un'istanza di quella classe chiamata "chiave" e una proprietà di un altro oggetto chiamato "chiave", ad esempio "door.key".
Purrell,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.