Theory
બે total, શૂન્ય સંઘર્ષ. પછી એક ભંગાણ.
ResultDesk માં હવે db.py અને reports.py છે, અને બંને total નામનું variable વ્યાખ્યાયિત કરે છે. કશું તૂટતું નથી. બે files, એક જ નામ, કોઈ ઝઘડો નહીં. કેવી રીતે?
પછી એક સાથી તમારી grades.py ને tools ના folder માં ખસેડે છે, અને અચાનક import grades મરી જાય છે: ModuleNotFoundError, ભલે file સ્પષ્ટપણે હાજર હોય.
બંને રહસ્યોનું મૂળ એક જ છે: Python નામોના નકશા રાખે છે, અને જ્યાં જોવું એની યાદી. નકશા (namespaces) અને યાદી (શોધનો રસ્તો) શીખો અને બંને રહસ્ય ઓગળી જાય છે.
Theory
એ જ નામ, જુદાં રજિસ્ટર
રિયા નામની ત્રણ students ત્રણ વર્ગમાં ભણે છે. ક્યારેય ગૂંચવણ થતી નથી: દરેક વર્ગનું રજિસ્ટર પોતાની નાની દુનિયા છે, અને "રિયા" એટલે દરેક રજિસ્ટર પ્રમાણે કોઈ ચોક્કસ વ્યક્તિ.
Namespace એ રજિસ્ટર છે: નામોથી ખરેખરા પદાર્થોનો નકશો. દરેક function એક રાખે છે (local), દરેક module એક રાખે છે (global), અને Python પોતે એક રાખે છે (built-in, જ્યાં print અને len વસે છે). જુદાં રજિસ્ટરમાં એકસરખાં નામ ક્યારેય અથડાતાં નથી.
Theory
Scope અને LEGB નું શોધવું
Scope એ પ્રશ્ન છે: જ્યારે code `total` કહે, ત્યારે Python કયું રજિસ્ટર તપાસે છે?
શોધનો ક્રમ LEGB છે, પહેલી મળે એ જીતે:
- Local: હાલના function ની અંદર બનેલાં નામ
- Enclosing: બહારનું function, જો nested હોય
- Global: module નાં પોતાનાં નામ
- Built-in: print, len, sum...
એક તીક્ષ્ણ ધાર: function ની અંદર assign કરવાથી LOCAL નામ બને છે. Function ની અંદરથી module ના સ્તરના નામને ફરી બાંધવા તમારે પહેલાં global total જાહેર કરવું પડે.
Practical
બાર લીટીમાં LEGB
total = 100 # G: module (global) namespace
def report():
total = 5 # L: a NEW local name, global untouched
print(total) # 5 (Local wins the lookup)
report()
print(total) # 100 (the global was never changed)
def reset():
global total # opt in to rebinding the global
total = 0
reset()
print(total) # 0
# Built-in namespace is the LAST stop:
# len, print, sum live there... until you shadow them:
# sum = 0 <- now sum() crashes: 'int' is not callable
This example runs in Gri-Learn on the web, where you can edit it and see the output.
Theory
Packages અને PYTHONPATH
Package એ modules નું folder છે, જેને __init__.py ની file ઓળખાવે છે:
resultdesk/
├── __init__.py
├── db.py
└── reports.py
Folders ને પ્રતિબિંબિત કરતાં ટપકાં સાથે import કરો: from resultdesk import db.
અને Python modules અને packages ક્યાં શોધે છે? ફક્ત sys.path માંનાં directories: હાલનું folder, standard જગ્યાઓ, વત્તા PYTHONPATH ના environment ના variable દ્વારા તમે ઉમેરેલું બધું (export PYTHONPATH=/home/riya/tools). સાથીનું ભંગાણ: tools નું folder એ યાદીમાં નહોતું.
Quiz
Module ના સ્તરે x = 10. એક function x = 99 કરે છે (કોઈ global નું વિધાન નહીં) અને પછી module x છાપે છે. શું છપાય છે, અને કેમ?
- 10: assignment એ અલગ **LOCAL** x બનાવ્યું; global અછૂતું રહ્યું
- 99: functions હંમેશા આસપાસનું variable બદલે છે
- ભૂલ: x બે વાર વ્યાખ્યાયિત થયું છે
- 0: Python ઢંકાયેલાં variables ને શૂન્ય કરી નાખે છે
Show the answer
10: assignment એ અલગ **LOCAL** x બનાવ્યું; global અછૂતું રહ્યું
Function ની અંદર assignment એ function ના પોતાના namespace માં local નામ જન્માવે છે; module ના સ્તરનું x એ વિશે કશું સાંભળતું નથી. Global બદલવા સ્પષ્ટ global x નું જાહેરનામું જોઈએ. વિકલ્પ B એવી ભાષાઓ વર્ણવે છે જે Python બનવાની ના પાડે છે; એક જ નામ ધરાવતાં બે namespaces સામાન્ય છે, ભૂલ નહીં. બરાબર આ ટ્રેસ, બરાબર આ બે સંખ્યાઓ સાથે, પરીક્ષાનું નિયમિત મહેમાન છે.
Think first
સાથીનું import સુધારો
grades.py હવે /home/riya/tools માં વસે છે, અને તમારી script (બીજેથી ચાલતી) ને import grades જોઈએ. Tap કરતાં પહેલાં: import સફળ કરવાની બે જુદી રીતો આપો.
Show the answer
1. PYTHONPATH ગોઠવો: ચલાવતાં પહેલાં export PYTHONPATH=/home/riya/tools: એ folder એ shell માંના દરેક Python ના run માટે sys.path માં જોડાય છે.
2. Code માં જોડો: import પહેલાં import sys; sys.path.append('/home/riya/tools'): દરેક script દીઠ ઉકેલ.
(ત્રીજો, ખરેખરા projects માટે સૌથી સ્વચ્છ: tools ને બરાબર install થયેલું package બનાવો.) બંને રીતે સિદ્ધાંત એ જ: Python ફક્ત sys.path શોધે છે; imports files ન હોવાથી નહીં, યાદીમાં ગેરહાજરીથી નિષ્ફળ જાય છે.
Watch out
ઢાંકવું: namespace નો ચૂપ ગુનો
Script ની ટોચે sum = 0 ચૂપચાપ જડેલા sum() ને દાટી દે છે: પચાસ લીટી પછી sum(scores) 'int' object is not callable સાથે ફૂટે છે અને કેમ એનો કોઈ સંકેત નહીં.
LEGB એ સમજાવે છે: તમારું Global sum હવે Built-in સુધી પહોંચાય એ પહેલાં જ શોધ જીતી લે છે. ગયા પાઠના csv.py એ csv module ને ઢાંક્યું એ જ રોગ: એક namespace નું સ્તર બીજાને છુપાવે છે. જડેલાં નામ (sum, list, max, id) ને અનામત ગણો.
Theory
આગળના એકમો માટે આ કેમ મહત્ત્વનું છે
તમે લખશો એ દરેક import (આગલા પાઠમાં sqlite3, એકમ 4 માં pandas) sys.path થી સફળ કે નિષ્ફળ થાય છે, અને તમે debug કરશો એ દરેક NameError એ LEGB પૂછે છે કે તમે એ નામ ખરેખર કયા રજિસ્ટરમાં મૂક્યું હતું. બે માનસિક ઓજાર, બંને અદૃશ્ય જ્યાં સુધી એ તમારો એક કલાક ન બચાવે.
Summary
Key takeaways
- Namespace નામોને પદાર્થો સાથે જોડે છે; local, global અને built-in namespaces શાંતિથી સાથે રહે છે.
- શોધનો ક્રમ LEGB છે: Local, Enclosing, Global, Built-in; પહેલી મળે એ જીતે.
- Function માં assignment local નામ બનાવે છે; global ને ફરી બાંધવા global નો શબ્દ જોઈએ.
- Package = __init__.py વાળું modules નું folder; import નાં ટપકાં folders ને પ્રતિબિંબિત કરે છે.
- Python ફક્ત sys.path શોધે છે; PYTHONPATH એમાં directories ઉમેરે છે.
- જડેલાં નામ (sum, list, max) કે module નાં નામ ક્યારેય ન ઢાંકો.
- Memory hook: એ જ નામ, જુદાં વર્ગનાં રજિસ્ટર.