Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

function parameter: question about scope

0 views
Skip to first unread message

Uwe Mayer

unread,
Jul 14, 2002, 9:06:57 PM7/14/02
to
hi,

I've got a object method which works similar to the __deepcopy__()
function of the copy/deepcopy protocol. this function takes an optional
argument "memo={}":

def getElements(self, types, memo={}):
'''Returns a list of sub-elements.'''
if memo.has_key(id(self)): return memo[id(self)]
elements = super(Compound, self).getElements(types, memo)
if (types == ()) or (self.__class__ in types): elements.extend
([self])
return elements


This function checks wether self.__class__ is contained in 'types' and
if so, it adds itself to the list 'elements' and returns it.

The problem is, that 'memo' seems to live beyond method invocation - and
I don't know why:
If I call 'getElements( types=() )', the method works fine. The first
call to 'getElements( types=(<someClass>) )' works fine, too. The
parameter 'memo' seems to have remembered <someClass>, because when I
call 'getElements( types=() )' again I get the same result as in the
previous call which is different to the first call.

Calling 'getElements( types=(), memo={} )' works fine.

Why does 'memo' keep exising?

Thanks in advance
Uwe

Emile van Sebille

unread,
Jul 14, 2002, 12:14:08 PM7/14/02
to
Uwe Mayer

> def getElements(self, types, memo={}):
[snip]

> The problem is, that 'memo' seems to live beyond method invocation -
and
> I don't know why:

When you use:

def getElements(self, types, memo={}):

memo will only be created once when the module is initially imported.
All subsequent access to getElements() that don't specifically override
memo share the same originally created copy of memo. You probably want
to do:

def getElements(self, types, memo=None):
if memo == None:
memo = {}

Then each invocation of getElements not passing in memo will get a newly
created memo.

HTH,

--

Emile van Sebille
em...@fenx.com

---------

Alex Martelli

unread,
Jul 14, 2002, 12:40:09 PM7/14/02
to
Uwe Mayer wrote:

> hi,
>
> I've got a object method which works similar to the __deepcopy__()
> function of the copy/deepcopy protocol. this function takes an optional
> argument "memo={}":
>
> def getElements(self, types, memo={}):

...


> Why does 'memo' keep exising?

What "keeps existing" is the DEFAULT value of memo -- it keeps
existing because it's stored among the function's attributes.

That's how default values of arguments behave: constructed once,
when you execute statement def, and thereafter remembered as
long as the function object survives.

This is generally OK when the default value is immutable, and
almost never what you want when it's mutable. Solution: don't
use mutable objects as default values for arguments. E.g., change
your function's start into:

def getElements(self, types, memo=None):
if memo is None: memo = {}
# proceed as before


This is the most idiomatic Python approach.


Alex


0 new messages