关于python:在一个任务中,提供回退fall-back值的最Python式方法是什么?

What is the most Pythonic way to provide a fall-back value in an assignment?

在Perl中,能够分配一个对象通常是很好的,但是如果从中分配的变量是"undef",则指定一些回退值。例如:

1
2
3
my $x = undef;
my $y = 2;
my $a = $x || $y;

在此之后,

1
$a == 2

在python中是否有一种简洁的方法来实现这一点,如果x值为none,或者将是一个完整的……

1
2
3
4
if x is not None
    a = x
else
    a = y

…是实现这一目标的最Python的方式吗?

编辑:很抱歉,正如一些评论者所指出的,我并不是真的在谈论未定义的值,而是在Perl中的"undef",这实际上不是一回事。但最初的问题并没有说明这一点。


自2.5以来:

如果你只想退而不退:

1
a = x if x is not None else y

如果还想在空字符串、false0等上回退:

1
a = x if x else y

1
a = x or y

对于未定义(从未定义,a.k.a.未绑定):

1
2
3
4
try:
  a = x
except NameError:
  a = y

或者更具黑客风格(我不建议这么做,但它很短):

1
a = vars().get('x',y)


首先,你可以充分利用三元:

1
a = y if x is None else x

但它不能解决你的问题。您要做的是更紧密地实现:

1
2
3
4
try:
    a = x
except:
    a = y


只是用Perl示例吹毛求疵:

1
my $x = undef;

此冗余代码可以缩短为:

1
my $x;

而下面的代码并没有做到你所说的那样:

1
my $a = $x || $y;

当$X为假时,它实际上将$Y分配给$A。假值包括undef、零和空字符串等。要只测试定义性,可以执行以下操作(从Perl5.10开始):

1
my $a = $x // $y;

我很确信没有"Python"的方法可以做到这一点,因为这不是Python的模式。控件不应到达优雅代码中未定义的变量引用。也有类似的想法是Python。最明显的是:

1
2
3
def myRange(start, stop=None):
    start, stop = (0, start) if stop is None else (start, stop)
    ...

重要的是,stop是在作用域中定义的,但调用方不必显式传递它,只需它接受了它的默认值,改变了参数的语义,这实际上导致第一个参数是可选的,而不是第二个参数,即使语言不允许没有这种巧妙的技巧。

也就是说,类似这样的东西可能会遵循这个前提,而不使用try-catch块。

1
a = locals().get('x', y)


我认为这会有帮助,因为问题归结为检查变量是否被定义:在Python中定义变量的简单方法?


有python的三元操作:

1
a = x if x is not None else y

2.5及以上版本。


重写的一种方法…

1
2
3
4
if x is not None
    a = x
else
    a = y

..是:

1
2
3
4
5
6
x = myfunction()

if x is None:
    x = y

print x

或者,使用异常(可能更多的是python'y,这取决于代码在做什么——如果因为出错而返回none,则使用异常可能是正确的方法):

1
2
3
4
5
6
try:
    x = myfunction()
except AnException:
    x ="fallback"

print x

尽管如此,您的原始代码确实没有任何问题:

1
2
3
4
if x is not None
    a = x
else
    a = y

它很长,但我发现阅读起来要比下面的一句话容易得多(而且要比Python的多):

1
2
a = x if x is not None else y
a = x or y

大多数依赖于if语句的解决方案都不适用于x为0或负数的情况。

1
2
3
4
5
6
>>> x = 0
>>> y = 2
>>> a = x or y
>>> a
2
>>>

如果您提前知道变量的名称,可以这样查找:

1
2
3
4
if 'x' in dir():
    a = x
except:
     a =y

不过,我觉得这个解决方案有点草率。我认为最好的方法是使用一个这样的试块:

1
2
3
4
try:
    a = x
else:
    a = y

如果它是函数的参数,你可以这样做:

1
2
3
4
5
6
7
def MyFunc( a=2 ):
    print"a is %d"%a

>>> MyFunc()
...a is 2
>>> MyFunc(5)
...a is 5

[编辑]为投票者。对于解决方案,I/EL位是不必要的,只是添加以使结果清晰。编辑它来删除if语句,如果它使它更清晰?