By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
444,199 Members | 1,120 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 444,199 IT Pros & Developers. It's quick & easy.

Automatic binding of **kwargs to variables

P: n/a
Hi all,

I have a very long list of parameters coming from a web form to my
method foo(self, **kwargs)

I would like to avoid manually binding the variables to the values
coming through the **kwargs dictionary, just to keep the code cleaner,
I'd like to bind them automatically

I was adviced against doing it by adding stuff to locals such as:

locals()["x"] = 5

since the Python Docs say:

Warning: The contents of this dictionary should not be modified;
changes may not affect the values of local variables used by the
interpreter.

Is there a way to do this? Maybe object.__setattr__() or something that
involves metaclasses?

As I might go touching something that I shouldn't (like locals()) I'd
like some advice from you before deciding which way to go.
Thanks,
Lorenzo

Oct 28 '05 #1
Share this Question
Share on Google+
26 Replies


P: n/a
"lb********@gmail.com" <lb********@gmail.com> writes:
I have a very long list of parameters coming from a web form to my
method foo(self, **kwargs)

I would like to avoid manually binding the variables to the values
coming through the **kwargs dictionary, just to keep the code cleaner,
I'd like to bind them automatically

I was adviced against doing it by adding stuff to locals such as:

locals()["x"] = 5

since the Python Docs say:

Warning: The contents of this dictionary should not be modified;
changes may not affect the values of local variables used by the
interpreter.

Is there a way to do this? Maybe object.__setattr__() or something that
involves metaclasses?
..__setattr__() will modify the instance variables, not the local
variables.
As I might go touching something that I shouldn't (like locals()) I'd
like some advice from you before deciding which way to go.


Reference the keyword arguments through the dictionary. Looking up
values by name is what dictionaries are for. Trying to move the names
from a dictionary into the local (or global) namespace is usually a
bad idea. If you don't know all the names in advance, you risk
collisions between the items in the dictionary and the legitimate
inhabitants of the namespace. If you do know all the names in advance,
you need to make sure the keys in the dictionary are in the list of
values you expect, so you need an explicit list.

That said, the most straightforward way to do this that I can think of
is with exec:

for name, value in kwargs.items():
if name in ('a', 'list', 'of', 'valid', 'keywords'):
exec "%s = %s" % (name, value)
else:
raise ValueError, "Unrecognized keyword " + name

Others will probably tell you that you really shouldn't be using exec.

<mike
--
Mike Meyer <mw*@mired.org> http://www.mired.org/home/mwm/
Independent WWW/Perforce/FreeBSD/Unix consultant, email for more information.
Oct 29 '05 #2

P: n/a
lb********@gmail.com wrote:
I have a very long list of parameters coming from a web form to my
method foo(self, **kwargs)

I would like to avoid manually binding the variables to the values
coming through the **kwargs dictionary, just to keep the code cleaner,
I'd like to bind them automatically


Why don't you just change the method signature to foo(self, x, y, z,
whatever, **kwargs)?

Peter

Oct 29 '05 #3

P: n/a
Peter Otten wrote:
lb********@gmail.com wrote:

I have a very long list of parameters coming from a web form to my
method foo(self, **kwargs)

I would like to avoid manually binding the variables to the values
coming through the **kwargs dictionary, just to keep the code cleaner,
I'd like to bind them automatically

Why don't you just change the method signature to foo(self, x, y, z,
whatever, **kwargs)?

Peter

Probably because values are then required for those arguments. Plus it's
a lot of work to specify "a very long list", and the list will also need
maintaining.

I must, however, agree with Mike's advice: it's unwise to try and
pollute a function's namespace with arbitrary variables. Some kind of
bunch-like object would seem to be the most satisfactory way to go.

regards
Steve
--
Steve Holden +44 150 684 7255 +1 800 494 3119
Holden Web LLC www.holdenweb.com
PyCon TX 2006 www.python.org/pycon/

Oct 29 '05 #4

P: n/a
Mike Meyer wrote:
[snip]
for name, value in kwargs.items():
if name in ('a', 'list', 'of', 'valid', 'keywords'):
exec "%s = %s" % (name, value)
else:
raise ValueError, "Unrecognized keyword " + name

Others will probably tell you that you really shouldn't be using exec.


What about using setattr?

for name, value in kwargs.items():
if name in ('a', 'list', 'of', 'valid', 'keywords'):
setattr(self, name, value)
else:
raise ValueError, "Unrecognized keyword " + name

