Le dichiarazioni di importazione devono essere sempre nella parte superiore di un modulo?


403

PEP 08 afferma:

Le importazioni vengono sempre inserite nella parte superiore del file, subito dopo i commenti e le istruzioni del modulo e prima dei globuli e delle costanti del modulo.

Tuttavia, se la classe / metodo / funzione che sto importando viene utilizzata solo in rari casi, sicuramente è più efficiente eseguire l'importazione quando è necessario?

Non è questo:

class SomeClass(object):

    def not_often_called(self)
        from datetime import datetime
        self.datetime = datetime.now()

più efficiente di così?

from datetime import datetime

class SomeClass(object):

    def not_often_called(self)
        self.datetime = datetime.now()

Risposte:


283

L'importazione dei moduli è piuttosto veloce, ma non istantanea. Ciò significa che:

  • Mettere le importazioni nella parte superiore del modulo va bene, perché è un costo banale che viene pagato solo una volta.
  • Inserendo le importazioni all'interno di una funzione, le chiamate a tale funzione impiegheranno più tempo.

Quindi, se ti interessa l'efficienza, metti le importazioni in cima. Spostali in una funzione solo se il tuo profilo mostra che sarebbe di aiuto (hai fatto il profilo per vedere dove migliorare al meglio le prestazioni, giusto ??)


Le migliori ragioni che ho visto per eseguire importazioni pigre sono:

  • Supporto libreria opzionale. Se il tuo codice ha più percorsi che utilizzano librerie diverse, non interrompere se non è installata una libreria opzionale.
  • Nel __init__.pydi un plugin, che potrebbe essere importato ma non effettivamente utilizzato. Esempi sono i plugin di Bazaar, che usano bzrlibil framework di caricamento lento.

17
John, questa era una domanda completamente teorica, quindi non avevo alcun codice da profilare. In passato ho sempre seguito il PEP, ma oggi ho scritto un po 'di codice che mi ha fatto chiedere se quella fosse la cosa giusta da fare. Grazie per l'aiuto.
Adam J. Forster,

43
> Inserendo le importazioni all'interno di una funzione, le chiamate a tale funzione impiegheranno più tempo. In realtà, penso che questo costo sia pagato solo per una volta. Ho letto che Python memorizza nella cache un modulo importato in modo che ci sia solo un costo minimo per importarlo di nuovo.
fusione del

24
@halfhourhacks Python non reimporterà il modulo, ma deve comunque eseguire alcune istruzioni solo per vedere se il modulo esiste / è in sys.modules / ecc.
John Millikin,

24
-1. Mettere le importazioni in una funzione non comporta necessariamente un tempo maggiore. Si prega di vedere la mia risposta su un'altra domanda.
aaronasterling

4
Un caso d'uso è evitare le importazioni circolari (di solito non è ragionevole, ma a volte è adatto). A volte la classe A nel modulo m1 chiama un metodo sulla classe B nel modulo m2 che costruisce un'altra istanza della classe A. Se il metodo nella classe B che costruisce un'istanza della classe A ha l'importazione eseguita solo dopo l'esecuzione della funzione che costruisce un'istanza, l'importazione circolare è evitata.
Sam Svenbjorgchristiensensen,

80

Inserendo l'istruzione import all'interno di una funzione è possibile evitare dipendenze circolari. Ad esempio, se si dispone di 2 moduli, X.py e Y.py ed entrambi devono importarsi a vicenda, ciò causerà una dipendenza circolare quando si importa uno dei moduli causando un ciclo infinito. Se si sposta l'istruzione import in uno dei moduli, non tenterà di importare l'altro modulo fino a quando non viene chiamata la funzione e quel modulo sarà già importato, quindi nessun ciclo infinito. Leggi qui per ulteriori informazioni - effbot.org/zone/import-confusion.htm


3
Sì, ma si può entrare nell'inferno delle dipendenze.
eigenein,

8
Se due moduli devono importarsi a vicenda, il codice presenta un problema grave.
Anna,

La programmazione orientata agli oggetti mi porta spesso a dipendenze circolari. Una classe di oggetti vitale può essere importata in diversi moduli. Affinché questo oggetto possa svolgere i propri compiti, potrebbe essere necessario raggiungere uno o più di questi moduli. Esistono modi per evitarlo, come l'invio di dati all'oggetto tramite args di funzione, per consentirgli di accedere all'altro modulo. Ma ci sono momenti in cui questo sembra molto intuitivo per OOP (il mondo esterno non dovrebbe aver bisogno di sapere come sta svolgendo il compito in quella funzione).
Robert,

