Scegli dinamicamente se usare __slots__ in una classe

0

Ho una classe contenitore generica:

from typing import Container, Generic, TypeVar, NamedTuple
import sys


fixed_typing = (sys.version_info >= (3, 6, 2) or 
                (3, 5, 3) <= sys.version_info < (3, 6))
T = TypeVar("T")
_Interval = NamedTuple("_Interval", [("start", int),
                                     ("stop", int),
                                     ("data", T)])

class Interval(_Interval, Container, Generic[T]):

    if fixed_typing:
        __slots__ = ()

    ...

Come potresti aver notato, c'è un interruttore che controlla l'utilizzo di __slots__ durante l'inizializzazione della classe. Fondamentalmente, mi piacerebbe utilizzare gli slot quando possibile, ma le versioni precedenti del modulo typing non supportano gli slot nelle classi generiche a causa di un errore . Va bene usare l'interruttore dal punto di vista della progettazione del codice? Non l'ho mai visto prima, ecco perché mi sto chiedendo. Lo trovo simile a controllare i flag del compilatore usando il preprocessore in C / C ++, che è una cosa comune da fare.

    
posta Eli Korvigo 04.09.2017 - 11:58
fonte

2 risposte

3

Da un lato, questo funziona e fa esattamente ciò che dice. Quindi sei già in vantaggio su una notevole quantità di codice reale su quel fronte.

D'altra parte, hai intenzione di aggiungere rami extra come questo per ogni bug che risolvono in Python? Probabilmente non ne vale la pena, francamente. La maggior parte degli utenti che eseguono 3.5.x, ad esempio, dovrebbe avere 3.5.3+, altrimenti i loro distributori avrebbero dovuto eseguire il backport di questa e altre correzioni di bug. Se qualcuno si lamenta che il tuo codice non funziona su 3.5.2, è del tutto ragionevole indirizzarlo al bug Python. Se non si desidera mettere in primo piano tali reclami, è possibile aggiungere un controllo di versione al punto di ingresso del programma e eseguire il fail-fast con un messaggio di errore ragionevole. Dato che alcuni distributori possono eseguire manualmente il backport delle correzioni alle vecchie versioni di Python, questo può o non può essere una decisione progettuale ideale, a seconda del pubblico di destinazione e della piattaforma (ad esempio, gli utenti Windows utilizzeranno in genere una versione "di riserva" di Python , mentre gli utenti Linux hanno maggiori probabilità di ottenere Python dal repository del pacchetto della loro distribuzione).

In terzo luogo, perché hai bisogno di __slots__ in primo luogo? Nella maggior parte dei casi, non lo fai. Nella maggior parte dei casi in cui ne hai bisogno, non puoi semplicemente tirarlo fuori per risolvere un bug. Allora, perché è lì?

Sulla mano quarta , in base al nome della tua classe e delle sue variabili, sembra che stai implementando nuovamente range() , che ha già un metodo __contains__() veloce . Ciò che davvero mi confonde, però, è questa variabile data . Sembra che tu stia cercando di raggruppare un range() insieme ad un oggetto arbitrario. Se è così, probabilmente vuoi la composizione piuttosto che l'ereditarietà. Ma in entrambi i casi, questa è una scelta sbagliata di nome.

    
risposta data 04.09.2017 - 16:58
fonte
1

È abbastanza ragionevole aspettarsi che le persone aggiornino la loro versione di python all'ultima versione della stessa versione secondaria. Ad esempio, dire alle persone di passare dal 3.5.3 al 3.5.4 o dal 3.6.1 al 3.6.2. In tal caso, farei qualcosa di simile a:

assert (sys.version_info >= (3, 6, 2) or 
                (3, 5, 3) <= sys.version_info < (3, 6)), "Your version of python is buggy! Please upgrade!"
    
risposta data 04.09.2017 - 17:18
fonte

Leggi altre domande sui tag