Întrebări frecvente, Python 3 pentru începători și începători

Unii nu sunt foarte evidente, cu care se confruntă programatori Python novice.

De ce primesc o excepție UnboundLocalError, cu toate că variabila are o valoare?

Poate părea surprinzător UnboundLocalError primi un cod care rulează anterior, care a fost adăugat într-o operațiune de atribuire undeva în cadrul funcției.

Acesta funcționează, dar codul de mai jos:

Aceasta duce la UnboundLocalError:

Acest lucru se datorează faptului că, atunci când atribuiți o variabilă în domeniul de aplicare, acesta devine un local din zonă și ascunde celelalte variabile ale aceluiași nume în regiunile exterioare.

Când ultima instrucțiune în foo atribuie o nouă valoare a variabilei x. compilatorul decide că este o variabilă locală. Prin urmare, atunci când încercări anterioare de a imprima pentru a imprima o variabilă neinitializate, apare o eroare.

În exemplul de mai sus, puteți accesa variabila prin declararea acesteia la nivel mondial:

Puteți face un lucru similar în domeniul de aplicare imbricate folosind cuvântul cheie nelocal:

Care sunt regulile pentru variabilele globale și locale în Python?

În Python, variabilele care se face referire numai în cadrul funcției sunt luate în considerare la nivel mondial. În cazul în care variabila i se atribuie o valoare nouă oriunde în corpul funcției, se consideră că este locală, și dacă aveți nevoie, trebuie să specificați în mod explicit la nivel mondial sa.

Deși este un pic surprinzătoare la prima vedere, este ușor de explicat. Pe de o parte, cererea de variabile globale atribuite previne efectele secundare nedorite în bar. Pe de altă parte, în cazul în care la nivel mondial a fost obligatorie pentru toate link-urile la nivel mondial, trebuie să utilizați la nivel mondial tot timpul. Tu ar trebui să declare ca la nivel mondial în fiecare trimitere la funcția sau modul de a importa componentele built-in.

De ce funcții anonime (lambda), definite în ciclul, cu valori diferite, returnează același rezultat?

De exemplu, scrieți următorul cod:

Acest lucru vă oferă o listă cu 5 funcții, ia în considerare x ** 2. Se poate aștepta ca, fiind numit, se întorc, respectiv, 0, 1, 4, 9 și 16. Cu toate acestea, veți vedea că toate acestea se întoarcă 16:

Acest lucru se întâmplă pentru că x nu este locală lambda. așa cum este definit în regiunea exterioară a vizibilității și se obține atunci când este invocată - dar nu și atunci când aceasta este determinată.

La finalul ciclului, x = 4. astfel încât toate funcțiile se întoarcă 4 ** 2. care este, 16. Acesta poate fi, de asemenea, verificată prin modificarea valorii lui x, si uita-te la rezultatele:

Pentru a evita acest lucru, trebuie să păstreze valorile variabilelor la nivel local:

Aici, n = x funcție creează o variabilă n locală și se calculează în momentul definirii funcției:

Acest lucru este valabil nu numai anonim, precum și funcțiile obișnuite.

Cum de a organiza accesul partajat la variabile globale pentru mai multe module?

Modul canonic de a organiza un astfel de acces - este de a crea un modul separat (adesea numit de configurare sau CFG). Trebuie doar să adăugați config de import în fiecare modul de aplicare. În acest caz, modulul este pus la dispoziție prin intermediul unui nume la nivel mondial. Deoarece există doar o singură instanță a modulului, modificările efectuate în modulul se reflectă peste tot. De exemplu:

Din aceleași motive, modulele pot fi utilizate ca bază pentru punerea în aplicare a Singleton.

Cum se utilizează importul?

În cazurile generale, nu se folosesc de la modulename de import *. Polueaza spațiul de nume de care importă. Unii oameni evita acest idiom, chiar și pentru câteva module care au fost proiectate în conformitate cu așa-importate. Acestea sunt module, cum ar fi Tkinter și filetare.

Modulele de import la începutul fișierului. Ea răspunde la întrebarea, ce module sunt cerute de codul și dacă numele modulului în domeniul de aplicare. Înregistrarea o linie de import facilitează adăugarea și eliminarea declarațiilor de import, dar mai multe importuri va ocupa mai puțin spațiu pe ecran.