4
Quando X ha bisogno di Y e Y ha bisogno di X, sono due parti della stessa idea (cioè dovrebbero essere definite insieme) o c'è un'astrazione mancante.
GLRoman

59

Ho adottato la pratica di inserire tutte le importazioni nelle funzioni che le utilizzano, piuttosto che nella parte superiore del modulo.

Il vantaggio che ottengo è la capacità di eseguire il refactoring in modo più affidabile. Quando sposto una funzione da un modulo a un altro, so che la funzione continuerà a funzionare intatta con tutta la sua eredità di test. Se ho le mie importazioni nella parte superiore del modulo, quando sposto una funzione, trovo che finisco per passare molto tempo a rendere le importazioni del nuovo modulo complete e minime. Un IDE refactoring potrebbe renderlo irrilevante.

C'è una penalità di velocità come menzionato altrove. L'ho misurato nella mia domanda e l'ho trovato insignificante per i miei scopi.

È anche bello poter vedere tutte le dipendenze dei moduli in anticipo senza ricorrere alla ricerca (ad es. Grep). Tuttavia, il motivo per cui mi preoccupo delle dipendenze del modulo è generalmente perché sto installando, refactoring o spostando un intero sistema comprendente più file, non solo un singolo modulo. In tal caso, eseguirò comunque una ricerca globale per assicurarmi di disporre delle dipendenze a livello di sistema. Quindi non ho trovato importazioni globali per aiutare la mia comprensione pratica di un sistema.

Di solito metto l'importazione sysall'interno del if __name__=='__main__'controllo e quindi passo argomenti (come sys.argv[1:]) a una main()funzione. Questo mi consente di utilizzare mainin un contesto in cui sysnon è stato importato.


4
Molti IDE semplificano il refactoring del codice ottimizzando e importando automaticamente i moduli necessari nel tuo file. Nella maggior parte dei casi PyCharm ed Eclipse hanno preso le decisioni giuste per me. Scommetto che esiste un modo per ottenere lo stesso comportamento in emacs o vim.
brent.payne,

3
Un'importazione all'interno di un'istruzione if nello spazio dei nomi globale è ancora un'importazione globale. Questo stamperà gli argomenti (usando Python 3): def main(): print(sys.argv); if True: import sys; main();Dovresti avvolgere if __name__=='__main__'una funzione per creare un nuovo spazio dei nomi.
Darcinon,

4
Questo mi sembra un'ottima ragione per importare all'interno di funzioni piuttosto che nell'ambito globale. Sono abbastanza sorpreso che nessun altro abbia mai parlato di farlo per lo stesso motivo. Ci sono aspetti negativi significativi, oltre alle prestazioni e alla verbosità?
Algal

Il lato negativo di @algal è che molte persone pitone lo odiano perché si viola il codice pep. Devi convincere i membri del tuo team. La penalità per le prestazioni è minima. A volte è ancora più veloce, vedi stackoverflow.com/a/4789963/362951
mit

Ho trovato estremamente utile per il refactoring mettere le importazioni vicino a dove le uso. Non è più necessario scorrere in alto e indietro così tanti tim. Uso IDE come Pycharm o Wing Ie e utilizzo anche il loro refactoring, ma non voglio sempre fare affidamento su di essi. Spostare le funzioni su un altro modulo diventa molto più semplice con questo stile di importazione alternativo, di conseguenza rifletto molto di più.
con il

39

Il più delle volte sarebbe utile per chiarezza e ragionevolezza, ma non è sempre così. Di seguito sono riportati alcuni esempi di circostanze in cui le importazioni dei moduli potrebbero risiedere altrove.

Innanzitutto, potresti avere un modulo con un unit test del modulo:

if __name__ == '__main__':
    import foo
    aa = foo.xyz()         # initiate something for the test

In secondo luogo, potrebbe essere necessario importare in modo condizionale alcuni moduli diversi in fase di esecuzione.

if [condition]:
    import foo as plugin_api
else:
    import bar as plugin_api
xx = plugin_api.Plugin()
[...]

Probabilmente ci sono altre situazioni in cui è possibile inserire importazioni in altre parti nel codice.


14