I'd probably turn the list of valid keywords into another dictionary to
make it easy to specify default values for all the parameters as well.

Cheers,
Chris

Oct 29 '05 #5

P: n/a
Steve Holden wrote:
Why don't you just change the method signature to foo(self, x, y, z,
whatever, **kwargs)?
Probably because values are then required for those arguments. Plus it's
a lot of work to specify "a very long list", and the list will also need
maintaining.
Note that I kept the **kwargs argument. He would only have to specify
variables that are actually used in foo(), and these need maintaining
anyway. As to optional arguments, you can provide default values. Checking
for those is easier and safer than using local variables that may not be
bound or accidentally refer to a global.

# e. g.
missing = object() # if None is a valid state of whatever
def foo(self, whatever=missing, **kwargs):
if whatever is not missing:
# use whatever
I must, however, agree with Mike's advice: it's unwise to try and
pollute a function's namespace with arbitrary variables. Some kind of
bunch-like object would seem to be the most satisfactory way to go.


Using a bunch doesn't remove the necessity of an existence-test either (for
optional attributes).

Peter
Oct 29 '05 #6

P: n/a
Peter Otten wrote:
Steve Holden wrote:

Why don't you just change the method signature to foo(self, x, y, z,
whatever, **kwargs)?

Probably because values are then required for those arguments. Plus it's
a lot of work to specify "a very long list", and the list will also need
maintaining.

Note that I kept the **kwargs argument. He would only have to specify
variables that are actually used in foo(), and these need maintaining
anyway. As to optional arguments, you can provide default values. Checking
for those is easier and safer than using local variables that may not be
bound or accidentally refer to a global.

Now I think I understand your intention better. Further discussion would
be flogging horse already dead for several days.
# e. g.
missing = object() # if None is a valid state of whatever
def foo(self, whatever=missing, **kwargs):
if whatever is not missing:
# use whatever

I must, however, agree with Mike's advice: it's unwise to try and
pollute a function's namespace with arbitrary variables. Some kind of
bunch-like object would seem to be the most satisfactory way to go.

Using a bunch doesn't remove the necessity of an existence-test either (for
optional attributes).

No more it does.

regards
Steve
--
Steve Holden +44 150 684 7255 +1 800 494 3119
Holden Web LLC www.holdenweb.com
PyCon TX 2006 www.python.org/pycon/

Oct 29 '05 #7

P: n/a
"ch*********@gmail.com" <ch*********@gmail.com> writes:
Mike Meyer wrote:
[snip]
for name, value in kwargs.items():
if name in ('a', 'list', 'of', 'valid', 'keywords'):
exec "%s = %s" % (name, value)
else:
raise ValueError, "Unrecognized keyword " + name

Others will probably tell you that you really shouldn't be using exec.
What about using setattr?

for name, value in kwargs.items():
if name in ('a', 'list', 'of', 'valid', 'keywords'):
setattr(self, name, value)
else:
raise ValueError, "Unrecognized keyword " + name


You clipped my description of what's wrong with setattr: it doesn't
bind the names in the local namespace, it binds them to an
object. This may be acceptable, but wasn't what the OP asked for.
I'd probably turn the list of valid keywords into another dictionary to
make it easy to specify default values for all the parameters as well.


If you're going to do that, why not just specify them explicitly in
the function definition instead of using **kwargs? That takes care of
everything - binding, checking, and providing a default value - in one
swoop.

<mike
--
Mike Meyer <mw*@mired.org> http://www.mired.org/home/mwm/
Independent WWW/Perforce/FreeBSD/Unix consultant, email for more information.
Oct 29 '05 #8

P: n/a
Thanks everybody for their reply. I'll see what solution is best for my
case and maybe follow up here.

Thanks again,
Lorenzo

Oct 30 '05 #9

P: n/a
What do u think of the following? I could keep the form schema as
expected_form1_kwargs in a separate module and import * and wrap the
kwargs check done in the for loop in a function for use in the whole
site.

The elif part is useful for checkboxes which are not passed by the
browser if they're not checked.

def foo(self, **kwargs)
expected_form1_kwargs = [arg1, arg2]

for name in kwargs:
if name not in expected_form1_kwargs:
raise ValueError, "Unrecognized keyword" + name
elif name in expected_form1_kwargs not in kwargs.keys():
kwargs.update(name=None)
Thanks again everybody,
Lorenzo

Oct 30 '05 #10

