相关疑难解决方法(0)

"最小的惊讶"和可变的默认论证

任何修补Python足够长的人都被以下问题咬伤(或撕成碎片):

def foo(a=[]):
    a.append(5)
    return a
Run Code Online (Sandbox Code Playgroud)

Python新手希望这个函数总能返回一个只包含一个元素的列表:[5].结果却非常不同,而且非常惊人(对于新手来说):

>>> foo()
[5]
>>> foo()
[5, 5]
>>> foo()
[5, 5, 5]
>>> foo()
[5, 5, 5, 5]
>>> foo()
Run Code Online (Sandbox Code Playgroud)

我的一位经理曾经第一次遇到这个功能,并称其为该语言的"戏剧性设计缺陷".我回答说这个行为有一个潜在的解释,如果你不理解内部,那确实非常令人费解和意想不到.但是,我无法回答(对自己)以下问题:在函数定义中绑定默认参数的原因是什么,而不是在函数执行时?我怀疑经验丰富的行为有实际用途(谁真的在C中使用静态变量,没有繁殖错误?)

编辑:

巴泽克提出了一个有趣的例子.再加上你的大部分评论和特别是Utaal,我进一步阐述了:

>>> def a():
...     print("a executed")
...     return []
... 
>>>            
>>> def b(x=a()):
...     x.append(5)
...     print(x)
... 
a executed
>>> b()
[5]
>>> b()
[5, 5]
Run Code Online (Sandbox Code Playgroud)

对我而言,似乎设计决策是相对于放置参数范围的位置:在函数内部还是"与它一起"?

在函数内部进行绑定意味着在调用函数时x有效地绑定到指定的默认值,而不是定义,这会产生一个深层次的缺陷:def在某种意义上,该行将是"混合"的(部分绑定)函数对象)将在定义时发生,并在函数调用时发生部分(默认参数的赋值).

实际行为更加一致:执行该行时,该行的所有内容都会得到评估,这意味着在函数定义中.

python language-design least-astonishment default-parameters

2458
推荐指数
31
解决办法
14万
查看次数

什么是避免作为空列表的默认参数的pythonic方法?

有时,使用默认参数(即空列表)似乎很自然.然而,Python在这些情况下会出现意外行为.

例如,我有一个功能:

def my_func(working_list = []):
    working_list.append("a")
    print(working_list)
Run Code Online (Sandbox Code Playgroud)

第一次使用默认值调用它将起作用,但之后的调用将使用不断更新的列表.

那么,获得我想要的行为的pythonic方法是什么(每个调用都有一个新的列表)?

python python-3.x

90
推荐指数
4
解决办法
4万
查看次数

作为一名学习Python的Java程序员,我应该注意什么?

我的大部分编程背景都是用Java编写的,而且我仍然使用Java编写大部分编程.但是,我开始在工作中学习一些辅助项目的Python,我想学习它尽可能独立于我的Java背景 - 即我不想只用Python编写Java.我应该注意哪些事情?

一个简单的例子 - 当浏览Python教程时,我发现了一个函数(例如列表)的默认可变参数被持久化(从调用到调用时记住).这对我作为Java程序员来说是违反直觉的,很难让我理解.(如果您不理解该示例,请参见此处此处.)

有人还向我提供了这个列表,我觉得这个列表很有用,但很简短.任何人都有任何其他Java程序员可能会滥用Python的例子......?或者Java程序员会错误地假设或难以理解的东西?

编辑:好的,简要概述了我链接的文章所解决的原因,以防止答案中的重复(如比尔蜥蜴所建议的).(如果我在措辞方面犯了错误,请告诉我,我开始使用Python,所以我可能完全不了解所有概念.而且免责声明 - 这些将非常简短,所以如果你不明白它在检查链接时会得到什么.)

  • Java中的静态方法不能转换为Python类方法
  • Java中的switch语句转换为Python中的哈希表
  • 不要使用XML
  • 吸气剂和制定者是邪恶的(嘿,我只是引用:))
  • 代码重复通常是Java中必不可少的恶魔(例如方法重载),但在Python中则不然

(如果你觉得这个问题很有意思,那么请查看链接.:)非常好.)

python java

62
推荐指数
6
解决办法
1万
查看次数

仍然对Python中可变的默认参数值"gotcha"感到困惑

我理解一个人不应该在Python中使用可变的默认参数值(有一些例外),因为这个值只在定义函数时被评估和存储一次,而不是每次稍后调用该函数.

我对此的理解是这样的(使用下面的例子;请原谅我不精确的语言,因为我只是Python编程的初学者,因为这个而被困在我教科书的功能章节中):

def f(x = [1, 2, 3]):
    x.append(4)
    print(x)

f()
f()
Run Code Online (Sandbox Code Playgroud)

1)定义函数f,x(f中的局部变量)采用默认变量[1,2,3](甚至在调用函数之前)

2)当调用f()时,x仍然是[1,2,3],因为没有传递给它的参数,并且x继续具有其默认值

3)使用append修改x,变为[1,2,3,4],并按原样打印

然而,这是我的困惑所在.我假设:

4)当f结束时,x被破坏(在堆栈中或你称之为的任何东西)并且不再与列表对象[1,2,3,4]**相关联**

5)回收列表对象[1,2,3,4],因为没有变量引用它了

因此,

6)当第二次调用f()时,我希望Python输出一个错误,因为x现在不再有与之关联的值.换句话说,当Python被回收/销毁时,Python如何重用上次评估的默认值?

感谢您的所有帮助和解释!

**我从Ned Batchelder的变量名称分配页面得到的这种理解(见下文) Net Batchelder的变量赋值函数

python default function

5
推荐指数
1
解决办法
612
查看次数