【问题标题】:How do I properly pass an argument to a function如何正确地将参数传递给函数
【发布时间】:2016-01-08 02:51:55
【问题描述】:

我来自 C++ 背景,所以这个问题对我来说似乎有点荒谬: 假设我有一个函数:

def scale(data, factor):
    for val in data:
        val *= factor

这不能按预期工作,如果我传递一个列表,它不会改变任何东西,但是

def scale(data, factor):
    for index, val in enumerate(data):
        data[index] *= factor

lst = [val * factor for val in lst] 正常工作。 Python 如何处理参数传递?我如何知道是否传递了实际引用或别名?

【问题讨论】:

    标签: python python-3.x parameter-passing


    【解决方案1】:

    如果你想改变列表,你需要引用元素。此版本使用map(可以使用列表推导式编写)

    def scale(data, factor):
        return map(lambda x : x*factor, data)
    

    lambda 函数是一个anonymous 函数。

    >>> (lambda x : x + 1) (5)
    6
    

    x 在这种情况下代替了变量5 + 1

    所以在这种情况下,我们遍历列表,将函数f(x) -> x * factor 应用于列表的每个元素。原始列表没有发生变化,而是返回一个新版本。

    【讨论】:

    • 大声笑,为更高级别的代码竖起大拇指,希望他是亲功能的。
    • 这是一个高级的,我没有读过Python中的lamda,但是谢谢先生
    【解决方案2】:

    在python中,基本数据类型是按值传递的——例如intstrbool等都是按值传递的

    classesenumlistdict 等派生数据类型通过引用传递。

    在您的示例中,问题在于您如何使用 for 循环 - 而不是函数参数。如果你这样做:

    for val in lst:
        val += 1
    

    lst 中的值不会更新,因为vallst[0]lst[1] 等不一样,如果val 是基本数据类型。所以,即使在这里,val 也是按值复制的。

    其次,在您的示例中,enumerate:
    但是当您遍历 enumerated 列表时,您使用的是 data[index] - 它会修改实际列表中的元素。

    最后,在您使用生成器的示例中:

    lst = [val * factor for val in lst] - 这里生成器循环遍历每个元素并创建一个新列表,该列表再次存储在lst 中。这类似于a = a + 2,但扩展到列表。

    【讨论】:

    • 你能说得更具体点吗?你能详细说明第一个功能吗?如果列表是通过引用传递的,那么为什么val *= factor 对实际列表没有影响?
    • @GiaPhatHa 我添加了更多信息 :)
    • 这是因为for 循环创建了一个生成器,并且每次循环遍历列表时都会创建每个元素的精确副本?
    • @GiaPhatHa 可以认为 for 循环只是在每个循环的开头执行 val = lst[i++]。在 C 中,这将复制项目的基本数据类型的值,如果数据类型是派生的,则将复制指针。 Python 也是如此
    • Passed-by-value 和passed-by-reference 在这里并不是特别有用的概念。真正的问题是赋值(对局部变量名)与变异(调用改变可变对象的方法)之间的区别。请参阅此处的答案以进行更多讨论:stackoverflow.com/questions/575196/…
    【解决方案3】:

    这种行为之所以如此,是因为基本数据类型是按值传递的,而派生数据类型(如列表)是通过引用传递的,请考虑这一点

    >>> x = 24
    
    >>> x + 1
    25
    
    >>> x
    24
    

    但另一方面是一个列表

    >>> y = [1, 2, 3, 4]
    
    >>> y.remove(2)
    
    >>> y
    [1,3,4]
    

    因此,在对基本数据类型执行操作时,您应该始终小心地重新分配值,并且还要小​​心通过引用传递的数据类型,因为您可能会在不知情的情况下意外修改变量

    【讨论】:

      猜你喜欢
      • 2016-01-08
      • 2019-11-05
      • 1970-01-01
      • 1970-01-01
      • 2021-06-29
      • 2014-04-02
      • 2021-07-12
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多