P: n/a
lb********@gmail.com wrote:
if name not in expected_form1_kwargs:
raise ValueError, "Unrecognized keyword" + name
elif name in expected_form1_kwargs not in kwargs.keys():
kwargs.update(name=None)


Do you mean this instead?

elif name in expected_form1_kwargs and name not in kwargs:

What you wrote doesn't do what you think it does... it actually tests
for whether True or False is a key in kwargs, depending on whether "name
in expected_form1_kwargs" returns True or False.

-Peter
Oct 30 '05 #11

P: n/a
FormEncode.

lb********@gmail.com wrote:
What do u think of the following? I could keep the form schema as
expected_form1_kwargs in a separate module and import * and wrap the
kwargs check done in the for loop in a function for use in the whole
site.

The elif part is useful for checkboxes which are not passed by the
browser if they're not checked.

def foo(self, **kwargs)
expected_form1_kwargs = [arg1, arg2]

for name in kwargs:
if name not in expected_form1_kwargs:
raise ValueError, "Unrecognized keyword" + name
elif name in expected_form1_kwargs not in kwargs.keys():
kwargs.update(name=None)
Thanks again everybody,
Lorenzo


Oct 30 '05 #12

P: n/a

Peter Hansen wrote:
Do you mean this instead?

elif name in expected_form1_kwargs and name not in kwargs:

What you wrote doesn't do what you think it does... it actually tests
for whether True or False is a key in kwargs, depending on whether "name
in expected_form1_kwargs" returns True or False.


Hi Peter,

you're right... the code needed also other fixes and I didn't find a
way to do it other than this:

def foo(**kwargs):
expected_form1_kwargs = ["arg1", "arg2"]

for name in expected_form1_kwargs:
if name not in kwargs:
kwargs[name]=None

for name in kwargs:
if name in kwargs and name not in expected_form1_kwargs:
raise ValueError, "Unrecognized keyword: " + name

print kwargs
if __name__ == "__main__":
foo(arg1=8)
Lorenzo

Oct 30 '05 #13

P: n/a
lb********@gmail.com <lb********@gmail.com> wrote:
...
def foo(**kwargs):
expected_form1_kwargs = ["arg1", "arg2"]

for name in expected_form1_kwargs:
if name not in kwargs:
kwargs[name]=None

for name in kwargs:
if name in kwargs and name not in expected_form1_kwargs:
raise ValueError, "Unrecognized keyword: " + name

print kwargs


I find this style of coding repulsive when compared to:

def foo(arg1=None, arg2=None):
print dict(arg1=arg1, arg2=arg2)

I don't understand what added value all of those extra, contorted lines
are supposed to bring to the party.
Alex
Oct 30 '05 #14

P: n/a
Don't know about this particular case but sometimes, I don't want to
have a default argument value. That is, argument not there is different
from argument = None. Though in general, I prefer the None as special
meaning coding style. But even python's builtin function prefers to
distinguish between "not there" and None.

Alex Martelli wrote:
lb********@gmail.com <lb********@gmail.com> wrote:
...
def foo(**kwargs):
expected_form1_kwargs = ["arg1", "arg2"]

for name in expected_form1_kwargs:
if name not in kwargs:
kwargs[name]=None

for name in kwargs:
if name in kwargs and name not in expected_form1_kwargs:
raise ValueError, "Unrecognized keyword: " + name

print kwargs


I find this style of coding repulsive when compared to:

def foo(arg1=None, arg2=None):
print dict(arg1=arg1, arg2=arg2)

I don't understand what added value all of those extra, contorted lines
are supposed to bring to the party.
Alex


Oct 30 '05 #15

P: n/a
Alex Martelli wrote:
I find this style of coding repulsive when compared to:

def foo(arg1=None, arg2=None):
print dict(arg1=arg1, arg2=arg2)

I don't understand what added value all of those extra, contorted lines
are supposed to bring to the party.


Hi Alex,

the thing is that I have about 30 parameters to pass to a method and I
wanted to have a cleaner way to deal with it than just declaring them
all as arguments: hence **kwargs and all that mess ;-)

I was thinking to declare the a list of valid and expected parameters
in a module and then import * and run my checks against it. Since this
stuff is being posted by a web form I also need to deal with checkbox
not being posted if not checked which lead me to:

for name in expected_form1_kwargs:
if name not in kwargs:
kwargs[name]=None

Lorenzo

Oct 30 '05 #16

P: n/a
"lb********@gmail.com" <lb********@gmail.com> writes:
Peter Hansen wrote:
Do you mean this instead?

elif name in expected_form1_kwargs and name not in kwargs:

What you wrote doesn't do what you think it does... it actually tests
for whether True or False is a key in kwargs, depending on whether "name
in expected_form1_kwargs" returns True or False.


Hi Peter,

you're right... the code needed also other fixes and I didn't find a
way to do it other than this:

def foo(**kwargs):
expected_form1_kwargs = ["arg1", "arg2"]

for name in expected_form1_kwargs:
if name not in kwargs:
kwargs[name]=None

for name in kwargs:
if name in kwargs and name not in expected_form1_kwargs:
raise ValueError, "Unrecognized keyword: " + name

print kwargs

You're contorting things horribly, and - not unexpected when you do
that kind of thing - running code that has no effect. To wit, the
second loop goes through every key in kwargs. The first thing it does
is test to see if the key you just selected from kwargs is in
kwargs. This test is always true.

IIUC, the reason you're going through these contortions is that the
argument list is long and repeated in a number of different places. So
you're going to declare expected_form1_kwargs in one place and use it
repeatedly. Presumably, you can also bundle the set/check code up in a
function that you pass kwargs to as well.

Have you thought about generating the more readable form from code you
write? One of the most powerful tools available to programmers is code
that writes code. This seems to be the perfect case for such a
tool. You could, for instance, run your code through m4 to generate
the Python that actually gets run. A trivial script that looks for
"^def " and then replaced **kwargs with your list could serve as a
custom preprocessor. To be particulary perverse, you could try using
a Cheetah template to generate your code - I've not tried generating
Python with it, but it creates Makefiles quite nicely.

<mike
--
Mike Meyer <mw*@mired.org> http://www.mired.org/home/mwm/
Independent WWW/Perforce/FreeBSD/Unix consultant, email for more information.
Oct 30 '05 #17

P: n/a
On Sat, 29 Oct 2005 11:01:02 -0700, ch*********@gmail.com wrote:
Mike Meyer wrote:
[snip]
for name, value in kwargs.items():
if name in ('a', 'list', 'of', 'valid', 'keywords'):
exec "%s = %s" % (name, value)
else:
raise ValueError, "Unrecognized keyword " + name

Others will probably tell you that you really shouldn't be using exec.


What about using setattr?

for name, value in kwargs.items():
if name in ('a', 'list', 'of', 'valid', 'keywords'):
setattr(self, name, value)
else:
raise ValueError, "Unrecognized keyword " + name

I'd probably turn the list of valid keywords into another dictionary to
make it easy to specify default values for all the parameters as well.


Here's a thought... instead of passing a class instance which you access
with obj.name, why not pass a dict which you access with dict[name]?

I don't understand the purpose of doing all this extra work to stuff
values stored in a dictionary into instance attributes, when it is so easy
to just use the dictionary. What advantage do you get?

--
Steven.

Oct 30 '05 #18

P: n/a
On Fri, 28 Oct 2005 15:49:12 -0700, lb********@gmail.com wrote:
I have a very long list of parameters coming from a web form to my
method foo(self, **kwargs)

I would like to avoid manually binding the variables to the values
coming through the **kwargs dictionary,
That's easy: Just Don't Do It.

Instead of some horribly contorted code converting key,item in kwargs into
self.key = item, just do the simple, obvious thing:

self.kwargs = kwargs

and then access the values with self.kwargs[key].
just to keep the code cleaner,
I'd like to bind them automatically


If you are worried about excessive use of quotation marks, you can always
define some constants to use:

NAME = 'name'
EMAIL = 'email'
NUM = 'num'

if self.kwargs[NAME]is None:
self.kwargs[NAME] = "Anonymous"
The benefit of this is that when you change your web form to use "number"
instead of "num", you only have to change your code in one place.
--
Steven

Oct 30 '05 #19

P: n/a
bo****@gmail.com <bo****@gmail.com> wrote:
Don't know about this particular case but sometimes, I don't want to
have a default argument value. That is, argument not there is different
from argument = None. Though in general, I prefer the None as special
meaning coding style. But even python's builtin function prefers to
distinguish between "not there" and None.


the canonical idiom when you need such distinction is:

_not_there = object()
def foo(bar=_not_there, baz=_not_there, bap=_not_there):
if bar is _not_there: ...

Other unique objects can be substituted for the 'sentinel', but I prefer
an empty "object()" because it has no other possible meaning except that
of a distinguishable, identifiable sentinel. IOW, you could set the
_not_there name to [] or {} or many other things, but that could be
slightly confusing for the reader (since the other things might have
other meanings and purposes) while 'object()' shouldn't be.

