在Python函数中使用参数

2024-09-30 22:21:00 发布

您现在位置:Python中文网/ 问答频道 /正文

我知道Python中可变参数与不可变参数,这是哪个,但是在可变参数方面我遇到了一个奇怪的问题。简化版本如下:

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返回随机垃圾,而不是我预期的结果。有什么问题吗?在

谢谢


Tags: true列表参数returnifmaindefprints
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”是在别的地方初始化的。在另一个函数中发生的事情对这个没有影响。在

这是我在运行你的密码:

^{pr2}$

这个问题可能与列表和元组之间的差异有关。在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]。在

正如其他人所指出的,在您的main()函数中没有名称b。在

断言代码行为方式的更好方法是对其进行单元测试。单元测试在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(),因为它显然已损坏。在

相关问题 更多 >