La prima variante è effettivamente più efficiente della seconda quando la funzione viene chiamata zero o una volta. Con la seconda e le successive invocazioni, tuttavia, l'approccio "importa ogni chiamata" è in realtà meno efficiente. Vedi questo link per una tecnica di caricamento lento che combina il meglio di entrambi gli approcci eseguendo una "importazione lenta".

Ma ci sono ragioni diverse dall'efficienza per cui potresti preferire l'una all'altra. Un approccio è quello di rendere molto più chiaro a qualcuno che legge il codice le dipendenze che questo modulo ha. Hanno anche caratteristiche di errore molto diverse: il primo fallirà al momento del caricamento se non c'è un modulo "datetime" mentre il secondo non fallirà fino a quando non viene chiamato il metodo.

Nota aggiunta: In IronPython, le importazioni possono essere un po 'più costose rispetto a CPython perché il codice viene sostanzialmente compilato mentre viene importato.


1
Non è vero che il primo funziona meglio: wiki.python.org/moin/PythonSpeed/…
Jason Baker,

Funziona meglio se il metodo non viene mai chiamato perché l'importazione non avviene mai.
Curt Hagenlocher,

Vero, ma funziona peggio se il metodo viene chiamato più di una volta. E i vantaggi in termini di prestazioni che otterresti non importando immediatamente il modulo sono nella maggior parte dei casi trascurabili. Le eccezioni sarebbero se il modulo è molto grande o ci sono molti di questi tipi di funzioni.
Jason Baker,

Nel mondo IronPython, le importazioni iniziali sono molto più costose rispetto a CPython;). L'esempio "lazy import" nel tuo link è probabilmente la migliore soluzione generica generale.
Curt Hagenlocher,

Spero non ti dispiaccia, ma l'ho modificato nel tuo post. Sono informazioni utili da sapere.
Jason Baker,

9

Curt ha un buon punto: la seconda versione è più chiara e fallirà al momento del caricamento piuttosto che in seguito, e inaspettatamente.

Normalmente non mi preoccupo dell'efficienza del caricamento dei moduli, poiché è (a) piuttosto veloce e (b) si verifica principalmente solo all'avvio.

Se devi caricare moduli pesanti in momenti inaspettati, probabilmente ha più senso caricarli dinamicamente con la __import__funzione, assicurandoti di catturare le ImportErroreccezioni e gestirle in modo ragionevole.


8

Non mi preoccuperei dell'efficienza di caricare troppo il modulo in anticipo. La memoria occupata dal modulo non sarà molto grande (supponendo che sia abbastanza modulare) e il costo di avvio sarà trascurabile.

Nella maggior parte dei casi si desidera caricare i moduli nella parte superiore del file di origine. Per qualcuno che legge il tuo codice, è molto più facile dire quale funzione o oggetto provenga da quale modulo.

Un buon motivo per importare un modulo altrove nel codice è se viene utilizzato in un'istruzione di debug.

Per esempio:

do_something_with_x(x)

Potrei eseguire il debug di questo con:

from pprint import pprint
pprint(x)
do_something_with_x(x)

Naturalmente, l'altro motivo per importare moduli altrove nel codice è se è necessario importarli dinamicamente. Questo perché praticamente non hai scelta.

Non mi preoccuperei dell'efficienza di caricare troppo il modulo in anticipo. La memoria occupata dal modulo non sarà molto grande (supponendo che sia abbastanza modulare) e il costo di avvio sarà trascurabile.


Stiamo parlando di decine di millisecondi di costo di avvio per modulo (sulla mia macchina). Ciò non è sempre trascurabile, ad esempio se influenza la reattività di un'applicazione Web al clic di un utente.
Evgeni Sergeev,

6

È un compromesso, che solo il programmatore può decidere di fare.

Il caso 1 consente di risparmiare un po 'di memoria e tempo di avvio non importando il modulo datetime (e facendo qualsiasi inizializzazione potrebbe richiedere) fino a quando necessario. Notare che fare l'importazione 'solo quando chiamato' significa anche farlo 'ogni volta che viene chiamato', quindi ogni chiamata dopo la prima comporta ancora l'overhead aggiuntivo di fare l'importazione.

Il caso 2 consente di risparmiare un po 'di tempo di esecuzione e latenza importando in anticipo datetime in modo che not_often_called () restituisca più rapidamente quando viene chiamato e anche senza sostenere il sovraccarico di un'importazione su ogni chiamata.

