Python - 如果不是带有 0.0 的语句

Python - If not statement with 0.0

我对 Python 2.7 中的 if not 语句有疑问。

我写了一些代码并使用了 if not 语句。在我编写的代码的一部分中,我引用了一个包含 if not 语句的函数来确定是否输入了可选关键字。

它工作正常,除非 0.0 是关键字的值。我理解这是因为 0 是被认为是 'not' 的事物之一。我的代码可能太长 post,但这是一个类似的(尽管已简化)示例:

def square(x=None):
    if not x:
        print "you have not entered x"
    else:
        y=x**2
        return y

list=[1, 3, 0 ,9]
output=[]


for item in list:
    y=square(item)
    output.append(y)

print output

然而,在这种情况下,我得到了:

you have not entered x
[1, 9, None, 81]    

我想去哪里:

[1, 9, 0, 81]

在上面的示例中,我可以使用列表理解,但假设我想使用该函数并获得所需的输出,我该怎么做呢?

我的一个想法是:

def square(x=None):
    if not x and not str(x).isdigit():
        print "you have not entered x"
    else:
        y=x**2
        return y

list=[1, 3, 0 ,9]
output=[]


for item in list:
    y=square(item)
    output.append(y)

print output

这可行,但似乎有点笨拙。如果有人有其他方法会很好,我将不胜感激。

问题

你没看错。 not 0(还有 not 0.0)returns True Python。可以做简单的测试看看这个:

a = not 0
print(a)

Result: True

至此,问题就说明了。这一行:

if not x:

必须改成别的。


解决方案

有几种方法可以解决此问题。我只是要 列出 它们,从我认为最好的解决方案到最后可能的解决方案:


  1. 处理所有可能的有效案例

    因为 square 自然应该 期望一个排除复数 的数字输入,否则 return 应该是一个错误,我认为最好的解决方案是使用 if not isinstance(x, numbers.Number) or isinstance(x, numbers.Complex):

    进行评估
    def square(x=None):
        if not isinstance(x, numbers.Number) or isinstance(x, numbers.Complex): # this sums up every number type, with the exclusion of complex number
            print ("you have not entered x")
        else:
            y=x**2
            return y
    
    list=[1, 3, 0 ,9]
    output=[]
    
    for item in list:
        y=square(item)
        output.append(y)
    
    print (output)
    

    numbers.Number is the abstract class to check if argument x is a number (credit to Copperfield 指出这一点)。

    摘自 Python Standard Library Documentation 解释 只是 您需要什么 - 除了复数:

    class numbers.Number

    The root of the numeric hierarchy. If you just want to check if an argument x is a number, without caring what kind, use isinstance(x, Number).

    但是,您不希望输入是复数。所以,只需使用 or isinstance(x, numbers.Complex)

    省略它

    This way, you write the definition of square exactly the way you want it. This solution, I think, is the best solution by the virtue of its comprehensiveness.


  1. 只处理您想要处理的数据类型

    如果您有一个有效的输入数据类型列表,您也可以列出您想要处理的特定数据类型。也就是说,您不想处理您指定以外的数据类型的情况。示例:

    if not instance(x, int): #just handle int
    if not instance(x, (int, float)): #just handle int and float
    if not instance(x, (numbers.Integral, numbers.Rational)): #just handle integral and rational, not real or complex
    

    You may change/extend the condition above easily for different data types that you want to include or to excluded - according to your need. This solution, I think, is the second best by the virtue of its customization for its validity checking.

    (上面的代码是用 Python 的方式完成的,正如 cat 所建议的那样)


  1. 不处理不可能的情况:您知道用户不会输入什么

    更宽松地考虑一下,如果您知道 - 不是像第二个解决方案中那样要处理的数据类型 - 但用户 不会 放置的数据类型,那么你可以像这样进行更宽松的条件检查:

    if not isinstance(x, numbers.Number): # this is ok, because the user would not put up complex number
    

    This solution, I think, is the third best by the virtue of being one of the simplest yet powerful checking.

    此解决方案的唯一缺点是您无法处理复杂类型。由于用户不会以复数作为输入,因此只能通过实施。


  1. 仅处理可能导致错误的已知可能输入的输入错误

    例如,如果您知道 x 总是 intNone - 因此唯一可能的输入错误是 None - 那么我们可以简单地编写逻辑来避免y 被评估 只有 xNone 时像这样:

    def square(x=None):
        if x is None:
            print ("you have not entered x")
        else:
           y=x**2
           return y
    
    list=[1, 3, 0 ,9]
    output=[]
    
    for item in list:
        y=square(item)
        output.append(y)
    
    print (output)
    

    This solution has the virtue of being the simplest.

    ...但最危险被使用如果你不知道确切 用户会输入什么。否则,这个解决方案很好,也是最简单的。

    你的解决方案,我觉得或多或少属于这一类。您知道用户将提供什么输入以及用户不会提供什么。因此,使用此解决方案或您自己的解决方案:

    if not x and not str(x).isdigit():
    

    很好,只是示例解决方案更简单


