Python yorumlayıcısı bir kaynak dosyasını okuduğunda, iki şey yapar:
Bunun nasıl çalıştığını ve __name__
Python komut dosyalarında her zaman gördüğümüz kontroller hakkındaki sorunuzla nasıl ilişkili olduğunu görelim.
Kod Örneği
İçe aktarma ve komut dosyalarının nasıl çalıştığını keşfetmek için biraz farklı bir kod örneği kullanalım. Aşağıdakilerin adlı bir dosyada olduğunu varsayalım foo.py
.
# Suppose this is foo.py.
print("before import")
import math
print("before functionA")
def functionA():
print("Function A")
print("before functionB")
def functionB():
print("Function B {}".format(math.sqrt(100)))
print("before __name__ guard")
if __name__ == '__main__':
functionA()
functionB()
print("after __name__ guard")
Özel Değişkenler
Python yorumlayıcısı bir kaynak dosyasını okuduğunda, önce birkaç özel değişken tanımlar. Bu durumda, __name__
değişkeni önemsiyoruz .
Modülünüz Ana Program Olduğunda
Modülünüzü (kaynak dosya) ana program olarak çalıştırıyorsanız, ör.
python foo.py
tercüman kodlanmış dize atar "__main__"
için __name__
değişken, yani
# It's as if the interpreter inserts this at the top
# of your module when run as the main program.
__name__ = "__main__"
Modülünüz Başka Biri Tarafından İçe Aktarıldığında
Öte yandan, başka bir modülün ana program olduğunu ve modülünüzü içe aktardığını varsayalım. Bu, ana programda veya başka bir modülde ana programın içe aktardığı gibi bir ifade olduğu anlamına gelir:
# Suppose this is in some other main program.
import foo
Yorumlayıcı foo.py
dosyanızı arayacaktır (birkaç başka varyantı da arayacaktır) ve bu modülü çalıştırmadan önce "foo"
, içe aktarma ifadesinden __name__
değişkene ad atayacaktır;
# It's as if the interpreter inserts this at the top
# of your module when it's imported from another module.
__name__ = "foo"
Modül Kodunu Çalıştırma
Özel değişkenler ayarlandıktan sonra, yorumlayıcı her seferinde bir deyim olmak üzere modüldeki tüm kodu yürütür. Kod açıklaması ile yan tarafta başka bir pencere açmak isteyebilirsiniz, böylece bu açıklama ile birlikte takip edebilirsiniz.
Her zaman
Dizeyi yazdırır "before import"
(tırnak işaretleri olmadan).
math
Modülü yükler ve adlı değişkene atar math
. Bu, import math
aşağıdakilerle değiştirmeye eşdeğerdir ( __import__
Python'da bir dize alan ve gerçek içe aktarmayı tetikleyen düşük düzeyli bir işlev olduğunu unutmayın ):
# Find and load a module given its string name, "math",
# then assign it to a local variable called math.
math = __import__("math")
Dizeyi yazdırır "before functionA"
.
def
Bir fonksiyon nesnesi oluşturarak bloğu yürütür ve daha sonra bu fonksiyon nesnesini adlı bir değişkene atar functionA
.
Dizeyi yazdırır "before functionB"
.
İkinci def
bloğu yürütür, başka bir işlev nesnesi oluşturur ve ardından adlandırılan bir değişkene atar functionB
.
Dizeyi yazdırır "before __name__ guard"
.
Yalnızca Modül Ana Program Olduğunda
- Modülünüz ana programsa, o zaman
__name__
gerçekten ayarlanmış olduğunu "__main__"
görür ve iki işlevi çağırır, dizeleri "Function A"
ve yazdırır "Function B 10.0"
.
Yalnızca Modülünüz Başka Biri Tarafından İçe Aktarıldığında
- ( bunun yerine ) Modülünüz ana program değilse ancak başka bir program tarafından içe aktarılmışsa
__name__
, olmayacak "foo"
, olmayacak "__main__"
ve if
ifadenin gövdesini atlayacaktır .
Her zaman
- Her
"after __name__ guard"
iki durumda da dizeyi yazdıracaktır .
özet
Özetle, iki durumda yazdırılacaklar şunlardır:
# What gets printed if foo is the main program
before import
before functionA
before functionB
before __name__ guard
Function A
Function B 10.0
after __name__ guard
# What gets printed if foo is imported as a regular module
before import
before functionA
before functionB
before __name__ guard
after __name__ guard
Neden Bu Şekilde Çalışıyor?
Doğal olarak neden herhangi birinin bunu isteyeceğini merak edebilirsiniz. Bazen .py
, diğer programlar ve / veya modüller tarafından modül olarak kullanılabilen ve ana programın kendisi olarak da çalıştırılabilen bir dosya yazmak istersiniz . Örnekler:
Modülünüz bir kitaplıktır, ancak bazı birim testleri veya bir demo çalıştıran bir komut dosyası moduna sahip olmak istersiniz.
Modülünüz yalnızca ana program olarak kullanılır, ancak bazı birim testleri vardır ve test çerçevesi .py
, komut dosyanız gibi dosyaları içe aktararak ve özel test işlevlerini çalıştırarak çalışır. Sadece modülü içe aktardığı için komut dosyasını çalıştırmayı denemek istemezsiniz.
Modülünüz çoğunlukla ana program olarak kullanılır, ancak ileri düzey kullanıcılar için programcı dostu bir API sağlar.
Bu örneklerin ötesinde, Python'da bir komut dosyası çalıştırmanın sadece birkaç sihirli değişken oluşturması ve komut dosyasını içe aktarması zariftir. Komut dosyasını "çalıştırmak", komut dosyasının modülünü içe aktarmanın bir yan etkisidir.
Düşünce için yiyecek
Soru: Birden fazla __name__
kontrol bloğum olabilir mi? Cevap: Bunu yapmak garip, ama dil sizi durdurmayacak.
Aşağıdakilerin olduğunu varsayalım foo2.py
. python foo2.py
Komut satırında söylerseniz ne olur ? Neden?
# Suppose this is foo2.py.
def functionA():
print("a1")
from foo2 import functionB
print("a2")
functionB()
print("a3")
def functionB():
print("b")
print("t1")
if __name__ == "__main__":
print("m1")
functionA()
print("m2")
print("t2")
- Şimdi,
__name__
check- in'i kaldırırsanız ne olacağını öğrenin foo3.py
:
# Suppose this is foo3.py.
def functionA():
print("a1")
from foo3 import functionB
print("a2")
functionB()
print("a3")
def functionB():
print("b")
print("t1")
print("m1")
functionA()
print("m2")
print("t2")
- Komut dosyası olarak kullanıldığında ne yapacak? Modül olarak alındığında?
# Suppose this is in foo4.py
__name__ = "__main__"
def bar():
print("bar")
print("before __name__ guard")
if __name__ == "__main__":
bar()
print("after __name__ guard")
if __name__ == "__main__":
bloğu koşulu kaldırılmıştır / Python 3 kadarıyla eskitiliyor? Bunu belirten bazı bilgiler buldum.