ฉันได้รับข้อผิดพลาดในเงื่อนไข IF ผมทำอะไรผิดหรือเปล่า?
มีเหตุผลที่คุณได้รับSyntaxErrorคือไม่มี&&ตัวดำเนินการใน Python ในทำนองเดียวกัน||และ!มีความไม่ถูกต้องผู้ประกอบการหลาม
ตัวดำเนินการบางอย่างที่คุณอาจรู้จักจากภาษาอื่นมีชื่อแตกต่างกันใน Python ผู้ประกอบการเชิงตรรกะ&&และ||จะเรียกว่าจริงและand orในทำนองเดียวกันผู้ประกอบการปฏิเสธตรรกะที่เรียกว่า!not
ดังนั้นคุณสามารถเขียน:
if len(a) % 2 == 0 and len(b) % 2 == 0:
หรือแม้กระทั่ง:
if not (len(a) % 2 or len(b) % 2):
ข้อมูลเพิ่มเติมบางอย่าง (ที่อาจมีประโยชน์):
ฉันสรุปผู้ประกอบการ "เทียบเท่า" ในตารางนี้:
+------------------------------+---------------------+
| Operator (other languages) | Operator (Python) |
+==============================+=====================+
| && | and |
+------------------------------+---------------------+
| || | or |
+------------------------------+---------------------+
| ! | not |
+------------------------------+---------------------+
ดูเอกสารประกอบของ Python: 6.11 ดำเนินการบูลี
นอกจากตัวดำเนินการเชิงตรรกะ Python ยังมีตัวดำเนินการ bitwise / binary:
+--------------------+--------------------+
| Logical operator | Bitwise operator |
+====================+====================+
| and | & |
+--------------------+--------------------+
| or | | |
+--------------------+--------------------+
ไม่มีการปฏิเสธบิตในหลามเป็น (เพียงบิตผกผันผู้ประกอบการ~- แต่ที่ไม่เทียบเท่าnot)
ดูเพิ่มเติมที่6.6 เลขคณิต Unary และการดำเนินการระดับบิต / ไบนารีและ6.7 การดำเนินการทางเลขฐานสอง
ตัวดำเนินการเชิงตรรกะ (เหมือนในภาษาอื่น ๆ ) มีข้อได้เปรียบที่สิ่งเหล่านี้จะลัดวงจร นั่นหมายความว่าถ้าตัวถูกดำเนินการตัวแรกกำหนดผลลัพธ์ไว้ผู้ดำเนินการรายที่สองจะไม่ได้รับการประเมินเลย
เพื่อแสดงสิ่งนี้ฉันใช้ฟังก์ชั่นที่รับค่าเพียงพิมพ์และส่งคืนอีกครั้ง สิ่งนี้มีประโยชน์ในการดูสิ่งที่ประเมินผลจริงเนื่องจากข้อความสั่งพิมพ์:
>>> def print_and_return(value):
... print(value)
... return value
>>> res = print_and_return(False) and print_and_return(True)
False
อย่างที่คุณเห็นเพียงคำสั่งการพิมพ์เพียงคำสั่งเดียวดังนั้น Python จึงไม่ได้ดูตัวถูกดำเนินการที่ถูกต้องจริงๆ
นี่ไม่ใช่กรณีสำหรับตัวดำเนินการไบนารี ผู้ประเมินทั้งสองตัวถูกดำเนินการเสมอ:
>>> res = print_and_return(False) & print_and_return(True);
False
True
แต่ถ้าตัวถูกดำเนินการตัวแรกนั้นไม่เพียงพอแน่นอนตัวดำเนินการที่สองจะถูกประเมิน:
>>> res = print_and_return(True) and print_and_return(False);
True
False
เพื่อสรุปนี่คือตารางอื่น:
+-----------------+-------------------------+
| Expression | Right side evaluated? |
+=================+=========================+
| `True` and ... | Yes |
+-----------------+-------------------------+
| `False` and ... | No |
+-----------------+-------------------------+
| `True` or ... | No |
+-----------------+-------------------------+
| `False` or ... | Yes |
+-----------------+-------------------------+
TrueและFalseเป็นตัวแทนของสิ่งbool(left-hand-side)ตอบแทนที่พวกเขาไม่จำเป็นต้องเป็นTrueหรือFalseพวกเขาเพียงต้องการที่จะกลับมาTrueหรือFalseเมื่อboolมีการเรียกร้องให้พวกเขา (1)
ดังนั้นใน Pseudo-Code (!) andและorฟังก์ชั่นทำงานเช่นนี้
def and(expr1, expr2):
left = evaluate(expr1)
if bool(left):
return evaluate(expr2)
else:
return left
def or(expr1, expr2):
left = evaluate(expr1)
if bool(left):
return left
else:
return evaluate(expr2)
โปรดทราบว่านี่เป็นรหัสหลอกไม่ใช่รหัสงูหลาม ใน Python คุณไม่สามารถสร้างฟังก์ชั่นที่เรียกว่าandหรือorเพราะสิ่งเหล่านี้เป็นคำหลัก นอกจากนี้คุณไม่ควรใช้ "ประเมิน" if bool(...)หรือ
การปรับพฤติกรรมของชั้นเรียนของคุณเอง
นี้โดยปริยายboolโทรสามารถใช้ในการกำหนดวิธีการเรียนของคุณประพฤติด้วยand, และornot
เพื่อแสดงให้เห็นว่าสิ่งนี้สามารถปรับแต่งได้ฉันใช้คลาสนี้ซึ่งprintเป็นสิ่งที่ติดตามสิ่งที่เกิดขึ้นอีกครั้ง:
class Test(object):
def __init__(self, value):
self.value = value
def __bool__(self):
print('__bool__ called on {!r}'.format(self))
return bool(self.value)
__nonzero__ = __bool__ # Python 2 compatibility
def __repr__(self):
return "{self.__class__.__name__}({self.value})".format(self=self)
ดังนั้นเรามาดูกันว่าจะเกิดอะไรขึ้นกับคลาสนั้นร่วมกับโอเปอเรเตอร์เหล่านี้:
>>> if Test(True) and Test(False):
... pass
__bool__ called on Test(True)
__bool__ called on Test(False)
>>> if Test(False) or Test(False):
... pass
__bool__ called on Test(False)
__bool__ called on Test(False)
>>> if not Test(True):
... pass
__bool__ called on Test(True)
ถ้าคุณไม่มี__bool__เมธอดแล้ว Python จะตรวจสอบว่าวัตถุนั้นมี__len__เมธอดหรือไม่และส่งคืนค่าที่มากกว่าศูนย์หรือไม่ อาจเป็นประโยชน์ที่จะรู้ในกรณีที่คุณสร้างคอนเทนเนอร์ตามลำดับ
ดูเพิ่มเติม4.1 ความจริงการทดสอบราคา
NumPy อาร์เรย์และคลาสย่อย
อาจจะเกินขอบเขตของคำถามเดิมเล็กน้อย แต่ในกรณีที่คุณติดต่อกับ NumPy อาร์เรย์หรือคลาสย่อย (เช่น Pandas Series หรือ DataFrames) การboolโทรโดยนัยจะเพิ่มความน่ากลัวValueError:
>>> import numpy as np
>>> arr = np.array([1,2,3])
>>> bool(arr)
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
>>> arr and arr
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
>>> import pandas as pd
>>> s = pd.Series([1,2,3])
>>> bool(s)
ValueError: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().
>>> s and s
ValueError: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().
ในกรณีเหล่านี้คุณสามารถใช้ตรรกะและฟังก์ชั่นจาก NumPy ซึ่งดำเนินการองค์ประกอบที่ชาญฉลาดand(หรือor):
>>> np.logical_and(np.array([False,False,True,True]), np.array([True, False, True, False]))
array([False, False, True, False])
>>> np.logical_or(np.array([False,False,True,True]), np.array([True, False, True, False]))
array([ True, False, True, True])
หากคุณกำลังจัดการกับบูลีนอาร์เรย์คุณสามารถใช้ตัวดำเนินการไบนารีกับ NumPy สิ่งเหล่านี้ทำการเปรียบเทียบองค์ประกอบที่ฉลาด (แต่ยังเป็นไบนารี):
>>> np.array([False,False,True,True]) & np.array([True, False, True, False])
array([False, False, True, False])
>>> np.array([False,False,True,True]) | np.array([True, False, True, False])
array([ True, False, True, True])
(1)
การboolเรียกใช้ตัวถูกดำเนินการต้องส่งคืนTrueหรือFalseไม่ถูกต้องอย่างสมบูรณ์ มันเป็นเพียงตัวถูกดำเนินการแรกที่ต้องการคืนค่าบูลีนด้วย__bool__วิธี:
class Test(object):
def __init__(self, value):
self.value = value
def __bool__(self):
return self.value
__nonzero__ = __bool__ # Python 2 compatibility
def __repr__(self):
return "{self.__class__.__name__}({self.value})".format(self=self)
>>> x = Test(10) and Test(10)
TypeError: __bool__ should return bool, returned int
>>> x1 = Test(True) and Test(10)
>>> x2 = Test(False) and Test(10)
นั่นเป็นเพราะandจริง ๆ แล้วคืนค่าตัวถูกดำเนินการแรกถ้าตัวถูกดำเนินการตัวแรกประเมินค่าFalseและถ้าประเมินตัวถูกTrueแล้วมันส่งคืนตัวถูกดำเนินการตัวที่สอง:
>>> x1
Test(10)
>>> x2
Test(False)
ในทำนองเดียวกันสำหรับorวิธีอื่น ๆ :
>>> Test(True) or Test(10)
Test(True)
>>> Test(False) or Test(10)
Test(10)
อย่างไรก็ตามหากคุณใช้พวกเขาในifคำแถลงifก็จะเรียกboolผลลัพธ์โดยปริยาย ดังนั้นคะแนนปลีกย่อยเหล่านี้อาจไม่เกี่ยวข้องกับคุณ