2016-01-15 2 views
2

Возникает вопрос о Idiomatic Python - checking for zero, но этот вопрос также рассматривается с проверкой типа переменных в рамках условий.Объявление множественного условия при проверке на числовой нуль - python

С учетом инструкции стиля 0 if not variable else variable, это позволит пропустить предмет объекта, например.

>>> x, y = None, [] 
>>> 0 if not(x and y) else x/y 
0 
>>> x, y = None, 0 
>>> 0 if not(x and y) else x/y 
0 
>>> x, y = 0, 1 
>>> 0 if not(x and y) else x/y 
0 
>>> x, y = 2, "" 
>>> 0 if not(x and y) else x/y 
0 
>>> x, y = 2, 1 
>>> 0 if not(x and y) else x/y 
2 

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

>>> x, y = 2, "" 
>>> 0 if (x&y) == 0 else x/y 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
TypeError: unsupported operand type(s) for |: 'int' and 'str' 
>>> x,y = "","" 
>>> 0 if (x&y) == 0 else x/y 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
TypeError: unsupported operand type(s) for |: 'str' and 'str' 
>>> x,y = [],[] 
>>> 0 if (x&y) == 0 else x/y 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
TypeError: unsupported operand type(s) for |: 'list' and 'list' 

Как правило, при определении условия для проверки на числовое значение что-то вроде кода 0 if (x|y) == 0 else x/y еще pythonic/более подходящего?

Но это также проблематично, так как это давай логическому тип проскочить и что вызывает некоторые весьма тревожные вещи, как ZeroDivisionError или ValueError произойти, например:

>>> x,y = True, True 
>>> 0 if (x&y) == 0 else x/y 
1 
>>> x,y = True, False 
>>> 0 if (x&y) == 0 else x/y 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
ZeroDivisionError: integer division or modulo by zero 
>>> x,y = False, True 
>>> 0 if (x&y) == 0 else x/y 
0 
>>> x,y = False, True 
>>> 0 if (x&y) == 0 else math.log(x/y) 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
ValueError: math domain error 

Кроме того, это вызывает проблемы, когда типы переменных являются числовыми но несколько иначе:

>>> x, y = 1, 3. 
>>> 0 if (x|y) == 0 else math.log(x/y) 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
TypeError: unsupported operand type(s) for |: 'int' and 'float' 

а также тот факт, что оператор _or не может принять плавать, это странно:

>>> x, y = 1., 3. 
>>> 0 if (x&y) == 0 and type(x) == type(y) == float else math.log(x/y) 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
TypeError: unsupported operand type(s) for |: 'float' and 'float' 
>>> x, y = 1., 3. 
>>> 0 if (x&y) == 0. and type(x) == type(y) == float else math.log(x/y) 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
TypeError: unsupported operand type(s) for |: 'float' and 'float' 
>>> x, y = 1, 3 
>>> 0 if (x&y) == 0 and type(x) == type(y) == float else math.log(x/y) 
-1.0986122886681098 

Так что вопрос:

  • Что такое вещий способ проверить многократные переменный для нулевого значения?
  • Кроме того, важно не любить булевский тип slip и поднять ошибку, вместо того чтобы позволить ему вернуть нуль, как это можно сделать?
  • И как следует разрешить TypeError: unsupported operand type(s) for |: 'float' and 'float' для проверки (x|y) == 0 с x и y как типы с плавающей запятой?
+4

Если у вас есть числовые операции, которые зависят от конкретного типа обоих операндов, очевидное (отсюда вещий) решение либо явно проверить типы обоих операндов или обрабатывать ожидаемые исключения. –

+1

Что касается явной проверки: «0 in (x, y)»? –

+0

@ A.Haaji это не сработает при буле: '0 in (True, False) => True' –

ответ

4

С PEP 20 «s„Простым лучше, чем комплекс“в виде, я бы утверждать, что, если вы хотите проверить, имеет ли значение числового типа, отличный от булева (ума: Boolean является числового типа в Python и 1/True), самый pythonic способ сделать это - сделать именно это, явно, без каких-либо поразрядных операций или полагаться на неявные проверки.

import numbers 

if not isinstance(y, numbers.Number) or type(y) is bool: 
    raise TypeError("y must be a number") 
return x/y if y else 0 
+0

Прохладный! Не знал, что в «номерах» есть классные мета и классы! – alvas

Смежные вопросы