Oltre all'efficienza, è più semplice vedere le dipendenze del modulo in anticipo se le dichiarazioni di importazione sono ... in anticipo. Nasconderli nel codice può rendere più difficile trovare facilmente da quali moduli dipende qualcosa.

Personalmente generalmente seguo il PEP ad eccezione di cose come i test unitari e tali che non voglio essere sempre caricati perché so che non verranno utilizzati tranne il codice di test.


2
-1. Il principale sovraccarico dell'importazione si verifica solo la prima volta. Il costo della ricerca del modulo sys.modulespuò essere facilmente compensato dai risparmi nel solo cercare un nome locale anziché un nome globale.
aaronasterling

6

Ecco un esempio in cui tutte le importazioni sono al top (questa è l'unica volta in cui ho bisogno di farlo). Voglio essere in grado di terminare un sottoprocesso su Un * xe Windows.

import os
# ...
try:
    kill = os.kill  # will raise AttributeError on Windows
    from signal import SIGTERM
    def terminate(process):
        kill(process.pid, SIGTERM)
except (AttributeError, ImportError):
    try:
        from win32api import TerminateProcess  # use win32api if available
        def terminate(process):
            TerminateProcess(int(process._handle), -1)
    except ImportError:
        def terminate(process):
            raise NotImplementedError  # define a dummy function

(Sulla recensione: cosa ha detto John Millikin .)


6

Questo è come molte altre ottimizzazioni: sacrifichi un po 'di leggibilità per la velocità. Come accennato da John, se hai fatto i tuoi compiti di profilazione e hai scoperto che questo è un cambiamento abbastanza significativamente utile e hai bisogno della velocità extra, allora provaci. Probabilmente sarebbe bene mettere un appunto con tutte le altre importazioni:

from foo import bar
from baz import qux
# Note: datetime is imported in SomeClass below

4

L'inizializzazione del modulo avviene una sola volta, alla prima importazione. Se il modulo in questione proviene dalla libreria standard, probabilmente lo importerai anche da altri moduli nel tuo programma. Per un modulo prevalente come il datetime, è anche probabilmente una dipendenza per una serie di altre librerie standard. La dichiarazione di importazione costerebbe molto poco allora poiché l'inizializzazione del modulo sarebbe già avvenuta. A questo punto, tutto ciò che sta facendo è associare l'oggetto modulo esistente all'ambito locale.

Associare queste informazioni all'argomento per la leggibilità e direi che è meglio avere la dichiarazione di importazione nell'ambito del modulo.


4

Solo per completare la risposta di Moe e la domanda originale:

Quando abbiamo a che fare con dipendenze circolari possiamo fare alcuni "trucchi". Supponendo che stiamo lavorando con i moduli a.pye b.pyche contengono x()e B y(), rispettivamente. Poi:

  1. Possiamo spostare uno dei from importsnella parte inferiore del modulo.
  2. Possiamo spostare una delle from importsfunzioni interne o il metodo che richiede effettivamente l'importazione (ciò non è sempre possibile, poiché è possibile utilizzarlo da più punti).
  3. Possiamo modificare uno dei due from importsin modo che sia un'importazione simile a:import a

Quindi, per concludere. Se non hai a che fare con dipendenze circolari e fai qualche trucco per evitarle, allora è meglio mettere tutte le tue importazioni in cima a causa dei motivi già spiegati in altre risposte a questa domanda. E per favore, quando fai questi "trucchi" includi un commento, è sempre il benvenuto! :)


4

Oltre alle eccellenti risposte già fornite, vale la pena notare che il posizionamento delle importazioni non è solo una questione di stile. A volte un modulo ha dipendenze implicite che devono essere importate o inizializzate per prime, e un'importazione di livello superiore potrebbe portare a violazioni dell'ordine di esecuzione richiesto.

Questo problema si presenta spesso nell'API Python di Apache Spark, dove è necessario inizializzare SparkContext prima di importare pacchetti o moduli pyspark. È meglio posizionare le importazioni di pyspark in un ambito in cui è garantito che SparkContext sia disponibile.


4

Sono stato sorpreso di non vedere i numeri di costo effettivi per i ripetuti controlli di carico già pubblicati, anche se ci sono molte buone spiegazioni su cosa aspettarsi.

Se si importa in alto, si prende il carico hit indipendentemente da cosa. È piuttosto piccolo, ma comunemente nei millisecondi, non nei nanosecondi.

