Apa ruang lingkup variabel yang diinisialisasi dalam pernyataan if?

266

Saya baru mengenal Python, jadi ini mungkin pertanyaan pelingkupan sederhana. Kode berikut dalam file Python (modul) sedikit membingungkan saya:

if __name__ == '__main__':
    x = 1

print x

Dalam bahasa lain yang pernah saya gunakan, kode ini akan memberikan pengecualian, karena xvariabelnya lokal untuk ifpernyataan dan tidak boleh ada di luarnya. Tetapi kode ini mengeksekusi, dan mencetak 1. Adakah yang bisa menjelaskan perilaku ini? Apakah semua variabel dibuat dalam modul global / tersedia untuk seluruh modul?

froadie
sumber
17
Permainan kata-kata lain Anda mungkin tidak menyadari: jika ifpernyataan di atas tidak berlaku (yaitu, __name__adalah tidak '__main__' , misalnya ketika Anda mengimpor modul bukannya dijalankan tingkat atas), maka xtidak akan pernah telah terikat, dan selanjutnya print xpernyataan akan melempar NameError: name 'x' is not defined.
Santa

Jawaban:

302

Variabel python di-scoped ke fungsi, kelas, atau modul terdalam di mana mereka ditugaskan. Blok kontrol suka ifdan whileblok tidak masuk hitungan, jadi variabel yang ditugaskan di dalam ifmasih dibatasi untuk fungsi, kelas, atau modul.

(Fungsi implisit yang didefinisikan oleh ekspresi generator atau pemahaman daftar / set / dikt benar- benar dihitung, seperti halnya ekspresi lambda. Anda tidak dapat memasukkan pernyataan penugasan ke dalam salah satu dari itu, tetapi parameter lambda dan fortarget klausa adalah penugasan implisit.)

Luke Maurer
sumber
1
@ chandr3sh docs.python.org/3/tutorial/…
Fakher Mokadem
105

Ya, mereka berada di "cakupan lokal" yang sama, dan sebenarnya kode seperti ini adalah umum dalam Python:

if condition:
  x = 'something'
else:
  x = 'something else'

use(x)

Catatan yang xtidak dideklarasikan atau diinisialisasi sebelum kondisi, seperti itu akan di C atau Java, misalnya.

Dengan kata lain, Python tidak memiliki cakupan level blok. Namun, berhati-hatilah dengan contoh-contoh seperti

if False:
    x = 3
print(x)

yang jelas akan menimbulkan NameErrorpengecualian.

Eli Bendersky
sumber
42

Lingkup dalam python mengikuti urutan ini:

  • Cari ruang lingkup lokal

  • Cari ruang lingkup fungsi terlampir

  • Cari ruang lingkup global

  • Cari bawaan

( sumber )

Perhatikan bahwa ifdan konstruksi pengulangan / percabangan lainnya tidak terdaftar - hanya kelas, fungsi, dan modul yang menyediakan ruang lingkup dengan Python, jadi apa pun yang dideklarasikan dalam sebuah ifblok memiliki cakupan yang sama dengan apa pun yang dideklarasikan di luar blok. Variabel tidak dicentang pada waktu kompilasi, itulah sebabnya bahasa lain memberikan pengecualian. Dalam python, selama variabel itu ada pada saat Anda memerlukannya, tidak ada pengecualian yang akan dibuang.

Daniel G
sumber
9

Seperti yang Eli katakan, Python tidak memerlukan deklarasi variabel. Dalam C Anda akan mengatakan:

int x;
if(something)
    x = 1;
else
    x = 2;

tetapi dalam deklarasi Python implisit, jadi ketika Anda menetapkan ke x itu secara otomatis dinyatakan. Itu karena Python diketik secara dinamis - itu tidak akan bekerja dalam bahasa yang diketik secara statis, karena tergantung pada jalur yang digunakan, variabel dapat digunakan tanpa dideklarasikan. Ini akan ditangkap pada waktu kompilasi dalam bahasa yang diketik secara statis, tetapi dengan bahasa yang diketik secara dinamis itu diizinkan.

Satu-satunya alasan bahwa bahasa yang diketik secara statis terbatas karena harus mendeklarasikan variabel di luar ifpernyataan karena masalah ini. Rangkul dinamis!

Skilldrick
sumber
9

Tidak seperti bahasa seperti C, variabel Python berada dalam ruang lingkup untuk seluruh fungsi (atau kelas, atau modul) di mana ia muncul, bukan hanya di "blok" terdalam. Seolah-olah Anda menyatakan int xdi bagian atas fungsi (atau kelas, atau modul), kecuali bahwa dalam Python Anda tidak harus mendeklarasikan variabel.

Perhatikan bahwa keberadaan variabel xdiperiksa hanya pada saat runtime - yaitu, ketika Anda sampai pada print xpernyataan. Jika __name__tidak sama "__main__"maka Anda akan mendapatkan pengecualian: NameError: name 'x' is not defined.

Paul Stephenson
sumber
Kelas tidak membuat ruang lingkup; variabel "lokal" di kelas hanya ditambahkan ke dikte kelas pada saat penciptaan.
chepner
3

Iya. Itu juga berlaku untuk forruang lingkup. Tapi tentu saja bukan fungsi.

Dalam contoh Anda: jika kondisi dalam ifpernyataan itu salah, xtidak akan didefinisikan.

Olivier Verdier
sumber
2

Anda mengeksekusi kode ini dari baris perintah karena itu ifkondisinya benar dan xdiatur. Membandingkan:

>>> if False:
    y = 42


>>> y
Traceback (most recent call last):
  File "<pyshell#6>", line 1, in <module>
    y
NameError: name 'y' is not defined
SilentGhost
sumber
0

Dan perhatikan bahwa karena tipe Python hanya diperiksa saat runtime, Anda dapat memiliki kode seperti:

if True:
    x = 2
    y = 4
else:
    x = "One"
    y = "Two"
print(x + y)

Tapi saya kesulitan memikirkan cara lain di mana kode akan beroperasi tanpa kesalahan karena masalah ketik.

cowang
sumber