我知道Python中的mutuable和immutable参数,这是哪个,但这是一个奇怪的问题,我遇到了可变参数。简化版如下:
def fun1a(tmp):
tmp.append(3)
tmp.append(2)
tmp.append(1)
return True
def fun1(a):
b = fun1a(a)
print a #prints [3,2,1]
return b
def fun2a():
tmp = []
tmp.append(3)
tmp.append(2)
tmp.append(1)
return [True, tmp]
def fun2(a):
[b, a] = fun2a()
print a #prints [3,2,1]
return b
def main():
a=[]
if fun1(a):
print a #prints [3,2,1]
if fun2(b):
print b #prints garbage, e.g. (0,1)
正如您所看到的,唯一的区别是fun2指向传入的参数以引用在fun2a中创建的列表,而fun1只是附加到main中创建的列表。最后,fun1返回正确的结果,而fun2返回随机垃圾而不是我期望的结果。这有什么问题?
由于
答案 0 :(得分:3)
这不是作为范围之一的可变/不可变问题。
“b”仅存在于fun1和fun2主体中。它不存在于主要或全球范围内(至少是故意的)
- 编辑 -
>>> def fun1(b):
... b = b + 1
... return b
...
>>> def fun2(a):
... b = 1
... return b
...
>>> fun1(5)
6
>>> fun2(b)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'b' is not defined
(来自我在终端的翻译)
我猜你的'b'已在其他地方初始化了。在另一个函数中发生的事情对此没有影响。
这是我运行您的确切代码:
>>> main()
[3, 2, 1]
[3, 2, 1]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 5, in main
NameError: global name 'b' is not defined
>>> b = 'whatever'
>>> main()
[3, 2, 1]
[3, 2, 1]
[3, 2, 1]
whatever
答案 1 :(得分:1)
正如其他人所指出,b
功能中没有名称“main()
”。
断言代码行为方式的更好方法是对其进行单元测试。单元测试在Python中非常容易,并且很容易进入。几年前,当我第一次开始编写Python时,我配对的人坚持要测试一切。从那天起,我继续并且从未必须使用Python调试器!我离题了......
考虑:
import unittest
class Test(unittest.TestCase):
def test_fun1a_populates_tmp(self):
some_list = []
fun1a(tmp=some_list)
self.assertEquals([3, 2, 1], some_list)
def test_fun1a_returns_true(self):
some_list = []
ret = fun1a(tmp=some_list)
self.assertTrue(ret)
def test_fun1_populates_a(self):
some_list = []
fun1(a=some_list)
self.assertEquals([3, 2, 1], some_list)
def test_fun1_returns_true(self):
some_list = []
ret = fun1(a=some_list)
self.assertTrue(ret)
def test_fun2a_populates_returned_list(self):
ret = fun2a()
self.assertEquals([True, [3, 2, 1]], ret)
def test_fun2_returns_true(self):
some_list = []
ret = fun2(some_list)
self.assertTrue(ret)
def test_fun2_des_not_populate_passed_list(self):
some_list = []
fun2(some_list)
self.assertEqual(0, len(some_list))
if __name__ == '__main__':
unittest.main()
这些单元测试中的每一个都传递并记录了函数的行为方式(除了打印,您可以根据需要添加测试)。它们还为您编辑代码时提供了一个线束,因为如果您破坏了某些内容,它们应该继续通过或开始失败。
我没有经过单元测试main()
,因为它已经明显坏了。
答案 2 :(得分:-1)
问题可能与列表和元组之间的差异有关。在fun2中,不要在a,b周围放括号。 在fun2a中,返回两个对象的元组而不是列表。 Python应该正确编写变量,如果那是你想要解决的问题。 此外,当b从未定义时,您使用参数b调用fun2。当然,fun2的参数从未实际使用过,因为它在读取之前会被重写。
最后,您的代码应如下所示:
def fun1a(tmp):
tmp.append(3)
tmp.append(2)
tmp.append(1)
return True
def fun1(a):
b = fun1a(a)
print a #prints [3,2,1]
return b
def fun2a():
tmp = []
tmp.append(3)
tmp.append(2)
tmp.append(1)
return (True, tmp)
def fun2():
b, a = fun2a()
print a #prints [3,2,1]
return b
def main():
a=[]
if fun1(a):
print a #prints [3,2,1]
if fun2():
print b #prints garbage, e.g. (0,1)
两次都应打印[3,2,1]。