cre*_*gox 28 python mutable names
现在跟随我的一系列"python新手问题"并基于另一个问题.
转到http://python.net/~goodger/projects/pycon/2007/idiomatic/handout.html#other-languages-have-variables并向下滚动到"默认参数值".在那里你可以找到以下内容:
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
Run Code Online (Sandbox Code Playgroud)
在python.org上甚至还有一个"重要的警告",这个例子非常相同,并不是说它"更好".
所以,这里的问题是:为什么在一个已知问题上的"好"语法比在一个促进"优雅语法"和"易于使用"的编程语言中那样丑陋?
编辑:
我不是在问为什么或如何发生(感谢Mark的链接).
我问为什么没有更简单的替代内置语言.
我认为更好的方法可能是在def自身中做一些事情,其中name参数将附加到def可变对象中的"本地"或"新" .就像是:
def better_append(new_item, a_list=immutable([])):
a_list.append(new_item)
return a_list
Run Code Online (Sandbox Code Playgroud)
我相信有人可以提供更好的语法,但我也猜测必须有一个非常好的解释为什么没有这样做.
Set*_*eth 11
这被称为'可变默认陷阱'.请参阅:http://www.ferg.org/projects/python_gotchas.html#contents_item_6
基本上,a_list在首次解释程序时初始化,而不是每次调用函数时(正如您可能期望的那样).因此,每次调用该函数时,您都没有获得新列表,但是您正在重复使用相同的列表.
我想这个问题的答案是,如果你想将某些东西附加到列表中,就这样做,不要创建一个函数来完成它.
这个:
>>> my_list = []
>>> my_list.append(1)
Run Code Online (Sandbox Code Playgroud)
阅读比以下更清晰,更容易阅读:
>>> my_list = my_append(1)
Run Code Online (Sandbox Code Playgroud)
在实际情况中,如果您需要这种行为,您可能会创建自己的类,其中包含管理其内部列表的方法.
在def执行语句时评估默认参数,这可能是最合理的方法:它通常是想要的.如果不是这种情况,当环境稍微变化时,可能会导致令人困惑的结果.
区别于魔法local或类似的东西远非理想.Python试图使事情变得非常简单,并且没有明显的,明确的替代当前的样板,而不是诉诸于Python当前具有的相当一致的语义.
函数的极其具体的用例允许您选择传递一个列表进行修改,但除非您专门传递一个列表,否则会生成一个新列表,这绝对不值得使用特殊情况语法。说真的,如果您要多次调用此函数,为什么要对系列中的第一个调用进行特殊处理(仅传递一个参数)以将其与其他每个调用区分开来(这将需要两个参数)能够不断丰富现有的列表)?!例如,考虑类似的东西(当然假设它betterappend做了一些有用的事情,因为在当前的示例中,调用它来代替直接调用是疯狂的.append!-):
def thecaller(n):
if fee(0):
newlist = betterappend(foo())
else:
newlist = betterappend(fie())
for x in range(1, n):
if fee(x):
betterappend(foo(), newlist)
else:
betterappend(fie(), newlist)
Run Code Online (Sandbox Code Playgroud)
这简直是疯了,显然应该是,
def thecaller(n):
newlist = []
for x in range(n):
if fee(x):
betterappend(foo(), newlist)
else:
betterappend(fie(), newlist)
Run Code Online (Sandbox Code Playgroud)
始终使用两个参数,避免重复,并构建更简单的逻辑。
引入特殊情况语法鼓励和支持特殊情况用例,而鼓励和支持这种极其特殊的用例实际上没有多大意义——现有的、完全规则的语法对于用例极其罕见的良好用途来说就很好了;- )。