Làm thế nào để tôi kiểm tra nếu một biến tồn tại?


954

Tôi muốn kiểm tra nếu một biến tồn tại. Bây giờ tôi đang làm một cái gì đó như thế này:

try:
   myVar
except NameError:
   # Do something.

Có những cách khác mà không có ngoại lệ?


15
Có gì sai với ngoại lệ?
S.Lott

10
@ S.Lott: nếu myVarmột cái gì đó thực sự phức tạp, phải mất một thời gian dài để sản xuất / đánh giá, liệu trynhững điều đó có chậm lại không?
dbliss

3
@dbliss: Đó là một biến. Ngoài một số trường hợp thực sự kỳ lạ nếu bạn đang làm điều gì đó điên rồ với exechoặc siêu dữ liệu, nó sẽ không tốn kém.
user2357112 hỗ trợ Monica

Một câu trả lời đầy đủ hơn: stackoverflow.com/a/1592578/1661797
nickboldt

Câu trả lời:


1628

Để kiểm tra sự tồn tại của một biến cục bộ:

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

Để kiểm tra sự tồn tại của biến toàn cục:

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

Để kiểm tra xem một đối tượng có thuộc tính không:

if hasattr(obj, 'attr_name'):
  # obj.attr_name exists.

29
Ok, và làm thế nào tôi có thể kiểm tra thuộc tính hiện có trong lớp?
Max Frai

7
và làm thế nào để bạn biến tên của biến có thể không tồn tại thành một chuỗi?
SilentGhost

15
Nhưng OP đang gõ mã, họ có thể gõ 'myVar' intstead của myVar. Nếu tên biến không được biết khi mã được viết, nó sẽ được lưu trong biến chuỗi khi chạy và kiểm tra tôi đã đăng cũng sẽ hoạt động.
Ayman Hourieh

8
Ngoài ra còn có các biến tích hợp và nếu bạn có các hàm lồng nhau, các biến trong phạm vi bên ngoài. Nếu bạn muốn kiểm tra tất cả chúng, có lẽ bạn nên kích hoạt tốt nhất NameError.
Petr Viktorin

14
Tôi cũng thích nhất if hasattr(obj, 'attr_name'):hoạt động cho các lớp học: tức làif hasattr(self, 'attr_name'):
Ron Kalian

118

Việc sử dụng các biến chưa được xác định hoặc đặt (ngầm hoặc rõ ràng) hầu như luôn là một điều xấu trong bất kỳ ngôn ngữ nào , vì nó thường chỉ ra rằng logic của chương trình đã không được suy nghĩ đúng đắn và có khả năng dẫn đến trong hành vi không thể đoán trước.

Nếu bạn cần thực hiện bằng Python, thủ thuật sau, tương tự như của bạn, sẽ đảm bảo rằng một biến có một số giá trị trước khi sử dụng:

try:
    myVar
except NameError:
    myVar = None

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

Tuy nhiên, tôi vẫn không tin đó là một ý tưởng hay - theo tôi, bạn nên cố gắng cấu trúc lại mã của mình để tình huống này không xảy ra.


8
Có thể đó là một biến số của sự phụ thuộc và dựa trên phiên bản / nền tảng mà nó có thể tồn tại hoặc không tồn tại và không có cách nào khác để biết phiên bản đó là gì.
WhyNotHugo

35
Các biến trạng thái không tồn tại trước khi chúng được gán - nếu bạn vẽ một dòng từ vị trí trước đó đến vị trí hiện tại, sau đó đặt trước = hiện tại, điều đó không có nghĩa là bạn "không biết biến của mình" trong cuộc gọi đầu tiên. Và viết thêm một dòng mã để khởi tạo trước = null bên ngoài thói quen vẽ không có nghĩa là bạn "biết các biến của mình" tốt hơn.
Dave

4
Quan điểm của tôi là một khối "nếu cuối cùng: vẽ (cuối cùng, hiện tại); cuối cùng = hiện tại" là dễ hiểu và không phải là lập trình kém. Thêm "thử / ngoại trừ" để kiểm tra sự tồn tại của "lần cuối" trước khi có thể kiểm tra nó làm mất khả năng đọc của mã đó.
Dave

23
"Việc sử dụng các biến chưa được xác định thực sự là một điều xấu trong bất kỳ ngôn ngữ nào" Hãy dành cho tôi lời nói hạ thấp. Một số người trong chúng ta sử dụng Python cho các kịch bản toán học hoặc thống kê đơn giản sử dụng các IDE như Spyder hoạt động như Matlab. Đôi khi có ý nghĩa trong các môi trường đó để cho phép người dùng xác định các biến trong bảng điều khiển toàn cầu và kiểm tra khác nếu chúng không được khai báo trong tập lệnh như khi thực hiện toán học trong Matlab.
Ricardo Cruz

