2016-07-18 94 views
20

Qual è la convenzione in base a PEP 8 per la scrittura di variabili che identificano i nomi di classe (non le istanze)?Python: nome classe PEP 8 come variabile

Vale a dire, date due classi, A e B, quale delle seguenti affermazioni sarebbe quella giusta?

target_class = A if some_condition else B 
instance = target_class() 

o

TargetClass = A if some_condition else B 
instance = TargetClass() 


Come indicato nella guida di stile,

nomi di classe:

nomi di classe devono normalmente utilizzare la convenzione CapWords.

Ma anche

Nomi dei metodi e variabili di istanza:

Utilizzare la funzione di regole di denominazione: minuscola con le parole separate da underscore se necessario per migliorare la leggibilità.

A mio parere, queste due convenzioni si scontrano e non riesco a trovare quale prevalga.

+3

classi di uso CamelCase. Nomi di variabili (istanze) use_underscore_lower_case –

+2

Perché non l'hai [solo cercato] (https://www.python.org/dev/peps/pep-0008/#class-names)? – jonrsharpe

+4

@jonrsharpe l'ho fatto, ma continuo a trovarlo poco chiaro. I nomi di classe dovrebbero normalmente utilizzare la convenzione CapWords, ok, ma le variabili no. Queste due convenzioni si scontrano, secondo me, quindi non so quale prevalga. – LostMyGlasses

risposta

11

In mancanza di uno specifico rivestimento di questo caso PEP 8, si può compensare un argomento per entrambi i lati della medaglia:

Un lato è: Come A e B due variabili pure, ma tenere un riferimento a una classe, utilizzare CamelCase (TargetClass) in questo caso.

Nulla vi impedisce di fare

class A: pass 
class B: pass 
x = A 
A = B 
B = x 

Ora A e B punto alla rispettivamente altra classe, quindi non sono in realtà fissato alla classe.

Quindi A e B hanno l'unica responsabilità di tenere una classe (non importa se hanno lo stesso nome o una diversa), e così ha TargetClass.


Per rimanere imparziale, abbiamo così può sostenere in altro modo: A e B sono speciali nella misura in cui vengono creati insieme con le loro classi, e interni le classi avere lo stesso nome. Finora sono una specie di "originale", qualsiasi altro compito dovrebbe essere contrassegnato come speciale nella misura in cui devono essere visti come variabili e quindi in lower_case.


La verità si trova, come così spesso, da qualche parte nel mezzo. Ci sono casi in cui vorrei andare da una parte e altri dove andrei dall'altra parte.

Esempio 1: Si passa una classe, che forse dovrebbe essere un'istanza, un metodo o una funzione:

def create_new_one(cls): 
    return cls() 

class A: pass 
class B: pass 

print(create_new_one(A)) 

In questo caso, è chiaramente cls stato molto provvisorio e chiaramente una variabile; può essere diverso ad ogni chiamata Quindi dovrebbe essere lower_case.

Esempio 2: aliasing di una classe

class OldAPI: pass 
class NewAPI: pass 
class ThirdAPI: pass 
CurrentAPI = ThirdAPI 

In questo caso, CurrentAPI deve essere visto come una sorta di alias per l'altro e rimane costante durante l'esecuzione del programma. Qui preferirei CamelCase.

+0

Vedo che la decisione è presa dalla tua opinione (che IMO ha senso), ma non è completamente convincente. L'opzione opposta è anche ben difesa nei commenti. – LostMyGlasses

+0

@LostMyGlasses Ora mostro entrambi i lati non corretti e mostro quando userei l'uno e quando l'altro. – glglgl

+0

Penso che entrambi i casi siano ben spiegati, e visto che si tratta di una decisione personale, i tuoi consigli sono utili. Grazie! – LostMyGlasses

1

Personalmente penso che la variabile che hai menzionato, che contiene un riferimento a una classe, sia definita come una variabile temporanea (ad esempio in una procedura o funzione) o come una derivazione da una classe esistente nello spettro globale abbia il maggior peso nel caso in cui ne venga usato uno. Quindi, per riassumere dalla risposta sopra:

  • Se la variabile è temporanea, ad es. all'interno di una funzione o utilizzato in una singola istanza nella risoluzione di un problema, dovrebbe essere lower_case con la separazione del carattere di sottolineatura.

  • Se la variabile si trova all'interno dello spettro globale ed è definita insieme alle altre classi come alias o derivazione da utilizzare per creare oggetti nel corpo del programma, è necessario definirla utilizzando CamelCase.

1

In caso di dubbio, farei lo stesso come sviluppatori Python. Hanno scritto il PEP-8 dopo tutto.

Si può considerare la vostra linea:

target_class = A if some_condition else B 

come una forma in linea del modello:

target_class = target_class_factory() 

e c'è un esempio ben noto per esso nella libreria Python, il namedtuple, che utilizza CamelCase.

+0

Wow, questo è un buon esempio. Tuttavia, mi piacerebbe sapere non solo _how_ per farlo, ma anche _why_. – LostMyGlasses

0

ho finalmente trovato un po 'di luce nel style guide:

nomi di classe

[...]

La convenzione di denominazione per le funzioni, possono essere usati nei casi in cui l'interfaccia è documentato e usato principalmente come un callable.

possono essere utilizzati non è una dichiarazione forte, ma copre il caso, come variabile era destinato ad essere utilizzato come richiamabile.

Così, per uso generale penso che

target_class = A if some_condition else B 
instance = target_class() 

è meglio di

TargetClass = A if some_condition else B 
instance = TargetClass() 
Problemi correlati