Bagaimana saya memeriksa apakah ada variabel?

954

Saya ingin memeriksa apakah ada variabel. Sekarang saya melakukan sesuatu seperti ini:

try:
   myVar
except NameError:
   # Do something.

Apakah ada cara lain tanpa pengecualian?

Max Frai
sumber
15
Apa yang salah dengan pengecualian ini?
S.Lott
10
@ S.Lott: jika myVarada sesuatu yang benar-benar rumit, yang membutuhkan waktu lama untuk menghasilkan / mengevaluasi, bukankah tryhal itu akan melambat?
dbliss
3
@ Dbliss: Ini variabel. Selain dari beberapa kasus yang sangat aneh jika Anda melakukan sesuatu yang gila dengan execatau metaclasses, itu tidak akan mahal.
user2357112 mendukung Monica
Jawaban yang lebih lengkap: stackoverflow.com/a/1592578/1661797
nickboldt

Jawaban:

1628

Untuk memeriksa keberadaan variabel lokal:

if 'myVar' in locals():
  # myVar exists.

Untuk memeriksa keberadaan variabel global:

if 'myVar' in globals():
  # myVar exists.

Untuk memeriksa apakah suatu objek memiliki atribut:

if hasattr(obj, 'attr_name'):
  # obj.attr_name exists.
Ayman Hourieh
sumber
29
Oke, dan bagaimana saya bisa memeriksa atribut yang ada di kelas?
Max Frai
7
dan bagaimana Anda mengubah nama variabel yang mungkin tidak ada menjadi string?
SilentGhost
15
Tapi OP mengetik kode, mereka bisa mengetik 'myVar' di myVar. Jika nama variabel tidak diketahui saat kode ditulis, itu akan disimpan dalam variabel string saat runtime, dan cek yang saya posting juga akan berfungsi.
Ayman Hourieh
8
Ada juga variabel bawaan, dan, jika Anda memiliki fungsi bersarang, variabel dalam cakupan luar. Jika Anda ingin memeriksa semuanya, Anda mungkin lebih baik memicu NameErrorsemua.
Petr Viktorin
14
Saya suka yang terbaik if hasattr(obj, 'attr_name'):yang bekerja untuk kelas juga: yaituif hasattr(self, 'attr_name'):
Ron Kalian
118

The Penggunaan variabel yang belum didefinisikan atau set (secara implisit maupun eksplisit) hampir selalu hal yang buruk dalam setiap bahasa, karena sering menunjukkan bahwa logika program belum memikirkan dengan baik, dan kemungkinan hasil dalam perilaku yang tidak terduga.

Jika Anda perlu melakukannya di Python, trik berikut, yang serupa dengan Anda, akan memastikan bahwa variabel memiliki beberapa nilai sebelum digunakan:

try:
    myVar
except NameError:
    myVar = None

# Now you're free to use myVar without Python complaining.

Namun, saya masih tidak yakin itu ide yang bagus - menurut saya, Anda harus mencoba untuk memperbaiki kode Anda sehingga situasi ini tidak terjadi.

paxdiablo
sumber
8
Mungkin itu adalah variabel ketergantungan, dan menurut versi / platform itu mungkin ada atau tidak ada, dan tidak ada cara lain untuk mengetahui versi apa itu.
WhyNotHugo
35
Variabel status tidak ada sebelum ditugaskan - jika Anda menggambar garis dari posisi sebelumnya ke posisi saat ini, lalu atur sebelumnya = saat ini, itu tidak berarti Anda "tidak tahu variabel Anda" pada panggilan pertama. Dan menulis baris kode tambahan untuk menginisialisasi sebelumnya = nol di luar rutin imbang tidak berarti Anda "tahu variabel Anda" lebih baik.
Dave
4
Maksud saya adalah bahwa blok "if last: draw (last, current); last = current" mudah dimengerti dan bukan pemrograman yang buruk. Menambahkan "coba / kecuali" untuk memeriksa keberadaan "terakhir" sebelum dapat mengujinya akan mengurangi keterbacaan kode itu.
Dave
23
"Penggunaan variabel yang belum didefinisikan sebenarnya merupakan hal yang buruk dalam bahasa apa pun" Jangan gunakan pidato merendahkan saya. Beberapa dari kita menggunakan Python untuk skrip matematika atau statistik sederhana menggunakan IDE seperti Spyder yang berfungsi seperti Matlab. Masuk akal kadang-kadang di lingkungan tersebut untuk memungkinkan pengguna untuk mendefinisikan variabel di konsol global dan memeriksa sebaliknya jika mereka tidak dideklarasikan dalam skrip seperti ketika melakukan matematika di Matlab.
Ricardo Cruz
15
@ Ricardo, mungkin, daripada menganggapnya merendahkan, Anda mungkin ingin setidaknya mempertimbangkan kemungkinan bahwa itu hanya nasihat yang baik dari seseorang yang mungkin lebih berpengetahuan luas :-) Atau apakah Anda menganggapnya sama-sama merendahkan jika saya menyarankan agar penggunaan global tidak dibatasi? variabel, kode spageti, objek dewa, merilis kode yang belum diuji, atau menulis sistem operasi dalam COBOL? Jawaban saya menyatakan mengapa saya pikir itu ide yang buruk (dan tidak ada dalam pertanyaan yang mengindikasikan mengapa OP berpikir itu perlu) tetapi masih memberikan jalan jika mereka benar-benar ingin melakukannya.
paxdiablo
52