At any rate, the complicated code I was commenting on did treat absent
expected arguments exactly the same way as arguments passed as None,
which is also a frequent use case, so this further level of refinement
was apparently not warranted ("use only as much power as you need" is a
programming principle that tends to promote simplicity, and therefore,
in many cases, is well worth adhering to).
Alex
Oct 30 '05 #20

P: n/a
lb********@gmail.com <lb********@gmail.com> wrote:
Alex Martelli wrote:
I find this style of coding repulsive when compared to:

def foo(arg1=None, arg2=None):
print dict(arg1=arg1, arg2=arg2)

I don't understand what added value all of those extra, contorted lines
are supposed to bring to the party.
Hi Alex,

the thing is that I have about 30 parameters to pass to a method and I
wanted to have a cleaner way to deal with it than just declaring them
all as arguments: hence **kwargs and all that mess ;-)


Aha, I see -- yes, a nasty case; I understand why you don't want the
boilerplate of 30 'optional named arguments'.

I was thinking to declare the a list of valid and expected parameters
in a module and then import * and run my checks against it. Since this
A list seems inappropriate, because it implies an order you don't care
about; I would suggest a set instead. Also, I don't see why "import *"
would be better than a normal import here -- the latter seems better.
stuff is being posted by a web form I also need to deal with checkbox
not being posted if not checked which lead me to:

for name in expected_form1_kwargs:
if name not in kwargs:
kwargs[name]=None