15
@Ricardo, có lẽ, thay vì cho rằng đó là sự nhượng bộ, ít nhất bạn có thể muốn xem xét khả năng đó chỉ là lời khuyên tốt từ một người thể hiểu biết hơn :-) Hoặc bạn sẽ xem xét việc bảo trợ như nhau nếu tôi khuyên bạn không nên sử dụng toàn cầu các biến, mã spaghetti, các đối tượng thần, phát hành mã chưa được kiểm tra hoặc viết các hệ điều hành trong COBOL? Câu trả lời của tôi cho biết lý do tại sao tôi nghĩ rằng đó là một ý tưởng tồi (và không có gì trong câu hỏi chỉ ra lý do tại sao OP nghĩ rằng nó là cần thiết) nhưng vẫn cung cấp một cách để tránh cơ hội họ thực sự muốn làm điều đó.
paxdiablo

52

Một cách đơn giản là khởi tạo nó ngay từ đầu myVar = None

Sau đó về sau:

if myVar is not None:
    # Do something

2
Có nhiều điều cần được cải thiện trong câu trả lời này. Thay vào đó - Một cách đơn giản là khai báo trước. myVar = none # do stuff... if not myVar: # give myVar a value myVar = 'something'
Shawn Mehan

tôi thích cái này rất nhiều vì tôi đặt mọi thứ thành Không có trong các exceptphát biểu của mình
HashRocketSyntax

tại sao không phải là một cái gì đó như: if myVar: # Do something Điều này tránh sự cần thiết phải đọc một tiêu cực kép
jjisnow

@jjisnow Bởi vì bạn muốn điều kiện này là đúng ngay cả khi myVardanh sách trống, số không, chuỗi trống, v.v.
Gabriel

7
@jjisnow if myVar: # Do somethingném NameErrorvào python3 nếu myVar không được khai báo
Agile Bean

25

Sử dụng thử / ngoại trừ là cách tốt nhất để kiểm tra sự tồn tại của một biến. Nhưng gần như chắc chắn là một cách tốt hơn để làm bất cứ điều gì bạn đang làm hơn là thiết lập / kiểm tra các biến toàn cục.

Ví dụ: nếu bạn muốn khởi tạo biến cấp mô-đun trong lần đầu tiên bạn gọi một số chức năng, tốt hơn hết bạn nên sử dụng mã như thế này:

my_variable = None

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

2
Tôi cố gắng không sử dụng điều này, vì nó gây ô nhiễm không gian tên toàn cầu. Một cách để tránh điều này là biến hàm thành một lớp, với my_variable là biến lớp và xác định lệnh gọi là phần thân của hàm hiện có, nhưng đó là một vấn đề khó để mã hóa và mở ra một loạt các câu hỏi khác. Tôi thích sử dụng các thuộc tính chức năng, xem bên dưới.
samwyse

17

đối với các đối tượng / mô-đun, bạn cũng có thể

'var' in dir(obj)

Ví dụ,

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

11

Tôi sẽ giả định rằng bài kiểm tra sẽ được sử dụng trong một chức năng, tương tự như câu trả lời của user97370 . Tôi không thích câu trả lời đó vì nó gây ô nhiễm không gian tên toàn cầu. Một cách để sửa nó là sử dụng một lớp thay thế:

class InitMyVariable(object):
  my_variable = None

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

Tôi không thích điều này, vì nó làm phức tạp mã và mở ra các câu hỏi như, liệu điều này có nên xác nhận với mẫu lập trình Singleton không? May mắn thay, Python đã cho phép các hàm có các thuộc tính trong một thời gian, điều này cho chúng ta giải pháp đơn giản này:

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

9

catchđược gọi exceptbằng Python. ngoài ra nó tốt cho những trường hợp đơn giản như vậy. Có những AttributeErrorthứ có thể được sử dụng để kiểm tra xem một đối tượng có thuộc tính hay không.


5

Một cách thường hoạt động tốt để xử lý loại tình huống này là không kiểm tra rõ ràng nếu biến đó tồn tại mà chỉ cần tiếp tục và sử dụng biến đầu tiên của biến không tồn tại trong một thử / ngoại trừ 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
  ...

3

Tôi đã tạo ra một chức năng tùy chỉnh.

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

Sau đó, gọi hàm như sau thay thế variable_namebằng biến bạn muốn kiểm tra:

exists("variable_name")

Sẽ trở lại TruehoặcFalse


2
Không, điều này sẽ không làm việc. locals()là ... err ... cục bộ cho chức năng exists😅
bgusach

1
1) Hàm locals () là cục bộ. 2) Tại sao việc gán thêm var_exists?
Dave
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.