O bună practică dacă importați module în următoarea ordine:

  • Modulele standard de bibliotecă (de exemplu, sys, os, getopt, re)
  • parte plug-in-uri (toate care este setat la directorul de site-pachete) - de exemplu, PIL, NumPy, etc.
  • module create la nivel local

Uneori ai nevoie pentru a pune funcția sau clasa de import, pentru a evita problemele cu importurile circulare. Gordon Mcmillan recomandă:

import Ciclic funcționează bine în cazul în care ambele module folosesc un formular de import . Dar ei nu reușesc atunci când al doilea modul dorește să preia numele primul (de la nume de modul de import), iar importurile este la nivelul exterior. Acest lucru se datorează faptului că primele nume de module nu sunt încă disponibile, astfel încât primul modul este ocupat de import al doilea.

În acest caz, în cazul în care al doilea modul este utilizat într-o singură funcție, importul poate fi ușor plasat în această funcție. Până în momentul în care este invocată, primul modul de inițializare a terminat și al doilea modul va efectua importurile sale.

Ar putea fi necesar să se mute importurile de la începutul fișierului în cazul în care unul dintre modulele de dependente platformei. În acest caz, importul tuturor modulelor la începutul fișierului nu va fi posibilă. În această situație, o soluție bună este de a importa modulele necesare în codul dependent de platforma corespunzătoare.

Carry importul de domenii imbricate, cum ar fi definirea funcțiilor numai în cazul în care vă confruntați cu o problemă, cum ar fi de import ciclice, sau dacă încercați pentru a reduce timpul inițializarea modulului.

Această tehnică este utilă în cazul în care o mulțime de importuri nu sunt necesare, și în funcție de modul în care programul va fi executat. Puteți pune, de asemenea, funcția de import, în cazul în care anumite module sunt utilizate numai în această funcție. Rețineți că, pentru a încărca modulul pentru prima dată, poate fi costisitoare din cauza întârzierii în inițializarea modulului, cu toate acestea, încărcare repetată „liber“, acestea sunt doar câteva căutări în dicționare. Chiar dacă numele modulului a dispărut din domeniul de aplicare, modulul probabil, este încă în sys.modules.

De ce sunt valori implicite împărțite între obiecte?

Acest tip de eroare este comună printre începători. Să presupunem că funcția:

Prima dată când apelați funcția, mydict conține o singură valoare. A doua oară, mydict elementul 2 cuprinde, ca atunci când foo () începe să curgă, mydict deja conține elementul.

De multe ori, este de așteptat ca apelul funcției creează noi obiecte la valorile implicite. Dar acest lucru nu este cazul. Valorile implicite sunt create doar o singură dată, atunci când funcția este definită. În cazul în care obiectul este schimbat, ca un dicționar în exemplul nostru, apelurile ulterioare la funcția va utiliza obiectul modificat.

Prin definiție, imuabil obiecte (numere, siruri de caractere, tuple și nici unul), sunt sigure pentru a schimba. Schimbarea obiecte modificabile, cum ar fi dicționare, liste și instanțe de clasă personalizată poate duce la consecințe neașteptate.

Prin urmare, o bună practică este de a nu folosi obiecte modificabile ca valori implicite. În schimb, utilizați nici unul și în interiorul funcției, verificați argumentul la None și de a crea o nouă listă / dicționar. De exemplu, nu scrie:

Cu toate acestea, această caracteristică poate fi utilă. Când aveți o funcție care este realizată pentru o lungă perioadă de timp, tehnica de multe ori folosite - parametrii de memorare în cache și rezultatul fiecărui apel de funcție:

Cum pot trece parametrii opționali sau cuvinte cheie de la o funcție la alta?

Obține acești parametri, puteți utiliza * și ** specifiers în lista de argumente funcționale; returnează tuplu de argumente poziționale și un dicționar de parametri cu nume. Apoi le puteți transfera la o altă funcție, folosind un apel * și **:

De ce această schimbare în lista de „y“ se schimbă, de asemenea, lista de „x“?

