代码之家  ›  专栏  ›  技术社区  ›  wheaties

Python:带有变量参数列表的对象赋值

  •  3
  • wheaties  · 技术社区  · 14 年前

    variable number of arguments 并让它使用 ( *args, **keywords )

    def foo( *args ):
        args[0] = 4
    

    TypeError: object does not support assignment

    def foo( *args ):
        plusOne = [ item+1 for item in args ]
        args = plusOne
    

    这对任何事情都没有影响。如果没有机制,也没有办法,我可以承认失败。

    编辑:

    为了阐明我为什么要走这条路,请考虑以下情况:

    class bar(object):
        def __init__(self,obj):
            self.obj = obj
    
    def foo( input ):
        input.obj = "something else"
    

    如果我通过考试 bar 对象转换为foo,我得到状态的变化。创建一个执行 deepcopy

    3 回复  |  直到 14 年前
        1
  •  4
  •   Mark Byers    14 年前

    否-Python使用 call by object-sharing

    澄清术语:您接收的不是对象的深度副本,而是对象的副本 参考 . 注意:这与 call-by-reference

    为了回答您的问题,您将收到一个参数副本(对象引用)。不能像通过引用传递一样修改对象引用。你可以做一个新的修改副本,如果你想,但从你的例子,这不是你要找的。调用作用域将看不到您的更改。

    变异 你接收的对象,客户端 看看这些变化。

        2
  •  3
  •   SilentGhost    14 年前

    原因是什么

    args[0] = 4
    

    args 一个元组,它是不可变的。因此,您需要先将其转换为可变对象,例如:

    >>> def foo( *args ):
        print(args)
        args = list(args)
        args[0] = 42
        print(args)
    
    
    >>> foo(23)
    (23,)
    [42]
    

    如果你提供更多的信息,就有可能提供更多的解决方案,因为你所做的看起来很奇怪。另外,第二个代码似乎工作得很好。

    例如,以下工作正常,并更改了调用范围变量:

    >>> def spam(*a):
        a[0][0] = 42
    
    
    >>> l = [23, 32]
    >>> spam(l)
    >>> l
    [42, 32]
    

    l 对象。在您的示例中也可以看到同样的情况:

    >>> def foo( *input ):
        input[0].obj = "something else"
    
    
    >>> b = bar('abc')
    >>> foo(b)
    >>> b.obj
    'something else'
    
        3
  •  1
  •   Pär Wieslander    14 年前

    >>> x, y = (10, 17)
    >>> foo(x, y)
    >>> print (x, y)
    (11, 18)
    

    你运气不好,因为马克在回答中说了原因。

    但是,如果要将可变对象传递给函数,则可以更改这些对象并在调用后查看结果 foo :

    def foo(*args):
        for arg in args:
            arg['value'] += 1
    
    >>> d1 = {'value': 1}
    >>> d2 = {'value': 2}
    >>> foo(d1, d2)
    >>> print (d1, d2)
    ({'value': 2}, {'value': 3})