ฉันจะตรวจสอบว่ามีตัวแปรอยู่ได้อย่างไร


953

ฉันต้องการตรวจสอบว่ามีตัวแปรอยู่หรือไม่ ตอนนี้ฉันทำอะไรแบบนี้:

try:
   myVar
except NameError:
   # Do something.

มีวิธีอื่นโดยไม่มีข้อยกเว้น?


15
เกิดอะไรขึ้นกับข้อยกเว้น
S.Lott

10
@ S.Lott: หากmyVarมีสิ่งที่ซับซ้อนจริงๆที่ใช้เวลานานในการผลิต / ประเมินผลtryสิ่งที่ช้าลงหรือไม่
dbliss

3
@dbliss: มันเป็นตัวแปร นอกเหนือจากกรณีแปลก ๆ บางอย่างถ้าคุณทำอะไรบ้า ๆexecหรือ metaclasses มันจะไม่แพง
user2357112 รองรับ Monica

คำตอบที่สมบูรณ์ยิ่งขึ้น: stackoverflow.com/a/1592578/1661797
nickboldt

คำตอบ:


1627

วิธีตรวจสอบการมีอยู่ของตัวแปรโลคัล:

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

วิธีตรวจสอบการมีอยู่ของตัวแปรโกลบอล:

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

วิธีตรวจสอบว่าวัตถุมีคุณสมบัติหรือไม่:

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

29
ตกลงและฉันจะตรวจสอบคุณสมบัติที่มีอยู่ในชั้นเรียนได้อย่างไร
Max Frai

7
และคุณจะเปลี่ยนชื่อของตัวแปรที่อาจไม่มีอยู่ในสตริงได้อย่างไร?
SilentGhost

15
แต่ OP กำลังพิมพ์รหัสพวกเขาสามารถพิมพ์ 'myVar' แทน myVar ได้ หากไม่ทราบชื่อตัวแปรเมื่อมีการเขียนรหัสมันจะถูกเก็บไว้ในตัวแปรสตริงที่รันไทม์และการตรวจสอบที่ฉันโพสต์จะทำงานเช่นกัน
Ayman Hourieh

8
นอกจากนี้ยังมีตัวแปรในตัวและถ้าคุณมีฟังก์ชั่นซ้อนกันตัวแปรในขอบเขตด้านนอก หากคุณต้องการที่จะตรวจสอบทั้งหมดของพวกเขา, คุณอาจดีที่สุดออกเรียกNameErrorหลังจากทั้งหมด
Petr Viktorin

14
ฉันชอบสิ่งif hasattr(obj, 'attr_name'):ที่ดีที่สุดสำหรับชั้นเรียนด้วยเช่น:if hasattr(self, 'attr_name'):
Ron Kalian

118

การใช้ตัวแปรที่ยังไม่ได้กำหนดหรือตั้งค่า (โดยปริยายหรือโดยชัดแจ้ง) มักจะเป็นสิ่งที่ไม่ดีในภาษาใด ๆเนื่องจากมันมักจะแสดงให้เห็นว่าตรรกะของโปรแกรมไม่ได้รับการคิดอย่างถูกต้องและมีแนวโน้มที่จะส่งผล ในพฤติกรรมที่คาดเดาไม่ได้

หากคุณจำเป็นต้องทำใน Python เคล็ดลับต่อไปนี้ซึ่งคล้ายกับของคุณจะช่วยให้มั่นใจว่าตัวแปรมีค่าบางอย่างก่อนการใช้งาน:

try:
    myVar
except NameError:
    myVar = None

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

อย่างไรก็ตามฉันยังไม่เชื่อว่าเป็นความคิดที่ดี - ในความคิดของฉันคุณควรพยายาม refactor รหัสของคุณเพื่อให้สถานการณ์นี้ไม่เกิดขึ้น


8
อาจเป็นตัวแปรของการพึ่งพาและอ้างอิงกับเวอร์ชัน / แพลตฟอร์มที่อาจมีหรือไม่มีอยู่และไม่มีวิธีอื่นที่จะทราบว่าเป็นรุ่นใด
WhyNotHugo

