default argument in method

Discussion in 'Python' started by ernest, Dec 12, 2010.

  1. ernest

    ernest Guest

    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
     
    ernest, Dec 12, 2010
    #1
    1. Advertising

  2. ernest

    Chris Rebert Guest

    On Sun, Dec 12, 2010 at 3:35 AM, ernest <> wrote:
    > 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
    --
    http://blog.rebertia.com
     
    Chris Rebert, Dec 12, 2010
    #2
    1. Advertising

  3. ernest wrote:
    > 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
     
    Jean-Michel Pichavant, Dec 13, 2010
    #3
  4. ernest

    Steve Holden Guest

    On 12/13/2010 12:14 PM, Godson Gera wrote:
    >
    >
    > On Sun, Dec 12, 2010 at 5:05 PM, ernest <
    > <mailto:>> wrote:
    >
    > 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
    --
    Steve Holden +1 571 484 6266 +1 800 494 3119
    PyCon 2011 Atlanta March 9-17 http://us.pycon.org/
    See Python Video! http://python.mirocommunity.org/
    Holden Web LLC http://www.holdenweb.com/
     
    Steve Holden, Dec 13, 2010
    #4
  5. On Monday 13 December 2010, 18:14:27 Godson Gera wrote:
    > On Sun, Dec 12, 2010 at 5:05 PM, ernest <> wrote:
    > > 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.


    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
     
    Hans-Peter Jansen, Dec 15, 2010
    #5
  6. On Wed, 15 Dec 2010 21:10:05 +0100, Hans-Peter Jansen wrote:

    > 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/



    --
    Steven
     
    Steven D'Aprano, Dec 15, 2010
    #6
  7. On Thursday 16 December 2010, 00:56:31 Steven D'Aprano wrote:
    > On Wed, 15 Dec 2010 21:10:05 +0100, Hans-Peter Jansen wrote:
    > > 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/


    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
     
    Hans-Peter Jansen, Dec 16, 2010
    #7
  8. ernest

    DevPlayer Guest

    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
     
    DevPlayer, Dec 30, 2010
    #8
  9. On Thu, 30 Dec 2010 11:26:50 -0800, DevPlayer wrote:

    > 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.


    >>> class C(object):

    .... 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.



    --
    Steven
     
    Steven D'Aprano, Dec 30, 2010
    #9
  10. ernest

    DevPlayer Guest

    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
     
    DevPlayer, Jan 1, 2011
    #10
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. =?ISO-8859-1?Q?Christian_M=F6rck?=

    Problem posting a method as an argument to an method..

    =?ISO-8859-1?Q?Christian_M=F6rck?=, Nov 20, 2003, in forum: C++
    Replies:
    4
    Views:
    314
    Christian M?rck
    Nov 21, 2003
  2. Bhushit Joshipura

    defaulting argument to previous argument

    Bhushit Joshipura, Dec 29, 2003, in forum: C++
    Replies:
    5
    Views:
    428
  3. mike
    Replies:
    5
    Views:
    350
    Ben Pope
    Feb 22, 2006
  4. Pedro Côrte-Real
    Replies:
    11
    Views:
    167
    Patrick Ritchie
    Jul 25, 2006
  5. Jennie
    Replies:
    24
    Views:
    383
    Steven D'Aprano
    Nov 12, 2012
Loading...

Share This Page