简体   繁体   中英

How to modify argument to function cleanly in Python?

I have the following code which I use to modify the node that is passed into the function recursively (the node is wrapped in an array so that the modification is persistent after the function returns):

Is there a better or cleaner way to modify the argument?

`

class node(object):
    def __init__(self, value, next=None):
        self._value = value
        self._next = next

    def __repr__(self):
        return "node({0})".format(self._value)


    @property
    def next(self):
        return self._next



def foo(a, b):
    if b == 0:
        print "setting to next node",
        a[0] = a[0].next
        print a
        return

    print a
    foo(a, b-1)
    print a

n = node(5, node(8))
foo([n], 2)

`

Question was answered in: How do I pass a variable by reference?

Because the parameter your are operating is object. You could use __dict__ to change the whole property of the object. It is equivalent to change every property of the project. You could try the following code:

class node(object):
    def __init__(self, value, next=None):
        self._value = value
        self._next = next

    def __repr__(self):
        return "node({0})".format(self._value)


    @property
    def next(self):
        return self._next



def foo(a):
    print "setting to next node\n",
    a.__dict__ = getattr(a.next, '__dict__', None)
    return

n = node(5, node(8, node(7)))

print n._value, '->' ,n._next._value
foo(n)
print n._value, '->' ,n._next._value

Hope this could help you.

To modify something, that thing has to be mutable. Your node instances are mutable:

n = node(3)
assert n.value == 3
n.value = 5
assert n.value == 5  # it was modified!

Also, your function fails to return any values. In your case it may be a wrong approach. Also, I frankly don't see why you would use number ( 0 , n - 1 ) where the .next value is referenced. These must be node instances, not numbers.

Apparently you're making a linked list implementation, and your foo function tries to remove n-th node by traversing a list. (Please take care to name your functions descriptively; it helps both you and people answering your question.)

That's how I'd do it:

class Node(object):  # class names are usually TitleCase
    def __init__(self, value, next=None):
        self.value = value
        self.next = next  # no properties for simplicity

    def __repr__(self):
        return "node({0})".format(self.value)


def asList(node):  # nice for printing
    if not node:
        return []
    return [node.value] + asList(node.next)


def removeNodeAt(head_node, index):
  """Removes a node from a list. Returns the (new) head node of the list."""
  if index == 0:  # changing head
    return head_node.next
  i = 1  # we have handled the index == 0 above 
  scan_node = head_node
  while i < index and scan_node.next:
    scan_node = scan_node.next
    i += 1
  # here scan_node.next is the node we want removed, or None
  if scan_node.next:
    scan_node.next = scan_node.next.next  # jump over the removed node
  return head_node

It works:

>>> n3 = Node(0, Node(1, Node(2)))
>>> asList(removeNodeAt(n3, 2))
[0, 1]

>>> n3 = Node(0, Node(1, Node(2)))
>>> asList(removeNodeAt(n3, 1))
[0, 2]

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM