python3 - Почему пустой список с оператором и все еще возвращает пустой список? [Дубликат]

Поскольку вы ссылаетесь на HTML 4.01:

Это Логический атрибут . Обе формы являются правильными, но спецификация рекомендует использовать предыдущий .


Если вы использовали XHTML, то вы должны использовать более длинную версию .

HTML 5 также позволяет обе версии и удаляет рекомендацию для использования одного над другим (поскольку для совместимости с XHTML, который использовался как text / html, все современные браузеры могут обрабатывать оба синтаксиса ).

60
задан coldspeed 26 May 2018 в 18:48
поделиться

7 ответов

TL; DR

Логический AND (and):

Возвращает первое значение False, если оно есть, else возвращает последнее значение в выражение

Логическое ИЛИ (or):

Возвращает первое значение Truthy, если оно есть, иначе верните последнее значение в выражении.


return len(args) and max(args) - min(args)

Является very питоновым лаконичным способом:

< blockquote>

, если args не пуст, верните результат из max(args) - min(args).

Операторы and и or не ограничены работой или возвращающих логические значения. Здесь можно протестировать любой объект со значением правдоподобия. Это включает в себя int, str, list, dict, tuple, set, NoneType и пользовательские объекты.

Обратите внимание, что это более сжатый способ построения выражения if-else:

return exp1 and exp2

Должен (грубо) перевести на:

r1 = exp1
if not r1:
    return r1

return exp2

Вот несколько примеров того, как и где эти конструкции могут использоваться для ручного ввода недопустимого ввода.

Пример с and (как показано OP)

Возвращает разницу между min и max группы аргументов.

def foo(*args):
     return len(args) and max(args) - min(args)

foo(1, 2, 3, 4, 5)
4

foo()
0

Поскольку and , второе выражение также должно быть оценено, если первое - True. Обратите внимание, что если первое выражение оценивается как Truthy, возвращаемый результат будет всегда результатом второго выражения .

Если первое выражение оценивается как Falsey, тогда возвращаемый результат является результатом первого выражения.

Если foo принимает любые аргументы, len(args) больше 0 (положительное число), поэтому Возвращаемый результат - max(args) - min(args).

Если foo не принимает аргументы, len(args) - 0, который является Falsey, и возвращается 0.

Обратите внимание, что альтернативным способом записи этой функции было бы следующее:

def foo(*args):
    if not len(args):
        return 0

    return max(args) - min(args)

Пример с or

Возвращает все числа над 9000.

def foo(*args):
     return [x for x in args if x > 9000] or 'No number over 9000!'

foo(9004, 1, 2, 500)
[9004]

foo(1, 2, 3, 4)
'No number over 9000!'

В этом случае используется or. Если первым выражением является Truthy, то возвращаемый результат является результатом первого выражения. В противном случае оба выражения оцениваются, а результат возвращается в результате второго выражения.

foo выполняет фильтрацию в списке, чтобы сохранить все числа над 9000. Если существуют такие числа, результатом понимания списка является непустой список, который является Truthy, поэтому он возвращается (здесь короткое замыкание в действии).

Если таких чисел нет, то результатом списка comp является [], который является Falsey. Итак, второе выражение теперь оценивается (непустая строка) и возвращается.

И альтернативой для этой функции будет:

def foo(*args):
    r = [x for x in args if x > 9000]
    if not r:
        return 'No number over 9000!' 

    return r
73
ответ дан coldspeed 15 August 2018 в 22:33
поделиться
  • 1
  • 2
    Я думаю, следует отметить, что условные выражения Python сделали этот синтаксис менее распространенным. Я, конечно, предпочитаю max (args) - min (args), если len (args) else 0 к оригиналу. – richardb 30 October 2017 в 09:07
  • 3
    Другой общий, который сначала запутывает, присваивает значение, если оно не существует: «some_var = arg или 3». – Erik 30 October 2017 в 09:09
  • 4
    @Baldrickk, прежде чем люди начнут бить этот синтаксис в пользу тройных операторов, имейте в виду, что когда дело доходит до n-ary выражения условий, тройные операторы могут быстро выйти из-под контроля. Например, if ... else (if ... else (if ... else (if ... else ...))) можно просто переписать как ... and ... and ... and ... and ..., и в этот момент действительно становится трудно утверждать, что читаемость для обоих случаев. – coldspeed 30 October 2017 в 11:15
  • 5
    Это не pythonic, чтобы пожертвовать ясностью для краткости, но это не так. Это хорошо известная идиома. Это идиома, которую вы должны изучать, как и любая другая идиома, но вряд ли «жертвует ясностью». – Miles Rout 30 October 2017 в 22:31