Se si importa all'interno di una o più funzioni, si prende il colpo solo per il caricamento se e quando viene chiamata per la prima volta una di quelle funzioni. Come molti hanno sottolineato, se ciò non accade affatto, si risparmia il tempo di caricamento. Ma se la funzione (s) vengono chiamati un sacco, si prende un ripetuto anche se molto più piccolo colpo (per controllare che esso è stato caricato, non per realtà ri-carico). D'altra parte, come ha sottolineato @aaronasterling, si risparmia anche un po 'perché l'importazione all'interno di una funzione consente alla funzione di utilizzare ricerche di variabili locali leggermente più veloci per identificare il nome in un secondo momento ( http://stackoverflow.com/questions/477096/python- import-coding-style / 4789963 # 4789963 ).

Ecco i risultati di un semplice test che importa alcune cose dall'interno di una funzione. I tempi riportati (in Python 2.7.14 su un Intel Core i7 a 2,3 GHz) sono mostrati di seguito (la seconda chiamata che prende più di chiamate successive sembra coerente, anche se non so perché).

 0 foo:   14429.0924 µs
 1 foo:      63.8962 µs
 2 foo:      10.0136 µs
 3 foo:       7.1526 µs
 4 foo:       7.8678 µs
 0 bar:       9.0599 µs
 1 bar:       6.9141 µs
 2 bar:       7.1526 µs
 3 bar:       7.8678 µs
 4 bar:       7.1526 µs

Il codice:

from __future__ import print_function
from time import time

def foo():
    import collections
    import re
    import string
    import math
    import subprocess
    return

def bar():
    import collections
    import re
    import string
    import math
    import subprocess
    return

t0 = time()
for i in xrange(5):
    foo()
    t1 = time()
    print("    %2d foo: %12.4f \xC2\xB5s" % (i, (t1-t0)*1E6))
    t0 = t1
for i in xrange(5):
    bar()
    t1 = time()
    print("    %2d bar: %12.4f \xC2\xB5s" % (i, (t1-t0)*1E6))
    t0 = t1

Le modifiche nel runtime sono probabilmente dovute al ridimensionamento della frequenza della CPU in risposta al carico. È meglio iniziare i test di velocità con un secondo di lavoro intenso per aumentare la velocità di clock della CPU.
Han-Kwang Nienhuys,

3

Non aspiro a fornire una risposta completa, perché altri lo hanno già fatto molto bene. Voglio solo menzionare un caso d'uso quando trovo particolarmente utile importare moduli all'interno di funzioni. La mia applicazione utilizza pacchetti e moduli python memorizzati in determinate posizioni come plugin. Durante l'avvio dell'applicazione, l'applicazione attraversa tutti i moduli nella posizione e li importa, quindi guarda all'interno dei moduli e se trova alcuni punti di montaggio per i plugin (nel mio caso è una sottoclasse di una determinata classe base con un unico ID) li registra. Il numero di plugin è grande (ora dozzine, ma forse centinaia in futuro) e ognuno di essi viene usato abbastanza raramente. Avere importazioni di librerie di terze parti nella parte superiore dei miei moduli plug-in è stato un po 'penalizzante durante l'avvio dell'applicazione. Soprattutto alcune librerie di terze parti sono pesanti da importare (ad esempio l'importazione di plotly cerca anche di connettersi a Internet e scaricare qualcosa che stava aggiungendo circa un secondo all'avvio). Ottimizzando le importazioni (chiamandole solo nelle funzioni in cui vengono utilizzate) nei plugin sono riuscito a ridurre l'avvio da 10 secondi a circa 2 secondi. Questa è una grande differenza per i miei utenti.

Quindi la mia risposta è no, non sempre mettere le importazioni in cima ai tuoi moduli.


3

È interessante notare che finora nessuna risposta ha menzionato l'elaborazione parallela, dove potrebbe essere NECESSARIO che le importazioni siano nella funzione, quando il codice funzione serializzato è ciò che viene trasferito ad altri core, ad esempio come nel caso di ipyparallel.


1

Può esserci un miglioramento delle prestazioni importando variabili / ambito locale all'interno di una funzione. Questo dipende dall'uso della cosa importata all'interno della funzione. Se esegui il loop molte volte e accedi a un oggetto globale del modulo, può essere utile importarlo come local.

test.py