35
ตัวแปรสถานะไม่มีอยู่ก่อนที่จะถูกกำหนด - หากคุณวาดเส้นจากตำแหน่งก่อนหน้าไปยังตำแหน่งปัจจุบันจากนั้นตั้งค่าก่อนหน้า = ปัจจุบันไม่ได้หมายความว่าคุณ "ไม่ทราบตัวแปรของคุณ" ในการโทรครั้งแรก และการเขียนโค้ดพิเศษเพื่อเริ่มต้นก่อนหน้านี้ = null นอกรูทีนการวาดไม่ได้หมายความว่าคุณ "รู้ตัวแปรของคุณ" ดีกว่า
เดฟ

4
ประเด็นของฉันคือบล็อก "ถ้าล่าสุด: draw (ล่าสุด, ปัจจุบัน); last = current" นั้นง่ายต่อการเข้าใจและไม่ใช่โปรแกรมที่ไม่ดี การเพิ่ม "ลอง / ยกเว้น" เพื่อตรวจสอบการมีอยู่ของ "สุดท้าย" ก่อนที่จะสามารถทดสอบได้ว่ามันจะเบี่ยงเบนจากความสามารถในการอ่านของรหัสนั้น
เดฟ

23
"การใช้ตัวแปรที่ไม่ได้กำหนดไว้จริง ๆ แล้วเป็นเรื่องเลวร้ายในภาษาใด ๆ " ช่วยพูดจาที่เหมาะสม พวกเราบางคนใช้ Python สำหรับสคริปต์คณิตศาสตร์หรือสถิติอย่างง่ายโดยใช้ IDE เช่น Spyder ซึ่งทำงานเหมือน Matlab มันสมเหตุสมผลในบางครั้งในสภาพแวดล้อมเหล่านั้นเพื่อให้ผู้ใช้สามารถกำหนดตัวแปรในคอนโซลทั่วโลกและตรวจสอบว่าพวกเขาไม่ได้ประกาศในสคริปต์เช่นเมื่อทำคณิตศาสตร์ใน Matlab
Ricardo Cruz

15
@Ricardo บางทีแทนที่จะคิดว่ามันเป็นภาระคุณอาจต้องการพิจารณาความเป็นไปได้ว่ามันเป็นเพียงคำแนะนำที่ดีจากคนที่อาจมีความรู้มากขึ้น :-) หรือคุณจะพิจารณามันอย่างเท่าเทียมกันหากฉันไม่แนะนำให้ใช้ทั่วโลก ตัวแปรรหัสสปาเก็ตตี้วัตถุพระเจ้าปล่อยรหัสที่ยังไม่ทดลองหรือเขียนระบบปฏิบัติการในภาษาโคบอล? คำตอบของฉันระบุว่าทำไมฉันจึงคิดว่ามันเป็นความคิดที่ไม่ดี (และไม่มีอะไรในคำถามที่แสดงว่าทำไม OP ถึงคิดว่ามันจำเป็น) แต่ก็ยังมีวิธีการในโอกาสที่พวกเขาต้องการทำมันจริงๆ
paxdiablo

52

วิธีง่ายๆคือการเริ่มต้นในตอนแรกว่า myVar = None

จากนั้นในภายหลัง:

if myVar is not None:
    # Do something

2
มีหลายสิ่งที่ต้องปรับปรุงในคำตอบนี้ Rather - วิธีง่ายๆคือการประกาศก่อน myVar = none # do stuff... if not myVar: # give myVar a value myVar = 'something'
Shawn Mehan

ผมชอบคนนี้มากเพราะผมตั้งสิ่งที่ไม่มีฉันในexceptงบ
HashRocketSyntax

ทำไมไม่ชอบ: if myVar: # Do something สิ่งนี้หลีกเลี่ยงความจำเป็นในการอ่านเชิงลบสองครั้ง
jjisnow

