default argument in method

E

ernest

Hi,

I'd like to have a reference to an instance attribute as
default argument in a method. It doesn't work because
"self" is not defined at the time the method signature is
evaluated. For example:

class C(object):
def __init__(self):
self.foo = 5
def m(self, val=self.foo):
return val

Raises NameError because 'self' is not defined.
The obvious solution is put val=None in the signature
and set val to the appropriate value inside the method
(if val is None: ...), but I wonder if there's another way.

Cheers,
Ernest
 
C

Chris Rebert

Hi,

I'd like to have a reference to an instance attribute as
default argument in a method. It doesn't work because
"self" is not defined at the time the method signature is
evaluated. For example:

class C(object):
   def __init__(self):
       self.foo = 5
   def m(self, val=self.foo):
       return val

Raises NameError because 'self' is not defined.
The obvious solution is put val=None in the signature
and set val to the appropriate value inside the method
(if val is None: ...), but I wonder if there's another way.

Nope, not really. There are some more complicated slight variations on
the same theme (e.g. hoisting the idiom into a decorator), but they're
of fairly dubious merit; just use the straightforward idiom you
already outlined.

Cheers,
Chris
 
J

Jean-Michel Pichavant

ernest said:
Hi,

I'd like to have a reference to an instance attribute as
default argument in a method. It doesn't work because
"self" is not defined at the time the method signature is
evaluated. For example:

class C(object):
def __init__(self):
self.foo = 5
def m(self, val=self.foo):
return val

Raises NameError because 'self' is not defined.
The obvious solution is put val=None in the signature
and set val to the appropriate value inside the method
(if val is None: ...), but I wonder if there's another way.

Cheers,
Ernest
your 'val=None' is jus fine.

JM
 
S

Steve Holden

On Sun, Dec 12, 2010 at 5:05 PM, ernest <[email protected]

Hi,

I'd like to have a reference to an instance attribute as
default argument in a method. It doesn't work because
"self" is not defined at the time the method signature is
evaluated. For example:

class C(object):
def __init__(self):
self.foo = 5
def m(self, val=self.foo):
return val

Raises NameError because 'self' is not defined.


You can defined foo outside the __init__ and can access it inside
methods using self.foo

class C(object):
foo=5
def __init__(self):
print self.foo
def m(self,val=foo):
return val

class attributes can be accessed with out self before them in method
signatures. However, becareful if you change the value of foo inside any
method, the method signature will still hold on to old value.
You are, of course, correct. It might be more accurate to say that if
C.foo is rebound this does not change the binding of the val default
value. "Change the value of foo" could be though to include "mutate a
mutable value", but in that case both C.foo and the method's val
parameter would still be bound to the same object.

regards
Steve
 
H

Hans-Peter Jansen

You can defined foo outside the __init__ and can access it inside
methods using self.foo

class C(object):
foo=5
def __init__(self):
print self.foo
def m(self,val=foo):
return val

class attributes can be accessed with out self before them in method
signatures. However, becareful if you change the value of foo inside
any method, the method signature will still hold on to old value.

Since this is a major pitfall, it might be worth mentioning, that
mutable default arguments are generally a bad idea, as the default
arguments are evaluated just once, hence e.g. using an empty list might
contain the items, that were appended in earlier calls of this method..

Code, that _relies_ on such behavior should be yanked instantaneous and
the producer of such code should be punished with coding APL¹ on a
dubeolsik hangul keyboard² for a year at least..

Pete

¹) Not, that APL is a bad language per se, but even one liners tend to
be rather cryptic for usual brains. Let's say it with Dijkstra:
"APL is a mistake, carried out through perfection..."
but given the second constraint, it's going to be a, hmm, challenge.
http://en.wikipedia.org/wiki/APL_(programming_language)
²) http://en.wikipedia.org/wiki/Keyboard_layout#Dubeolsik
 
S

Steven D'Aprano

Since this is a major pitfall, it might be worth mentioning, that
mutable default arguments are generally a bad idea, as the default
arguments are evaluated just once, hence e.g. using an empty list might
contain the items, that were appended in earlier calls of this method..

It's only a pitfall for users who expect that default arguments are re-
created every time you call the function; it's only a bad idea for code
which relies on the default arguments being re-created each time.

If you hold misunderstandings about the behaviour of a language, you'll
have trouble understanding what code does. Default arguments are no
different from any other feature.


