函数调用中的条件参数扩展

问题描述 投票:0回答:2

我想根据一些前提条件有条件地替换文件中的一行并写入新内容。 我选择的方式是:

n_file = []
For line in file.getlines():
    n_file.append( line.replace(
            *("foo", "bar") if False else
            *("baz", "bam") if True else
            # ...
            *("", "") # no replacement
    ))
new_file.write(n_file)  

但是我遇到了一个我不明白的问题。 问题是星号。每当

replace()
函数的非第一个位置有星号时,它就会给我一个语法错误,我完全不知道为什么。

你可以自己尝试一下。在 Python 2 或 3 中也是一样的。

def tf(a,b): print( str(a) +" "+ str(b) )

tf( *(1,1) if False else (2,2) if False else (3,3) )
# prints '3 3' as expec... intended

tf( *(1,1) if False else *(2,2) if False else *(3,3) )
# invalid syntax         ^

tf( (1,1) if False else (2,2) if False else (3,3) )
# missing 1 required positional argument: 'b'

虽然我找到了解决我的特定问题的方法。我仍然不明白为什么一定要这样。 我最好的猜测是,它与扩展参数的位置有关,但仍然无法解释为什么星号只能位于第一项

亲切的问候。

ps。 这是我的第一个问题,我不确定标题是否合适(或者如何具体调用这个 if-thingy,发生在

replace()
-args 中)。 寻找这个问题的答案很麻烦,所以如果你有更好的标题或标签建议,请告诉我。

python if-statement conditional-statements argument-unpacking
2个回答
2
投票

您需要用括号将整个三元组级联括起来,以便首先对它们进行求值,然后继续解包表达式的结果。 splat 运算符位于括号之外:

tf( *((1,1) if False else (2,2) if False else (3,3)) ) #-> 3 3

更具体地说:

...
n_file.append( line.replace(
            **(("foo", "bar") if False else
               ("baz", "bam") if True else
                ...
               ("", "")) # no replacement
    ))

OTOH,当您像这样级联三元组时,代码会变得非常难以阅读。使用普通的

if
子句会更具可读性,分配给一个变量,然后解压该变量。


0
投票

函数定义

def tf(a, b):

   print(str(a) + " " + str(b))

该函数有 2 个参数,

a
b

第一个案例

函数调用

tf(*(1,1) if False else (2,2) if False else (3,3))

会起作用,因为,

  1. 首先执行表达式

    (1,1) if False else (2,2) if False else (3,3)
    ,结果为
    (3,3)

  2. 然后函数调用变成

    tf(*(3,3))
    ,就像将星号参数传递给函数一样。

  3. 这样就会匹配到函数定义,并且执行函数,也就是

    3 3

第二种情况

tf(*(1,1) if False else *(2,2) if False else *(3,3))

这会失败,因为,

  1. 表达式
    *(1,1) if False else *(2,2) if False else *(3,3)
    是无效表达式。
  2. 这会产生语法错误

第三种情况

tf((1,1) if False else (2,2) if False else (3,3))

这会失败,因为

  1. 表达式

    (1,1) if False else (2,2) if False else (3,3)
    将计算为
    (3,3)
    ,这是一个元组。

  2. 此结果是单个对象,而函数签名要求传递 2 个参数。

  3. 因此

    (3, 3)
    将被传递为
    a
    。缺少
    b
    的值,并且它是必需的位置参数,因此出现错误
    missing 1 required positional argument: 'b'

© www.soinside.com 2019 - 2024. All rights reserved.