Cara sederhana adalah menginisialisasi pada pepatah pertama myVar = None

Kemudian di kemudian hari:

if myVar is not None:
    # Do something
Chinedum Ukejianya
sumber
2
Ada banyak hal yang harus diperbaiki dalam jawaban ini. Sebaliknya - Cara sederhana adalah mendeklarasikannya terlebih dahulu. myVar = none # do stuff... if not myVar: # give myVar a value myVar = 'something'
Shawn Mehan
Saya sangat menyukai yang ini karena saya mengatur semuanya menjadi Tidak ada dalam exceptpernyataan saya
HashRocketSyntax
mengapa tidak sesuatu seperti: if myVar: # Do something Ini menghindari kebutuhan untuk membaca negatif ganda
jisnow
@jjisnow Karena Anda ingin kondisi ini benar meskipun myVardaftar kosong, nol, string kosong dll.
Gabriel
7
@jjisnow if myVar: # Do somethingmelempar NameErrorpython3 jika myVar tidak dideklarasikan
Agile Bean
25

Menggunakan try / kecuali adalah cara terbaik untuk menguji keberadaan variabel. Tetapi hampir pasti ada cara yang lebih baik untuk melakukan apa pun yang Anda lakukan daripada menetapkan / menguji variabel global.

Misalnya, jika Anda ingin menginisialisasi variabel tingkat modul saat pertama kali Anda memanggil beberapa fungsi, Anda lebih baik dengan kode seperti ini:

my_variable = None

def InitMyVariable():
  global my_variable
  if my_variable is None:
    my_variable = ...

sumber
2
Saya mencoba untuk tidak menggunakan ini, karena mencemari namespace global. Salah satu cara untuk menghindari ini adalah dengan membuat fungsi kelas, dengan my_variable sebagai variabel kelas, dan mendefinisikan panggilan sebagai isi dari fungsi yang ada, tetapi itu menyebalkan untuk kode dan membuka banyak pertanyaan lain. Saya lebih suka menggunakan atribut fungsi, lihat di bawah.
samwyse
17

untuk objek / modul, Anda juga bisa

'var' in dir(obj)

Sebagai contoh,

>>> class Something(object):
...     pass
...
>>> c = Something()
>>> c.a = 1
>>> 'a' in dir(c)
True
>>> 'b' in dir(c)
False
Wyrmwood
sumber
11

Saya akan berasumsi bahwa tes akan digunakan dalam suatu fungsi, mirip dengan jawaban user97370 . Saya tidak suka jawaban itu karena mencemari namespace global. Salah satu cara untuk memperbaikinya adalah dengan menggunakan kelas sebagai gantinya:

class InitMyVariable(object):
  my_variable = None

def __call__(self):
  if self.my_variable is None:
   self.my_variable = ...

Saya tidak suka ini, karena mempersulit kode dan membuka pertanyaan seperti, haruskah ini mengkonfirmasi ke pola pemrograman Singleton? Untungnya, Python telah mengizinkan fungsi untuk memiliki atribut untuk sementara waktu, yang memberi kami solusi sederhana ini:

def InitMyVariable():
  if InitMyVariable.my_variable is None:
    InitMyVariable.my_variable = ...
InitMyVariable.my_variable = None
samwyse
sumber
9

catchdisebut exceptdengan Python. selain itu tidak masalah untuk kasus sederhana seperti itu. Ada AttributeErroryang dapat digunakan untuk memeriksa apakah suatu objek memiliki atribut.

SilentGhost
sumber
5

Cara yang sering bekerja dengan baik untuk menangani situasi semacam ini adalah dengan tidak secara eksplisit memeriksa apakah variabel itu ada tetapi lanjutkan dan bungkus penggunaan pertama dari variabel yang mungkin tidak ada dalam percobaan / kecuali NameError:

# Search for entry.
for x in y:
  if x == 3:
    found = x

# Work with found entry.
try:
  print('Found: {0}'.format(found))
except NameError:
  print('Not found')
else:
  # Handle rest of Found case here
  ...
Roger Dahl
sumber
3

Saya membuat fungsi khusus.

def exists(var):
     var_exists = var in locals() or var in globals()
     return var_exists

Kemudian panggil fungsi seperti berikut menggantikan variable_namedengan variabel yang ingin Anda periksa:

exists("variable_name")

Akan kembali TrueatauFalse

Abhishek R
sumber
2
Tidak, ini tidak akan berhasil. locals()is ... err ... lokal ke fungsi exists😅
bgusach
1
1) Fungsi penduduk lokal () adalah lokal. 2) Mengapa tugas tambahan var_exists?
Dave