Цитирование из Документы Python

Обратите внимание, что ни and, ни or не ограничивают значение и тип, они возвращаются к False и True, а скорее вернет последний оцененный аргумент. Иногда это полезно, например, если s - это строка, которая должна быть заменена значением по умолчанию, если оно пустое, выражение s or 'foo' дает требуемое значение.

Итак, вот как Python был разработан для оценки булевых выражений, а приведенная выше документация дает нам представление о том, почему они это сделали.

Чтобы получить логическое

return bool(len(args) and max(args)-min(args))

Почему?

Короткое замыкание.

Например:

2 and 3 # Returns 3 because 2 is Truthy so it has to check 3 too
0 and 3 # Returns 0 because 0 is Falsey and there's no need to check 3 at all

То же самое также для or, то есть он вернет выражение, которое является Truthy , как только оно его обнаружит, потому что оценка остальной части выражения является избыточной.

Вместо этого возвращаемого хардкора True или False, Python возвращает Truthy или Falsey , которые в любом случае будут оцениваться с помощью True или False. Вы можете использовать выражение как есть, и оно все равно будет работать.


Чтобы узнать, что Truthy и Falsey , проверьте Patrick Ответ Хау

12
ответ дан Amit Joki 15 August 2018 в 22:33
поделиться

Да. Это правильное поведение и сравнение.

По крайней мере, в Python A and B возвращает B, если A по существу True, в том числе, если A NOT Null, NOT None НЕ пустой контейнер (например, пустой list, dict и т. Д.). A возвращается IFF A по существу False или None или Empty или Null.

С другой стороны, A or B возвращает A, если A по существу True, в том числе, если A НЕ НУЛЬНО, NOT None NOT Пустое контейнер (например, пустой list, dict и т. д.), в противном случае он возвращает B.

Легко не заметить (или игнорировать) это поведение, потому что в Python любой непустой объект non-null оценивается как True, обрабатывается как логическое.

Для Например, все следующие будут печатать «True»

if [102]: 
    print "True"
else: 
    print "False"

if "anything that is not empty or None": 
    print "True"
else: 
    print "False"

if {1, 2, 3}: 
    print "True"
else: 
    print "False"

С другой стороны, все следующие будут печатать «False»

if []: 
    print "True"
else: 
    print "False"

if "": 
    print "True"
else: 
    print "False"

if set ([]): 
    print "True"
else: 
    print "False"
0
ответ дан emmanuelsa 15 August 2018 в 22:33
поделиться
  • 1
    Спасибо. Я хотел написать A по существу True. Исправленный. – emmanuelsa 31 October 2017 в 06:47

Gotchas

Да, есть несколько gotchas.

fn() == fn(3) == fn(4, 4)

Во-первых, если fn возвращает 0, вы не можете знать если он был вызван без какого-либо параметра, с одним параметром или с несколькими равными параметрами:

>>> fn()
0
>>> fn(3)
0
>>> fn(3, 3, 3)
0

Что означает fn?

Затем Python является динамическим языком. Он не указан нигде, что делает fn, каким должен быть его вход и каким должен быть его выход. Поэтому очень важно правильно назвать функцию. Точно так же аргументы не должны называться args. delta(*numbers) или calculate_range(*numbers) может лучше описать, что должна делать функция.

Ошибки аргумента

Наконец, предполагается, что логический оператор and предотвращает отказ функции если вызывается без каких-либо аргументов. Он все еще терпит неудачу, если какой-то аргумент не является числом:

>>> fn('1')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 2, in fn
TypeError: unsupported operand type(s) for -: 'str' and 'str'
>>> fn(1, '2')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 2, in fn
TypeError: '>' not supported between instances of 'str' and 'int'
>>> fn('a', 'b')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 2, in fn
TypeError: unsupported operand type(s) for -: 'str' and 'str'

Возможная альтернатива

Вот способ записи функции в соответствии с «Легче спросить для прощения, чем разрешения ». Принцип :

def delta(*numbers):
    try:
        return max(numbers) - min(numbers)
    except TypeError:
        raise ValueError("delta should only be called with numerical arguments") from None
    except ValueError:
        raise ValueError("delta should be called with at least one numerical argument") from None

В качестве примера:

>>> delta()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 7, in delta
ValueError: delta should be called with at least one numerical argument
>>> delta(3)
0
>>> delta('a')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 5, in delta
ValueError: delta should only be called with numerical arguments
>>> delta('a', 'b')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 5, in delta
ValueError: delta should only be called with numerical arguments
>>> delta('a', 3)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 5, in delta
ValueError: delta should only be called with numerical arguments
>>> delta(3, 4.5)
1.5
>>> delta(3, 5, 7, 2)
5

Если вы действительно не хотите создавать исключение, когда delta вызывается без каких-либо аргументов , вы можете вернуть некоторое значение, которое невозможно в противном случае (например, -1 или None):

>>> def delta(*numbers):
...     try:
...         return max(numbers) - min(numbers)
...     except TypeError:
...         raise ValueError("delta should only be called with numerical arguments") from None
...     except ValueError:
...         return -1 # or None
... 
>>> 
>>> delta()
-1
3
ответ дан Eric Duminil 15 August 2018 в 22:33
поделиться

и / или выполнять логическую логику, но при их сравнении они возвращают одно из фактических значений. При использовании и значения оцениваются в булевом контексте слева направо. 0, '', [], (), {} и None являются ложными в булевом контексте; все остальное истинно.

Если все значения истинны в булевом контексте и возвращают последнее значение.

>>> 2 and 5
5
>>> 2 and 5 and 10
10

Если какое-либо значение ложно в булевом контексте и возвращает первое ложное значение.

>>> '' and 5
''
>>> 2 and 0 and 5
0

Итак, код

return len(args) and max(args)-min(args)

возвращает значение max(args)-min(args), когда есть args else, он возвращает len(args), который равен 0.

7
ответ дан Nithin Varghese 15 August 2018 в 22:33
поделиться

Является ли этот легитимный / надежный стиль или есть какие-либо ошибки на этом?

Это законно, это оценка короткого замыкания , где возвращается последнее значение.

Вы являетесь хорошим примером. Функция вернет 0, если аргументы не переданы, и код не должен проверять частный случай отсутствия аргументов.

Другим способом использования этого параметра является аргумент по умолчанию Нет аргументов для изменяемого примитива, например, пустой список:

def fn(alist=None):
    alist = alist or []
    ....

Если какое-то неправдоподобное значение передается в alist по умолчанию используется пустой список, удобный способ избежать оператора if и изменчивого аргумента аргумента по умолчанию

4
ответ дан salparadise 15 August 2018 в 22:33
поделиться

Является ли этот легитимный / надежный стиль или есть какие-либо ошибки на этом?

Я хотел бы добавить к этому вопросу, что он не только законный и надежный, но и он ультра практичный. Вот простой пример:

>>>example_list = []
>>>print example_list or 'empty list'
empty list

Поэтому вы действительно можете использовать его в своих интересах. Для того, чтобы быть таким, я вижу это:

Or operator

Оператор or Python возвращает первое значение Truth-y или последнее значение и останавливается

And operator

Оператор and Python возвращает первое значение False-y или последнее значение и останавливает

. За сцены

В python все числа интерпретируются как True, за исключением 0. Поэтому, говоря:

0 and 10 

, это то же самое, что:

False and True

Который явно False. Поэтому логично, что он возвращает 0

0
ответ дан scharette 15 August 2018 в 22:33
поделиться
Другие вопросы по тегам:

Похожие вопросы: