Чи підтримує Python коротке замикання?


Відповіді:



192

Замикання поведінки оператора and, or:

Давайте спочатку визначимо корисну функцію, щоб визначити, чи виконується щось чи ні. Проста функція, яка приймає аргумент, роздруковує повідомлення та повертає введення, не змінюючи.

>>> def fun(i):
...     print "executed"
...     return i
... 

Можна спостерігати поведінку короткого замикання Пітона з and, orоператорів в наступному прикладі:

>>> fun(1)
executed
1
>>> 1 or fun(1)    # due to short-circuiting  "executed" not printed
1
>>> 1 and fun(1)   # fun(1) called and "executed" printed 
executed
1
>>> 0 and fun(1)   # due to short-circuiting  "executed" not printed 
0

Примітка . Наступні значення інтерпретатор вважає помилковими:

        False    None    0    ""    ()    []     {}

Поведінка короткого замикання у функції: any(), all():

Python any()і all()функції також підтримують коротке замикання. Як показано в документах; вони оцінюють кожен елемент послідовності в порядку, поки не знаходять результат, який дозволяє достроково вийти з оцінки. Розгляньте приклади нижче, щоб зрозуміти обидва.

Функція any()перевіряє, чи будь-який елемент є True. Він припиняє виконання, як тільки зустрічається True, і повертає True.

>>> any(fun(i) for i in [1, 2, 3, 4])   # bool(1) = True
executed
True
>>> any(fun(i) for i in [0, 2, 3, 4])   
executed                               # bool(0) = False
executed                               # bool(2) = True
True
>>> any(fun(i) for i in [0, 0, 3, 4])
executed
executed
executed
True

Функція all()перевіряє, що всі елементи є істинними, і зупиняє виконання, як тільки виявляється False:

>>> all(fun(i) for i in [0, 0, 3, 4])
executed
False
>>> all(fun(i) for i in [1, 0, 3, 4])
executed
executed
False

Поведінка короткого замикання в ланцюговому порівнянні:

Крім того, в Python

Порівняння можуть бути пов'язані довільно ; наприклад, x < y <= zеквівалентний x < y and y <= z, за винятком того, що yвін оцінюється лише один раз (але в обох випадках zвзагалі не оцінюється, коли x < yвиявляється помилковим).

>>> 5 > 6 > fun(3)    # same as:  5 > 6 and 6 > fun(3)
False                 # 5 > 6 is False so fun() not called and "executed" NOT printed
>>> 5 < 6 > fun(3)    # 5 < 6 is True 
executed              # fun(3) called and "executed" printed
True
>>> 4 <= 6 > fun(7)   # 4 <= 6 is True  
executed              # fun(3) called and "executed" printed
False
>>> 5 < fun(6) < 3    # only prints "executed" once
executed
False
>>> 5 < fun(6) and fun(6) < 3 # prints "executed" twice, because the second part executes it again
executed
executed
False

Edit:
Ще один цікавий момент , щоб відзначити : - Logical and,or оператори в Python повертає операнд значення замість Boolean ( Trueабо False). Наприклад:

Операція x and yдає результатif x is false, then x, else y

На відміну від інших мов, наприклад &&, ||оператори в C, які повертають або 0, або 1.

Приклади:

>>> 3 and 5    # Second operand evaluated and returned 
5                   
>>> 3  and ()
()
>>> () and 5   # Second operand NOT evaluated as first operand () is  false
()             # so first operand returned 

Аналогічно orоператор повертає ліве найбільше значення, для якого bool(value)== Trueelse right most false значення (відповідно до поведінки короткого замикання), приклади:

>>> 2 or 5    # left most operand bool(2) == True
2    
>>> 0 or 5    # bool(0) == False and bool(5) == True
5
>>> 0 or ()
()

Отже, чим це корисно? Один із прикладів використання, наведених у Practical Python By Magnus Lie Hetland:
Скажімо, користувач повинен ввести своє ім’я, але може вирішити нічого не вводити. У цьому випадку ви хочете використовувати значення за замовчуванням '<unknown>'. Ви можете використовувати оператор if, але ви також можете викладати речі дуже стисло:

In [171]: name = raw_input('Enter Name: ') or '<Unkown>'
Enter Name: 

In [172]: name
Out[172]: '<Unkown>'

Іншими словами, якщо значення повернення з raw_input є істинним (не порожній рядок), воно присвоюється імені (нічого не змінюється); в іншому випадку за замовчуванням '<unknown>'призначено name.


1
Незначна каламбура: явний список хибних значень злегка вводить в оману. Будь-який тип може мати одне або кілька фальшивих значень. За угодою, всі числові типи зі значенням 0є falsy (так що це не просто 0, це 0.0, 0j, decimal.Decimal(0), fractions.Fraction(0)і т.д.), як і всі колекції з довжиною 0(так у верхній частині того, що ви перерахували, b''[PY3], u''[py2] і set()/ frozenset()є всі вбудовані модулі, які оцінюються як хибні), але визначені користувачем / сторонні типи можуть визначати свої власні (з __bool__[Py3] / __nonzero__[Py2] безпосередньо або опосередковано шляхом визначення __len__).
ShadowRanger

@ShadowRanger тут ваш коментар доповнить мою відповідь. дякую за додавання цієї примітки.
Гріеш Чаухан

Крім того, python подвійно оцінює умови короткого замикання, якщо пізніше вони використовуються як булеві символи ... якщо вони не містяться в операторі if, який є приватним
Ерік Аронесті

48

Так. Спробуйте наступне в інтерпретаторі python:

і

>>>False and 3/0
False
>>>True and 3/0
ZeroDivisionError: integer division or modulo by zero

або

>>>True or 3/0
True
>>>False or 3/0
ZeroDivisionError: integer division or modulo by zero
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.