X=10
Y=11
Z=12
def add(i):
  i = i + 10

runlocal.py

from test import add, X, Y, Z

    def callme():
      x=X
      y=Y
      z=Z
      ladd=add 
      for i  in range(100000000):
        ladd(i)
        x+y+z

    callme()

run.py

from test import add, X, Y, Z

def callme():
  for i in range(100000000):
    add(i)
    X+Y+Z

callme()

Un tempo su Linux mostra un piccolo guadagno

/usr/bin/time -f "\t%E real,\t%U user,\t%S sys" python run.py 
    0:17.80 real,   17.77 user, 0.01 sys
/tmp/test$ /usr/bin/time -f "\t%E real,\t%U user,\t%S sys" python runlocal.py 
    0:14.23 real,   14.22 user, 0.01 sys

reale è l'orologio da parete. l'utente è tempo nel programma. sys è il momento delle chiamate di sistema.

https://docs.python.org/3.5/reference/executionmodel.html#resolution-of-names


1

leggibilità

Oltre alle prestazioni di avvio, è necessario creare un argomento di leggibilità per le importdichiarazioni di localizzazione . Ad esempio, prendi i numeri di riga python da 1283 a 1296 nel mio primo progetto python attuale:

listdata.append(['tk font version', font_version])
listdata.append(['Gtk version', str(Gtk.get_major_version())+"."+
                 str(Gtk.get_minor_version())+"."+
                 str(Gtk.get_micro_version())])

import xml.etree.ElementTree as ET

xmltree = ET.parse('/usr/share/gnome/gnome-version.xml')
xmlroot = xmltree.getroot()
result = []
for child in xmlroot:
    result.append(child.text)
listdata.append(['Gnome version', result[0]+"."+result[1]+"."+
                 result[2]+" "+result[3]])

Se la importfrase fosse in cima al file avrei dovuto scorrere molto in alto, o premere Home, per scoprire cosa ETfosse. Quindi dovrei tornare alla riga 1283 per continuare a leggere il codice.

In effetti, anche se l' importistruzione fosse in cima alla funzione (o alla classe) come molti la posizionerebbero, sarebbe richiesto il paging su e giù.

La visualizzazione del numero di versione di Gnome verrà eseguita raramente, quindi la parte importsuperiore del file introduce un ritardo di avvio non necessario.


0

Vorrei citare un mio caso d'uso, molto simile a quelli menzionati da @John Millikin e @VK:

Importazioni opzionali

Faccio analisi dei dati con Jupyter Notebook e utilizzo lo stesso notebook IPython come modello per tutte le analisi. In alcune occasioni, devo importare Tensorflow per eseguire alcune rapide serie di modelli, ma a volte lavoro in luoghi in cui tensorflow non è impostato / è lento da importare. In quei casi, incapsulo le mie operazioni dipendenti da Tensorflow in una funzione di supporto, importando tensorflow all'interno di quella funzione e lo associo a un pulsante.

In questo modo, potrei fare "riavvia-e-esegui-tutto" senza dover attendere l'importazione o riprendere il resto delle celle in caso di errore.


0

Questa è una discussione affascinante. Come molti altri non avevo mai nemmeno preso in considerazione questo argomento. Sono stato costretto a dover importare le funzioni perché volevo usare Django ORM in una delle mie librerie. Dovevo chiamare django.setup()prima di importare le mie classi di modello e poiché questo era all'inizio del file, veniva trascinato in un codice di libreria completamente non Django a causa della costruzione dell'iniettore IoC.

In un certo senso ho hackerato un po 'e ho finito per mettere il django.setup()costruttore singleton e l'importazione rilevante in cima a ogni metodo di classe. Ora questo ha funzionato bene ma mi ha messo a disagio perché le importazioni non erano al top e anche io ho iniziato a preoccuparmi del colpo di tempo in più delle importazioni. Poi sono venuto qui e ho letto con grande interesse che tutti lo prendono.

Ho un lungo background C ++ e ora uso Python / Cython. La mia opinione su questo è che perché non mettere le importazioni nella funzione a meno che non causi un collo di bottiglia profilato. È solo come dichiarare spazio per le variabili appena prima che tu ne abbia bisogno. Il problema è che ho migliaia di righe di codice con tutte le importazioni in alto! Quindi penso che lo farò d'ora in poi e cambierò il file dispari qua e là quando sto passando e avrò il tempo.

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.