Я отримую помилку, якщо ІФ умовно. Що я роблю неправильно?
Причина, що ви отримуєте, SyntaxErrorполягає в тому, що &&в Python немає оператора. Точно так же ||і !є недійсним оператори 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 також має бітові / бінарні оператори:
+--------------------+--------------------+
| Logical operator | Bitwise operator |
+====================+====================+
| and | & |
+--------------------+--------------------+
| or | | |
+--------------------+--------------------+
У Python немає бітового заперечення (просто бітовий зворотний оператор ~- але це не еквівалентно not).
Див. Також 6.6. Одинарні арифметичні та бітові / двійкові операції та 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).
Отже, у Псевдокодексі (!) Функції 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. У Python ви не можете створювати функції, викликані andабо orтому, що це ключові слова. Також ніколи не слід використовувати "оцінювати" або if bool(...).
Налаштування поведінки ваших власних занять
Цей неявний boolвиклик може бути використаний для настройки , як ваші класи поводяться з and, orі not.
Щоб показати, як це можна налаштувати, я використовую цей клас, який знову 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 або 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результат. Тож ці тонкі бали можуть не бути актуальними для вас.