Set operations appear to be at a more appropriate level of abstraction
for what you're doing, it seems to me. You want to ensure that kwargs,
seen as a set, is a subset of expected_kwargs, and then enrich kwargs
with None for all names that are in expected_kwargs but not yet in
kwargs; the most direct expression of this (assuming you want a detailed
diagnostics of wrongly-passed argument names), it appears to me, is to
keep in expected_args the dictionary mapping each expected arg to its
default value (dict.fromkeys(listofnames), if listofnames is a list of
the expected arguments' names a None the default value for each) and
then check in your method with code such as:

spurious_args = set(kwargs).difference(expected_args)
if spurious_args:
raise TypeError, 'spurious args %s' % spurious_args
kwargs = dict(expected_args, **kwargs)

If you didn't need the list of spurious argument names for diagnostic
purposes, the check might be more simply expressed as

if not set(kwargs).issubset(expected_args): ...

which is more readable (IMHO the difference isn't quite enough to
warrant checking in this way and then computing the spurious_args only
if needed, i.e., in the body of the if statement, but that's a debatable
issue of style).
Operating on sets, and more generally at higher abstraction levels, is
often a preferable Python alternative to "detailed looping" at a level
that's closer to the concrete data structures in your code.
Alex
Oct 30 '05 #21

P: n/a
In article <1h*****************************@yahoo.com>,
Alex Martelli <al*****@yahoo.com> wrote:

the canonical idiom when you need such distinction is:

_not_there = object()
def foo(bar=_not_there, baz=_not_there, bap=_not_there):
if bar is _not_there: ...

Other unique objects can be substituted for the 'sentinel', but I prefer
an empty "object()" because it has no other possible meaning except that
of a distinguishable, identifiable sentinel. IOW, you could set the
_not_there name to [] or {} or many other things, but that could be
slightly confusing for the reader (since the other things might have
other meanings and purposes) while 'object()' shouldn't be.


What's your preferred idiom when you're dealing with storable objects?
--
Aahz (aa**@pythoncraft.com) <*> http://www.pythoncraft.com/

"If you think it's expensive to hire a professional to do the job, wait
until you hire an amateur." --Red Adair
Oct 31 '05 #22

P: n/a
Aahz <aa**@pythoncraft.com> wrote:
In article <1h*****************************@yahoo.com>,
Alex Martelli <al*****@yahoo.com> wrote:

the canonical idiom when you need such distinction is:

_not_there = object()
def foo(bar=_not_there, baz=_not_there, bap=_not_there):
if bar is _not_there: ...

Other unique objects can be substituted for the 'sentinel', but I prefer
an empty "object()" because it has no other possible meaning except that
of a distinguishable, identifiable sentinel. IOW, you could set the
_not_there name to [] or {} or many other things, but that could be
slightly confusing for the reader (since the other things might have
other meanings and purposes) while 'object()' shouldn't be.


What's your preferred idiom when you're dealing with storable objects?


What's a "storable object"? You mean, something that can be pickled, or
passed to the .write method of a file object, or stored in a database,
or what else?
Alex
Nov 1 '05 #23

P: n/a
In article <1h*************************@mail.comcast.net>,
Alex Martelli <al***@mail.comcast.net> wrote:
Aahz <aa**@pythoncraft.com> wrote:
In article <1h*****************************@yahoo.com>,
Alex Martelli <al*****@yahoo.com> wrote:

the canonical idiom when you need such distinction is:

_not_there = object()
def foo(bar=_not_there, baz=_not_there, bap=_not_there):
if bar is _not_there: ...

Other unique objects can be substituted for the 'sentinel', but I prefer
an empty "object()" because it has no other possible meaning except that
of a distinguishable, identifiable sentinel. IOW, you could set the
_not_there name to [] or {} or many other things, but that could be
slightly confusing for the reader (since the other things might have
other meanings and purposes) while 'object()' shouldn't be.


What's your preferred idiom when you're dealing with storable objects?


What's a "storable object"? You mean, something that can be pickled, or
passed to the .write method of a file object, or stored in a database,
or what else?


Pickled and/or stored in a DB.
--
Aahz (aa**@pythoncraft.com) <*> http://www.pythoncraft.com/

"If you think it's expensive to hire a professional to do the job, wait
until you hire an amateur." --Red Adair
Nov 1 '05 #24

P: n/a
Aahz <aa**@pythoncraft.com> wrote:
...
the canonical idiom when you need such distinction is:

_not_there = object() ... What's your preferred idiom when you're dealing with storable objects?


What's a "storable object"? You mean, something that can be pickled, or
passed to the .write method of a file object, or stored in a database,
or what else?


Pickled and/or stored in a DB.


Relational databases have the concept of NULL specifically to indicate
"there is NOTHING here". I love it.

For pickling, object() as a unique "nothing here, NOT EVEN a None"
marker (AKA sentinel) works fine.
Alex
Nov 2 '05 #25

P: n/a
In article <1h**************************@mail.comcast.net>,
Alex Martelli <al***@mail.comcast.net> wrote:
Aahz <aa**@pythoncraft.com> wrote:
Alex:
Aahz:
Alex:
>
>the canonical idiom when you need such distinction is:
>
>_not_there = object()

What's your preferred idiom when you're dealing with storable objects?

What's a "storable object"? You mean, something that can be pickled, or
passed to the .write method of a file object, or stored in a database,
or what else?
Pickled and/or stored in a DB.


Relational databases have the concept of NULL specifically to indicate
"there is NOTHING here". I love it.


Right.
For pickling, object() as a unique "nothing here, NOT EVEN a None"
marker (AKA sentinel) works fine.


How does that work? Maybe I'm missing something obvious.

sentinel = object()
class C:
def __init__(self, foo=sentinel):
self.foo = foo
def process(self):
if self.foo is not sentinel:
....

Now, the way I understand this, when your application restarts and an
instance of C is read from a pickle, your sentinel is going to be a
different instance of object() and process() will no longer work
correctly. Are you suggesting that you need to pickle the sentinel with
the instance? Or is there some other trick I'm missing?
--
Aahz (aa**@pythoncraft.com) <*> http://www.pythoncraft.com/

"If you think it's expensive to hire a professional to do the job, wait
until you hire an amateur." --Red Adair
Nov 8 '05 #26

P: n/a
Aahz <aa**@pythoncraft.com> wrote:
...
For pickling, object() as a unique "nothing here, NOT EVEN a None"
marker (AKA sentinel) works fine.


How does that work? Maybe I'm missing something obvious.

sentinel = object()
class C:
def __init__(self, foo=sentinel):
self.foo = foo
def process(self):
if self.foo is not sentinel:
....

Now, the way I understand this, when your application restarts and an
instance of C is read from a pickle, your sentinel is going to be a
different instance of object() and process() will no longer work
correctly. Are you suggesting that you need to pickle the sentinel with
the instance? Or is there some other trick I'm missing?


Yes, I'd set self.sentinel=sentinel (and test wrt that) -- while in the
abstract it would be better to set sentinel at class level, since
classes are only pickled "by name" that wouldn't work.

If you don't need the absolute ability to pass ANY argument to C(),
there are of course all sorts of workaround to save some small amount of
memory -- any object that's unique and you never need to pass can play
the same role as a sentinel, obviously.
Alex
Nov 9 '05 #27

This discussion thread is closed

Replies have been disabled for this discussion.