Dacă ai scris codul:

ați putea fi surprins de faptul că adăugarea de y, de asemenea, modificări cu x.

Două fapte conduc la următorul rezultat:

  • Variabile - este doar o referință la un obiect. y = x nu creează o copie a listei - este pur și simplu creează o variabila y. care se referă la același obiect, ca x.
  • Listele sunt mutabile.

După apelarea adăugați. Conținutul obiectului a fost schimbat de la [] până la [10]. Deoarece x și y se referă la același obiect, utilizați oricare dintre ele ne [10] dă.

Dacă vom folosi obiecte imuabile:

putem vedea că x și y nu mai sunt egale, deoarece numerele sunt imuabile, iar x = x + 1 nu se schimba numărul 5 prin creșterea. In schimb, se creează un nou obiect 6 și atribuit variabilei x (de exemplu, schimbarea care obiect referințe x). După aceea avem 2 obiecte (6 și 5) și două variabile care se referă la ele.

Unele operații (de exemplu y.append (10) și y.sort ()) schimbarea obiectului în timp ce ambele operații extern asociate (de exemplu, y = y + [10], și sortate (y)) a crea un nou obiect. În general, în Python (și în toate cazurile în biblioteca standard), o metodă care schimbă obiectul, returnează Nici una. pentru a ajuta la evitarea greșelilor. Prin urmare, dacă scrie

gândindu-mă că vă va da o copie a lui y sortate, în loc să te Niciuna. care este de natură să conducă la o eroare ușor de diagnosticat.

Cu toate acestea, există o clasă de operațiuni în care aceeași operație se comportă în mod diferit, cu diferite tipuri: operatori de atribuire extinse. De exemplu, + = listează modificări, dar nu și numărul de tuple sau (a_list + = [1, 2, 3] a_list.extend echivalent ([1, 2, 3])) și modifică lista, în timp ce ca some_tuple + = ( 1, 2, 3) și some_int + = 1 creează un nou obiect.

Dacă doriți să știe dacă cele două variabile se referă la același obiect sau nu, puteți utiliza este operatorul. sau built-in functie id.

Cum de a crea o funcții de ordin superior?

Există două moduri: utilizați funcția imbricată sau obiecte apelabile. De exemplu, cu ajutorul funcțiilor imbricate:

Utilizarea Apelanții:

În ambele cazuri,

oferă o funcție care (de exemplu) taxe (10E6) == 0,3 * 10E6 + 2.

Folosind obiectul nevărsat - un pic mai lent, iar rezultatul este un cod mai lung. Rețineți, totuși, că mai multe funcții pot partaja semnătura lor prin moștenire:

Un obiect poate menține starea sa pentru o serie de provocări:

Aici inc. decembrie reset acționează ca funcții care au în comun aceeași variabilă.

Cum pot copia un obiect în Python?

Secvențe pot fi copiate pe secțiuni:

Cum pentru a afla metodele și atributele disponibile ale obiectului?

dir (x) returnează o listă de metode și atribute.

Cum pot găsi numele de obiect?

În general vorbind, în nici un fel, pentru că obiectele nu sunt cu adevărat nume. Important: atribuirea leagă întotdeauna numele obiectului. Acest lucru este valabil și pentru instruirea def și clasă.

Probabil, clasa are un nume: dar, cu toate că acesta este asociat cu două nume și solicitate prin intermediul B. creată instanță este în continuare considerată a fi o instanta a clasei A. Cu toate acestea, este imposibil de spus, un nume de instanță de a sau b. deoarece acestea se referă ambele la aceeași valoare.

Ce se acordă prioritate operatorului „virgulă“?

Virgula nu este un operator în Python.

Deoarece virgula - nu operatorul, dar delimitator între expresii, exemplul de mai sus este executată ca în cazul în care a fost introdus:

Același lucru este valabil și pentru operatorul de atribuire (=. = +, Și altele). Ele nu sunt operatori ca atare, ci pur și simplu delimitatori sintactice în operațiunile de atribuire.

Există un Python echivalent al operatorului ternar „?“ În C?

Este posibil să se scrie-garnituri umbrită?

Nu încercați să-l facă acasă!

articole similare