function parameter scope python 2.5.2

Rafe rafesacks at gmail.com
Thu Nov 20 22:56:02 EST 2008


On Nov 21, 6:31 am, J Kenneth King <ja... at agentultra.com> wrote:
> I recently encountered some interesting behaviour that looks like a bug
> to me, but I can't find the appropriate reference to any specifications
> to clarify whether it is a bug.
>
> Here's the example code to demonstrate the issue:
>
> class SomeObject(object):
>
>     def __init__(self):
>         self.words = ['one', 'two', 'three', 'four', 'five']
>
>     def main(self):
>         recursive_func(self.words)
>         print self.words
>
> def recursive_func(words):
>     if len(words) > 0:
>         word = words.pop()
>         print "Popped: %s" % word
>         recursive_func(words)
>     else:
>         print "Done"
>
> if __name__ == '__main__':
>     weird_obj = SomeObject()
>     weird_obj.main()
>
> The output is:
>
> Popped: five
> Popped: four
> Popped: three
> Popped: two
> Popped: one
> Done
> []
>
> Of course I expected that recursive_func() would receive a copy of
> weird_obj.words but it appears to happily modify the object.
>
> Of course a work around is to explicitly create a copy of the object
> property befor passing it to recursive_func, but if it's used more than
> once inside various parts of the class that could get messy.
>
> Any thoughts? Am I crazy and this is supposed to be the way python works?

You are passing a mutable object. So it can be changed. If you want a
copy, use slice:
>>> L = [1, 2, 3, 4, 5]
>>> copy = L[:]
>>> L.pop()
5
>>> L
[1, 2, 3, 4]
>>> copy
[1, 2, 3, 4, 5]

...in your code...

    def main(self):
        recursive_func(self.words[:])
        print self.words

...or...

>>> def recursive_func(words):
>>>     words = words[:]
>>>     if len(words) > 0:
>>>         word = words.pop()
>>>         print "Popped: %s" % word
>>>         recursive_func(words)
>>>     else:
>>>         print "Done"
>>>
>>> words = ["one", "two", "three"]
>>> recursive_func(words)
Popped: three
Popped: two
Popped: one
Done
>>> words
['one', 'two', 'three']

Though I haven't been doing this long enough to know if that last
example has any drawbacks.

If we knew more about what you are trying to do, perhaps an
alternative would be even better.

- Rafe



More information about the Python-list mailing list