如何在不分配的情况下更改函数内的用户定义对象

时间:2018-03-03 07:20:35

标签: python

例如,我有一个带有链接列表类的类

class Link:

    empty = ()

    def __init__(self, first, rest=empty):
        assert rest is Link.empty or isinstance(rest, Link)
        self.first = first
        self.rest = rest

    def __repr__(self):
        if self.rest is Link.empty:
            return 'Link({})'.format(self.first)
        else:
            return 'Link({}, {})'.format(self.first, repr(self.rest))

    def __str__(self):
        """Returns a human-readable string representation of the Link

        >>> s = Link(1, Link(2, Link(3, Link(4))))
        >>> str(s)
        '<1 2 3 4>'
        >>> str(Link(1))
        '<1>'
        >>> str(Link.empty)  # empty tuple
        '()'
        """
        string = '<'
        while self.rest is not Link.empty:
            string += str(self.first) + ' '
            self = self.rest
        return string + str(self.first) + '>'

是否可以获取一个链接列表对象并将其输入到一个函数中,该函数将在不指定

的情况下对其进行更改
def func(lst):

    lst=lst.rest

而不是

def func2(lst):

    return lis.rest

所以我可以做func1(lst)而且它会改变而不是lst = func2(lst)

2 个答案:

答案 0 :(得分:0)

因为对象在Python中是可变的(默认情况下),所以您可以修改对象但不会更改外部作用域中的引用。您可以使用id函数对此进行测试:

class A:
    pass

def func1(a):
    print('From func1 before assignment ', id(a))
    a = A()
    print('From func1 after assignment ', id(a))

a = A()
print('From global scope before function ', id(a))
func1(a)
print('From global scope after function ', id(a))

输出

From global scope before function  4646262768
From func1 before assignment  4646262768
From func1 after assignment  4646263888
From global scope after function  4646262768

所以在func1中,我们更改了变量a所引用的内容,但由于它是局部变量,因此它不会更改函数范围之外的a引用。 / p>

答案 1 :(得分:0)

如果您想要在不必重新创建该对象的情况下尝试更改函数内对象的属性,则可以:

def change_link(lnk):
    lnk.rest = Link(10)

如果您不想使用赋值运算符,可以使用setattr

def change_link(lnk):
    setattr(lnk, 'rest', Link(10))

setattr在设置属性后不会返回任何内容,甚至不会返回对象。这样做

def change_link(lnk):
    return setattr(lnk, 'rest', Link(10))

会返回None

现在,如果您真正尝试做的是链接几个依次修改Link对象的函数

modify_list(add_item(pop_first(lnk)))

然后你需要 修改并返回 来自函数的对象:

>>> def insert_2nd_link(lnk):
...     lnk.rest = Link(10, lnk.rest)  # adds a new 2nd item
...     return lnk                     # return the object
...
>>> def multiply_first_by_50(lnk):
...     lnk.first *= lnk.first * 50    # modifies 1st item
...     return lnk                     # return the object
...
>>> s = Link(1, Link(2, Link(3, Link(4))))
>>> s      # original s
Link(1, Link(2, Link(3, Link(4))))
>>> new_s = multiply_first_by_50(insert_2nd_link(s))
>>> new_s  # is it actually new? No
Link(50, Link(10, Link(2, Link(3, Link(4)))))
>>> s      # old s
Link(50, Link(10, Link(2, Link(3, Link(4)))))
>>> id(s) == id(new_s)
True
>>>

请注意,在您的功能链之外,您不需要分配返回值,因为它发生了&#34;就地&#34;:

>>> s = Link(1, Link(2, Link(3, Link(4))))
>>> s
Link(1, Link(2, Link(3, Link(4))))
>>> multiply_first_by_50(insert_2nd_link(s))
Link(50, Link(10, Link(2, Link(3, Link(4)))))
>>> s
Link(50, Link(10, Link(2, Link(3, Link(4)))))
>>>
相关问题