Python'da dosyanın sonunda işlevi bildir


94

İlk önce tam olarak tanımlamadan bir işlevi çağırmak mümkün müdür? Bunu denerken şu hatayı alıyorum: " işlev_adı tanımlı değil". C ++ geçmişinden geliyorum, bu yüzden bu sorun beni şaşırtıyor.

İşlevin çalışmadan önce bildirilmesi:

def Kerma():
        return "energy / mass"    

print Kerma()

Ancak, işlevi önce tanımlamadan çağırmaya çalışmak sorun yaratır:

print Kerma()

def Kerma():
    return "energy / mass"

C ++ 'da, başlığını önüne koyduğunuzda aramadan sonra bir işlev bildirebilirsiniz.

Burada bir şey mi kaçırıyorum?


5
Python'da "beyan" yoktur. Tanım var (tamamlanmış olmalı) veya hiçbir şey yok.
S.Lott

2
"Sorun çıkarır" diyorsunuz. Bunu detaylandırır mısın?
Martin Del Vecchio


Kerma is an acronym for "kinetic energy released per unit mass"
Birinin

1
Bunun çok eski olduğunu biliyorum, ancak neden hiç kimse işlevleri ayrı bir .pydosyaya koymayı ve bunu içe aktarmayı önermiyor ? İstenmeyen bazı sonuçlar var mı?
Kyle

Yanıtlar:


145

Python'da bir tür deyimsel olan yollardan biri yazmaktır:

def main():
    print Kerma()

def Kerma():
    return "energy / mass"    

if __name__ == '__main__':
    main()

Bu main, sonunda işlevi çağırmaya devam ettiğiniz sürece size istediğiniz sırada kod yazmanıza olanak tanır .


4
@Muhammad: Bu uygulanabilir bir yaklaşım olsa da, kesinlikle Python'da deyimsel değil. Tam tersine, çoğu mainişlevin genellikle sona yerleştirildiğini fark edeceksiniz .
Eli Bendersky

15
@Eli Bendersky: if __name__ == '__main__':Anahtarın ortak deyimsel kısım olduğunu belirtmek isterim .
S.Lott

2
@Eli: modülün üst düzeyde bir kod modül ise, bir ana işlevi çağırmak sonunda: deyimsel kısmı sonunda eğer maddesi olan ana .
Ned Batchelder

1
@Eli: Deyimsel kısım if ... __main__':. mainKodun geri kalanının üstüne yerleştirilmesi gerektiğini söylemedim . Önemli kısmın _\_main__sonunda çağırmak olduğunu söyledim ve o zaman tanımını nereye koyduğunuz önemli değil.
Muhammad Alkarouri

2
Eğer birlikte adı == ' ana ': o size işlevlerini sipariş nasıl ilgisiz hale getirin. Yapılacak doğru şey (TM) budur.
MKesper

18

Bir Python modülü (.py dosyası) çalıştırıldığında, içindeki en üst düzey ifadeler, yukarıdan aşağıya (baştan sona) göründükleri sırayla yürütülür. Bu, tanımlayana kadar bir şeye referans veremeyeceğiniz anlamına gelir. Örneğin, aşağıdakiler gösterilen hatayı oluşturacaktır:

c = a + b  # -> NameError: name 'a' is not defined
a = 13
b = 17

Diğer birçok dilden farklı olarak defve classifadeler Python'da çalıştırılabilir - sadece bildirime dayalı değildir - bu nedenle bunlardan birine ya ada bbu gerçekleşene ve tanımlanana kadar başvuruda bulunamazsınız . İlk örneğinizin sorun yaşamasının nedeni budur - Kerma()işlevi, defifadesi çalıştırılmadan ve gövdesi işlenmeden ve sonuçta ortaya çıkan işlev nesnesi işlevin adına bağlanmadan önce başvuruyorsunuz , bu nedenle kodda o noktada tanımlanmamıştır.

C ++ gibi dillerdeki programlar genellikle çalıştırılmadan önce #includeişlenir ve bu derleme aşamasında programın tamamı ve başvurduğu dosyalar bir kerede okunur ve işlenir. Python'dan farklı olarak, bu dil, kullanımdan önce işlevlerin adının ve çağırma sırasının (veya statik değişken türünün) bildirilmesine (ancak tanımlanmamasına) izin veren bildirimsel ifadeler içerir, böylece derleyici adlarıyla karşılaştığında, bunları kontrol etmek için yeterli bilgiye sahip olur. birincil olarak tür denetimi ve tür dönüştürmeyi gerektiren kullanım, bunların hiçbiri gerçek içeriklerinin veya kod gövdelerinin henüz tanımlanmış olmasını gerektirmez.


Dinamik bir dil bunu yapamaz değil. Perl dinamik bir dildir ve bir işlevi tanımlamadan önce çağırabilirsiniz. Bunun nedeni, bir derleme aşamasına ve bir yürütme aşamasına sahip olmasıdır (garip bir şekilde, ancak yararlı bir şekilde, derleme aşamasında kod çalıştırmayı ayarlayabilirsiniz). Bu çalışır: doit(); sub doit { print("I'm doing it!\n"); }
John Deighan

9

Python'da bu mümkün değildir, ancak açıkçası yakında buna hiç ihtiyacınız olmadığını göreceksiniz. Pythonic kod yazmanın yolu, programınızı sınıfları ve işlevleri tanımlayan modüllere ve diğerlerini içe aktaran ve çalışan tek bir "ana modül" e bölmektir.

Basit bir atma komut dosyaları için, "yürütülebilir kısmı" en sona yerleştirmeye veya daha iyisi etkileşimli bir Python kabuğu kullanmayı öğrenin.


1

Python dinamik bir dildir ve yorumlayıcı her zaman değişkenlerin (fonksiyonlar, ...) durumunu çağırdıkları anda olduğu gibi alır. Hatta bazı if bloklarındaki işlevleri yeniden tanımlayabilir ve her seferinde farklı şekilde çağırabilirsiniz. Bu yüzden aramadan önce onları tanımlamalısınız.


1

C ++ gibi olmaya ve bir işlevin içindeki her şeyi kullanmaya istekliysen. ilk işlevi dosyanın altından şu şekilde çağırabilirsiniz:

def main():
    print("I'm in main")
    #calling a although it is in the bottom
    a()

def b():
   print("I'm in b")

def a():
   print("I'm in a")
   b()

main()

Bu şekilde python önce tüm dosyayı 'okur' ve ardından yürütmeyi başlatır.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.