Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/287.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
为什么会有";可变默认参数fix“;python新手问:语法太难看了_Python_Mutable_Names - Fatal编程技术网

为什么会有";可变默认参数fix“;python新手问:语法太难看了

为什么会有";可变默认参数fix“;python新手问:语法太难看了,python,mutable,names,Python,Mutable,Names,现在遵循并基于 特权 转到并向下滚动至“默认参数值”。在这里,您可以找到以下内容: def bad_append(new_item, a_list=[]): a_list.append(new_item) return a_list def good_append(new_item, a_list=None): if a_list is None: a_list = [] a_list.append(new_item) return a_

现在遵循并基于

特权 转到并向下滚动至“默认参数值”。在这里,您可以找到以下内容:

def bad_append(new_item, a_list=[]):
    a_list.append(new_item)
    return a_list

def good_append(new_item, a_list=None):
    if a_list is None:
        a_list = []
    a_list.append(new_item)
    return a_list
甚至还有一个与这个例子非常相似的例子,但实际上并没有说它“更好”

一种说法是 所以,这里的问题是:为什么在一个已知问题上的“好”语法像在一个编程语言中那样丑陋

编辑:

另一种说法是 我不是在问(谢谢马克的链接)

我在问为什么没有更简单的替代内置语言

我认为更好的方法可能是在
def
本身中执行一些操作,其中name参数将附加到
def
可变对象中的“local”或“new”。比如:

def better_append(new_item, a_list=immutable([])):
    a_list.append(new_item)
    return a_list

我相信有人可以提供更好的语法,但我也猜一定有一个很好的解释来解释为什么没有这样做。

这就是所谓的“可变默认值陷阱”。见:

基本上,
a_list
是在程序第一次被解释时初始化的,而不是每次调用函数时(正如您从其他语言中所期望的那样)。因此,每次调用函数时都不会得到一个新的列表,而是重复使用同一个列表

我想这个问题的答案是,如果你想在列表中添加一些东西,只需添加,而不需要创建函数

这:

>>> my_list = []
>>> my_list.append(1)
比以下内容更清晰、更易于阅读:

>>> my_list = my_append(1)

在实际情况中,如果需要这种行为,您可能会创建自己的类,该类具有管理其内部列表的方法

您可能不应该将这两个函数定义为好函数和坏函数。 您可以将第一个与列表或字典一起使用,以实现对相应对象的就地修改。 如果你不知道可变对象是如何工作的,但如果你知道你在做什么,这个方法会让你头疼,我认为这是可以的


因此,您有两种不同的方法来传递提供不同行为的参数。这很好,我不会更改它。

默认参数在执行
def
语句时进行计算,这可能是最合理的方法:这通常是需要的。如果情况并非如此,当环境稍有变化时,可能会导致混乱的结果


用神奇的
local
方法或类似的方法进行区分远非理想。Python试图使事情变得非常简单,并且没有明显、清晰的替代品来替代当前的样板文件,而不是破坏Python当前具有的相当一致的语义。

如果您不是在谈论列表,而是谈论awesomeset,一个您刚刚定义的类,该怎么办?您想在每个类中定义“.local”吗

可能有用,但很快就会变老。很快,“if a is None:a=CorrectObject()”模式就成了第二天性,你不会觉得它难看——你会发现它很有启发性


问题不在于语法,而在于语义——默认参数的值在函数定义时计算,而不是在函数执行时计算

一个函数的非常特殊的用例,它允许你选择性地传递一个列表进行修改,但是除非你特别地传递一个列表,否则它会生成一个新的列表,这绝对不值得使用特殊的语法。说真的,如果要对该函数进行多次调用,为什么要对序列中的第一个调用进行特殊处理(只传递一个参数),以将其与其他调用区分开来(需要两个参数才能不断丰富现有列表)?!例如,考虑一些类似的情况(假设“代码> BestEnter < /COD>”做了一些有用的事情,因为在当前的示例中,调用它代替直接的代码>将是疯狂的。 这简直是疯了,显然应该是

def thecaller(n):
  newlist = []
  for x in range(n):
    if fee(x):
      betterappend(foo(), newlist)
    else:
      betterappend(fie(), newlist)
始终使用两个参数,避免重复,并构建更简单的逻辑


引入特殊用例语法鼓励和支持特殊用例,而鼓励和支持这种极其特殊的用例实际上没有多大意义——现有的、完全规则的语法对于用例极其罕见的良好用途来说是很好的;-)

我认为你把优雅的语法和语法上的甜点混淆了。python语法清楚地传达了这两种方法,只是碰巧正确的方法看起来不如不正确的方法优雅(就语法行而言)。但是,由于不正确的方法,是好的…不正确的,它的优雅是无关的。至于你在better_append中演示的东西为什么没有实现,我想
应该有一个——最好只有一个——明显的方法来实现。
胜过优雅的小收获

这比good_append()好,依我看:


你也可以格外小心,检查一个列表是否是一个列表…

我编辑了这个答案,将问题中许多评论中的想法包括在内

你举的例子有缺陷。它会修改作为副作用传递的列表。如果您希望函数是这样工作的,那么使用默认参数是没有意义的。返回更新后的列表也没有意义。如果没有默认参数,问题就会消失

如果目的是返回一个新列表,则需要复制输入列表。Python更希望事情是显式的,所以由您来制作副本

def better_append(new_item, a_list=[]): 
    new_list = list(a_list)
    new_list.append(new_item) 
    return new_list 
对于稍有不同的内容,您可以制作一个生成器,它可以将列表或生成器作为输入:

def generator_append(new_item, a_list=[]):
    for x in a_list:
        yield x
    yield new_item
我认为您误解了Python以不同的方式对待可变和不可变的默认参数;那根本不是真的。相反,这个论点的不变性让你改变了
def ok_append(new_item, a_list=None):
    return a_list.append(new_item) if a_list else [ new_item ]
def better_append(new_item, a_list=[]): 
    new_list = list(a_list)
    new_list.append(new_item) 
    return new_list 
def generator_append(new_item, a_list=[]):
    for x in a_list:
        yield x
    yield new_item
def string_append(new_item, a_string=''):
    a_string = a_string + new_item
    return a_string