@jjisnow เพราะคุณต้องการเงื่อนไขนี้จะเป็นจริงแม้ว่าmyVarเป็นรายการที่ว่างเปล่า, ศูนย์สตริงว่าง ฯลฯ
กาเบรียล

7
@jjisnow if myVar: # Do somethingขว้างNameErrorใน python3 หาก myVar ไม่ได้ถูกประกาศ
Agile Bean

25

การใช้ลอง / ยกเว้นเป็นวิธีที่ดีที่สุดในการทดสอบการมีอยู่ของตัวแปร แต่มีวิธีที่ดีกว่าในการทำสิ่งที่คุณกำลังทำอยู่กว่าการตั้งค่า / ทดสอบตัวแปรทั่วโลก

ตัวอย่างเช่นหากคุณต้องการเริ่มต้นตัวแปรระดับโมดูลในครั้งแรกที่คุณเรียกใช้ฟังก์ชันบางอย่างคุณก็จะได้โค้ดที่ดีกว่าเช่นนี้:

my_variable = None

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

2
ฉันพยายามที่จะไม่ใช้สิ่งนี้เพราะมันสร้างมลภาวะต่อเนมสเปซส่วนกลาง วิธีหนึ่งในการหลีกเลี่ยงสิ่งนี้คือการทำให้ฟังก์ชั่นเป็นคลาสโดยมี my_variable เป็นตัวแปรคลาสและกำหนดการเรียกเป็นเนื้อหาของฟังก์ชันที่มีอยู่ แต่นั่นเป็นความเจ็บปวดในการเขียนโค้ดและเปิดคำถามมากมาย ฉันชอบที่จะใช้คุณสมบัติฟังก์ชั่นดูด้านล่าง
samwyse

17

สำหรับวัตถุ / โมดูลคุณยังสามารถ

'var' in dir(obj)

ตัวอย่างเช่น,

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

11

ผมจะสมมติว่าการทดสอบเป็นไปเพื่อนำมาใช้ในการทำงานคล้ายกับคำตอบของ user97370 ฉันไม่ชอบคำตอบนั้นเพราะมันทำให้เนมสเปซส่วนกลางหมดไป วิธีหนึ่งในการแก้ไขคือใช้คลาสแทน:

class InitMyVariable(object):
  my_variable = None

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

ฉันไม่ชอบสิ่งนี้เพราะมันซับซ้อนรหัสและเปิดคำถามเช่นนี้ควรยืนยันรูปแบบการเขียนโปรแกรม Singleton? โชคดีที่ Python อนุญาตให้ฟังก์ชั่นมีคุณสมบัติอยู่พักหนึ่งซึ่งทำให้เรามีวิธีง่ายๆนี้:

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

9

catchถูกเรียกexceptใน Python นอกจากนั้นมันก็โอเคสำหรับกรณีง่าย ๆ เช่นนั้น มีสิ่งAttributeErrorที่สามารถใช้ตรวจสอบว่าวัตถุมีคุณสมบัติหรือไม่


5

วิธีที่ใช้งานได้ดีในการจัดการกับสถานการณ์เช่นนี้คือการไม่ตรวจสอบอย่างชัดเจนว่ามีตัวแปรอยู่หรือไม่ แต่เพียงดำเนินการก่อนและตัดการใช้งานครั้งแรกของตัวแปรที่อาจไม่มีอยู่ในลอง / ยกเว้น 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

ฉันสร้างฟังก์ชั่นที่กำหนดเอง

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

จากนั้นฟังก์ชั่นการโทรจะคล้ายvariable_nameกับการแทนที่ด้วยตัวแปรที่คุณต้องการตรวจสอบ:

exists("variable_name")

จะกลับมาTrueหรือFalse


2
ไม่นี่ใช้ไม่ได้ locals()คือ ... เอ่อ ... local to function exists😅
bgusach

1
1) ฟังก์ชั่น locals () เป็นของท้องถิ่น 2) ทำไมการมอบหมายพิเศษของ var_exists
เดฟ
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.