Code, that _relies_ on such behavior should be yanked instantaneous and
the producer of such code should be punished with coding APL¹ on a
dubeolsik hangul keyboard² for a year at least..

Python code that relies on default arguments to *not* be re-created on
each function call is no worse than (say) Ruby code that relies on
default arguments *to* be re-created each time.

I don't mean to be elitist (ah, who am I fooling, of course I do), but
when coders of the skill and experience of the Effbot and Guido use
mutable defaults, who are you to say they shouldn't?

http://effbot.org/zone/default-values.htm
http://www.python.org/doc/essays/graphs/
 
H

Hans-Peter Jansen

It's only a pitfall for users who expect that default arguments are
re- created every time you call the function; it's only a bad idea
for code which relies on the default arguments being re-created each
time.

If you hold misunderstandings about the behaviour of a language,
you'll have trouble understanding what code does. Default arguments
are no different from any other feature.


Python code that relies on default arguments to *not* be re-created
on each function call is no worse than (say) Ruby code that relies on
default arguments *to* be re-created each time.

I don't mean to be elitist (ah, who am I fooling, of course I do),
but when coders of the skill and experience of the Effbot and Guido
use mutable defaults, who are you to say they shouldn't?

http://effbot.org/zone/default-values.htm
http://www.python.org/doc/essays/graphs/

Hmm, thanks for the pointers, Steven. I stand corrected, as I won't
argue with taste.. I like the part about the disastrous results
specially.

If such code would be used in any collaborations, I would expect an
explicit comment at least.

Pete
 
D

DevPlayer

There's some_object.some_method.func_defaults and
some_function.func_defaults both are a settable attribute. How to set
the methods func_defaults? You'd have to have code in
_getattribute__(yourmethod) if not __getattr__(yourmethod)

def __getattribute__(self, attr):
if attr == self.my_method:
# something like this, but i'm probably a little off
# you might need to use super or something to prevent
recursive __getattribute__ calls here
self.my_method.func_defaults = self.foo
 
S

Steven D'Aprano

There's some_object.some_method.func_defaults

Not quite -- method objects don't expose the function attributes
directly. You need some_object.some_method.im_func to get the function
object, which then has a func_defaults attribute.

and
some_function.func_defaults both are a settable attribute. How to set
the methods func_defaults?

(1) You shouldn't mess with func_defaults unless you know what you're
doing.

(2) If you do know what you are doing, you probably won't want to mess
with func_defaults.

(3) But if you insist, then you would so the same way you would set any
other object's attribute.

.... def method(self, x=[]):
.... print x
....
C().method() []
function = inst.method.im_func
function.func_defaults ([],)
function.func_defaults = ("spam",)
inst.method()
spam


(4) Seriously, don't do this.

You'd have to have code in
_getattribute__(yourmethod) if not __getattr__(yourmethod)

def __getattribute__(self, attr):
if attr == self.my_method:
# something like this, but i'm probably a little off
# you might need to use super or something to prevent
recursive __getattribute__ calls here
self.my_method.func_defaults = self.foo


*cries*

A much better solution would be:

class MyClass:
def my_method(self, x=None):
if x is None:
x = self.foo
...

Don't write slow, confusing, complex, convoluted, self-modifying code
when you can write fast, simple, straight-forward, obvious code. Unless
you're doing it to win a bet.
 
D

DevPlayer

I agree with you Steven that the OP should avoid __getattribute__ and
the like for many a thing. I also agree with your last statement. I
try to answer the OP's question without much "You shouldn't do this's
and don't do that's". I trust them to make thier own decisions. I'd
say "A much better solution..." is the way I like to say it.

The last solution you offered I find I use more often now as I like to
set my function with default values for which I call set-and-forget
function parms/args where using None is what allows my functions to
know what is changing (or not).
# for example
def logger(parm1, parm2=None):
if not hasattr(myfunc.parm2_default):
if parm2:
myfunc.parm2_default = parm2
else:
myfunc.parm2_default = CONSOLE
if not parm2:
parmTwo = myfunc.parm2_default
else:
parmTwo = parm2

# do something
print(parmTwo)

log = logger(gui_frame, GUI) # an inaccurate example
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,968
Messages
2,570,153
Members
46,699
Latest member
AnneRosen

Latest Threads

Top