相关疑难解决方法(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万
查看次数

什么是memoization以及如何在Python中使用它?

我刚开始使用Python,我不知道什么是memoization以及如何使用它.另外,我可以有一个简化的例子吗?

python memoization

356
推荐指数
9
解决办法
14万
查看次数

"是无"和"==无"之间的区别是什么?

我最近遇到了这种语法,我不知道它的区别.

如果有人能告诉我差异,我将不胜感激.

python jython

289
推荐指数
5
解决办法
14万
查看次数

Python参数绑定器

如何将参数绑定到Python方法以存储一个用于以后调用的nullary仿函数?与C++类似boost::bind.

例如:

def add(x, y):
    return x + y

add_5 = magic_function(add, 5)
assert add_5(3) == 8
Run Code Online (Sandbox Code Playgroud)

python partial-application

60
推荐指数
5
解决办法
2万
查看次数

可变函数参数默认值的良好用途?

在Python中将一个可变对象设置为函数中参数的默认值是一个常见的错误.以下是David Goodger撰写的优秀文章中的一个例子:

>>> def bad_append(new_item, a_list=[]):
        a_list.append(new_item)
        return a_list
>>> print bad_append('one')
['one']
>>> print bad_append('two')
['one', 'two']
Run Code Online (Sandbox Code Playgroud)

之所以出现这种情况的解释是在这里.

现在我的问题:这个语法有一个很好的用例吗?

我的意思是,如果遇到它的每个人都犯了同样的错误,调试它,理解问题,从而试图避免它,这种语法有什么用?

python arguments mutable default-value

59
推荐指数
5
解决办法
7022
查看次数

如何将实例成员的默认参数值传递给方法?

我想使用实例的属性值将默认参数传递给实例方法:

class C:
    def __init__(self, format):
        self.format = format

    def process(self, formatting=self.format):
        print(formatting)
Run Code Online (Sandbox Code Playgroud)

尝试时,我收到以下错误消息:

NameError: name 'self' is not defined
Run Code Online (Sandbox Code Playgroud)

我希望该方法的行为如下:

C("abc").process()       # prints "abc"
C("abc").process("xyz")  # prints "xyz"
Run Code Online (Sandbox Code Playgroud)

这里有什么问题,为什么这不起作用?我怎么能做这个工作?

python instance-variables default-arguments

53
推荐指数
3
解决办法
3万
查看次数

使用self.xxxx作为默认参数 - Python

嘿大家好,我正在努力简化我的一个作业问题并使代码更好一些.我正在使用的是二叉搜索树.现在我在我的Tree()类中有一个函数,它找到所有元素并将它们放入列表中.

tree = Tree()
#insert a bunch of items into tree
Run Code Online (Sandbox Code Playgroud)

然后我使用我的makeList()函数从树中获取所有节点并将它们放在一个列表中.makeList()我打电话给这个功能tree.makeList(tree.root).对我来说,这似乎有点重复.我已经调用了树对象,tree.所以这tree.root只是浪费一点点打字.

现在makeList函数是:

    def makeList(self, aNode):
        if aNode is None:
            return []
        return [aNode.data] + self.makeList(aNode.lChild) + self.makeList(aNode.rChild)
Run Code Online (Sandbox Code Playgroud)

我想让aNode输入一个默认参数,例如aNode = self.root(这不起作用),这样我可以运行这个函数,tree.makeList().

第一个问题是,为什么不起作用?
第二个问题是,有没有办法可以运作?正如你所看到的那样,makeList()函数是递归的,所以我无法在函数的开头定义任何东西,或者我得到一个无限循环.

编辑 以下是所有要求的代码:

class Node(object):
    def __init__(self, data):
        self.data = data
        self.lChild = None
        self.rChild = None

class Tree(object):
    def __init__(self):
        self.root = None

    def __str__(self):
        current = self.root

    def isEmpty(self):
        if …
Run Code Online (Sandbox Code Playgroud)

python tree recursion object

52
推荐指数
2
解决办法
2万
查看次数

使用self.*作为方法的默认值

def save_file(self, outputfilename = self.image_filename): 
    self.file.read(outputfilename)
    ....
Run Code Online (Sandbox Code Playgroud)

NameError: name 'self' is not defined在第一行给出.似乎Python不接受它.如何重写代码以免引发异常?

python

34
推荐指数
3
解决办法
7549
查看次数

为什么"可变的默认参数修复"语法如此丑陋,请问python newbie

现在跟随我的一系列"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)

我相信有人可以提供更好的语法,但我也猜测必须有一个非常好的解释为什么没有这样做.

python mutable names

28
推荐指数
3
解决办法
2303
查看次数

Python中默认参数的范围是什么?

当您使用数组参数在Python中定义函数时,该参数的范围是什么?

这个例子来自Python教程:

def f(a, L=[]):
    L.append(a)
    return L

print f(1)
print f(2)
print f(3)
Run Code Online (Sandbox Code Playgroud)

打印:

[1]
[1, 2]
[1, 2, 3]
Run Code Online (Sandbox Code Playgroud)

我不太确定我是否理解这里发生的事情.这是否意味着数组的范围超出了函数的范围?为什么数组会记住从调用到调用的值?来自其他语言,只有当变量是静态的时候我才会期望这种行为.否则它似乎应该每次重置.实际上,当我尝试以下内容时:

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

我得到了我期望的行为(每次调用都重置了数组).

所以在我看来,我只需要def f(a, L=[]):解释这一行- L变量的范围是什么?

python parameters scope function-calls default-value

25
推荐指数
2
解决办法
3556
查看次数