20

if not我对 中的陈述有疑问Python 2.7

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

它工作正常,除非0.0是关键字的值。我理解这是因为这是0被认为是“不”的事情之一。我的代码可能太长而无法发布,但这是一个类似的(尽管是简化的)示例:

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

这可行,但似乎有点笨拙。如果有人有另一种很好的方式,我将不胜感激。

4

6 回答 6

18

问题

你理解的没错。not 0(也)not 0.0返回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是检查参数是否为数字抽象类(感谢Copperfield指出这一点)。x

    Python 标准库文档的摘录解释你所需要的——除了复数:

    班级 编号。编号

    数字层次结构的根。如果您只想检查参数 x 是否为数字,而不关心类型,请使用isinstance(x, Number)

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

    这样,您就可以完全按照您想要的方式编写definitionof 。我认为这个解决方案是最好的解决方案,因为它的全面性square


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

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

    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
    

    您可以根据需要轻松更改/扩展要包含或排除的不同数据类型的上述条件。我认为这个解决方案是第二好的因为它的有效性检查是定制的

    (如cat建议的那样,上面的代码以更Python的方式完成)


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

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

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

    我认为这个解决方案是第三好的,因为它是最简单但功能最强大的检查之一

    此解决方案的唯一缺点是您不处理复杂类型。因此只能通过用户没有复数作为输入来实现。


  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)
    

    这个解决方案的优点是最简单

    ...但如果您不确切知道​​户会为输入提供什么,那么使用起来最危险否则,这个解决方案很好,也是最简单的。

    你的解决方案,我认为或多或少属于这一类。你知道用户会给出什么输入,用户不会给出什么。因此,使用此解决方案或您自己的解决方案:

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

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


鉴于您的情况,您可以使用上述任何解决方案来获得:

 [1, 9, 0, 81]

(旁注:为了便于阅读,我尝试将解决方案格式化为“规范解决方案”。这样,那些有相同问题的人以及将来访问此页面的人可能能够找到更全面和更全面的解决方案可读)

于 2016-02-23T08:56:29.400 回答
8

由于您使用None的是信号“未设置此参数”,那么这正是您应该使用is关键字检查的内容:

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

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

于 2016-02-23T09:02:56.290 回答
2
if x is None:
   print 'x is None'
于 2016-02-23T08:58:36.953 回答
1

据我了解,您想捕捉没有输入的情况:

if x is None:
    ...

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

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"

因为Noneis not an intor afloat你也可以省略第一个条件并写:

if isinstance(x, (int, float)):
     ...
于 2016-02-23T09:13:15.547 回答
1

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

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 程序员会期待这种代码;它遵循“请求原谅比许可更容易”的原则。

旁白(也许):

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

def square(x):
    try:
        return float(x)**2
    except TypeError:
        print "You did not enter a real number"
        return None
于 2016-04-27T23:36:25.157 回答
0

你可以在这里处理异常。制作这样的代码

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=[]
于 2016-02-23T08:58:35.983 回答