鉴于你的情况,你可以使用上面的任何解决方案得到:

 [1, 9, 0, 81]

(旁注:为了便于阅读,我尝试将解决方案的格式设置为 "canonical solutions"。这样,那些有相同问题并在以后可能会找到更全面和可读性更强的解决方案)

你可以在这里处理异常。编写这样的代码

def square(x):
    if not x:
        print "you have not entered x"
    else:
        try:
            int(y)=x**2
            return y
        except TypeError:
            pass


list=[1, 3, 0 ,9]
output=[]
if x is None:
   print 'x is None'

既然您使用 None 来表示 "this parameter is not set",那么这正是您应该使用 is 关键字检查的内容:

def square(x=None):
    if x is None:
        print "you have not entered x"
    else:
        y=x**2
        return y

检查类型既麻烦又容易出错,因为您必须检查所有可能的输入类型,而不仅仅是int

据我了解,您想捕获未提供输入的情况:

if x is None:
    ...

以及不是数字的情况。对于第二个,你最终会遇到很多问题,因为你可能希望在未来允许 numpy-ndarrays 或其他东西,通常我只是建议不要费心排除其他 类 但如果你只想允许 intfloat 然后使用

if isinstance(x, (int, float, ...)):
    ...

...代表其他允许的类(可能是DecimalFractions)。

所以你可以这样写:

if x is not None and isinstance(x, (int, float)):
     return x**2
else:
     print "you have not entered x"

因为 None 不是 int 也不是 float 你也可以省略第一个条件并写成:

if isinstance(x, (int, float)):
     ...

如果您可以识别所有输入必须兼容的单一类型,那么您可以转换它并处理异常:

def square(x=None):
    try:
        return float(x)**2
    except TypeError:
        print "You did not enter a real number"
        return None # Explicit is better than implicit

这有几个优点。

  • 它强制用户发送给您的任何内容都与 float 兼容。这可以是任何数字、包含数字 ('5.0') 的字符串或任何其他可以转换为 float 的内容。 (float 个实例原样返回。)
  • 很简单。您的方法中没有奇怪的魔法。你没有打破鸭子打字。您只是在执行您的要求以使事情正常工作。
  • 它不容易受到实际检查类型所涉及的问题的影响。您的来电者可以告诉您他们的自定义类型如何转换为 float。 Python 提供了 __float__ 魔术方法,因此如果您的用户有奇特的类型并需要使用您的功能,他们不会沉没。
  • 这是惯用语。有经验的 Python 程序员会期待这种代码;它遵循 "easier to ask forgiveness than permission" 原则。

旁白(可能):

如果 None 是无效值,请不要将其设为默认值。只需强制调用者提供输入:

def square(x):
    try:
        return float(x)**2
    except TypeError:
        print "You did not enter a real number"
        return None