How to use a class property to store function variables?

Discussion in 'Python' started by GZ, Apr 28, 2010.

  1. GZ

    GZ Guest

    I want to store a reference to a function into a class property.

    So I am expecting that:

    class A:
    fn = lambda x: x

    fn = A.fn
    fn(1)

    Traceback (most recent call last):
    File "<string>", line 1, in <string>
    TypeError: unbound method <lambda>() must be called with A instance as
    first argument (got int instance instead)


    The problem is that A.fn is treated as a bounded method. I really want
    A.fn to be a variable that stores a reference to a function. Is there
    any way to achieve this?

    Thanks,
    GZ
    GZ, Apr 28, 2010
    #1
    1. Advertising

  2. GZ

    Chris Rebert Guest

    On Tue, Apr 27, 2010 at 4:36 PM, GZ <> wrote:
    > I want to store a reference to a function into a class property.
    >
    > So I am expecting that:
    >
    > class A:
    >     fn = lambda x: x
    >
    > fn = A.fn
    > fn(1)
    >
    > Traceback (most recent call last):
    >  File "<string>", line 1, in <string>
    > TypeError: unbound method <lambda>() must be called with A instance as
    > first argument (got int instance instead)
    >
    >
    > The problem is that A.fn is treated as a bounded method. I really want
    > A.fn to be a variable that stores a reference to a function. Is there
    > any way to achieve this?


    Use the staticmethod() decorator:

    class A(object):
    @staticmethod
    def fn(x):
    return x

    #rest same as before

    Cheers,
    Chris
    --
    http://blog.rebertia.com
    Chris Rebert, Apr 28, 2010
    #2
    1. Advertising

  3. GZ

    Terry Reedy Guest

    On 4/27/2010 7:36 PM, GZ wrote:
    > I want to store a reference to a function into a class property.
    >
    > So I am expecting that:
    >
    > class A:
    > fn = lambda x: x
    >
    > fn = A.fn
    > fn(1)
    >
    > Traceback (most recent call last):
    > File "<string>", line 1, in<string>
    > TypeError: unbound method<lambda>() must be called with A instance as
    > first argument (got int instance instead)
    >
    >
    > The problem is that A.fn is treated as a bounded method. I really want
    > A.fn to be a variable that stores a reference to a function. Is there
    > any way to achieve this?


    Use 3.1, though you will have the same issue when calling it and same
    fix that Chris gave.

    Terry Jan Reedy
    Terry Reedy, Apr 28, 2010
    #3
  4. GZ

    GZ Guest

    Hi Chris,

    On Apr 27, 6:43 pm, Chris Rebert <> wrote:
    > On Tue, Apr 27, 2010 at 4:36 PM, GZ <> wrote:
    > > I want to store a reference to a function into a class property.

    >
    > > So I am expecting that:

    >
    > > class A:
    > >     fn = lambda x: x

    >
    > > fn = A.fn
    > > fn(1)

    >
    > > Traceback (most recent call last):
    > >  File "<string>", line 1, in <string>
    > > TypeError: unbound method <lambda>() must be called with A instance as
    > > first argument (got int instance instead)

    >
    > > The problem is that A.fn is treated as a bounded method. I really want
    > > A.fn to be a variable that stores a reference to a function. Is there
    > > any way to achieve this?

    >
    > Use the staticmethod() decorator:
    >
    > class A(object):
    >     @staticmethod
    >     def fn(x):
    >         return x
    >
    > #rest same as before
    >
    > Cheers,
    > Chris
    > --http://blog.rebertia.com- Hide quoted text -
    >
    > - Show quoted text -


    I do not think it will help me. I am not trying to define a function
    fn() in the class, but rather I want to make it a "function reference"
    so that I can initialize it any way I like later.

    For example, I want to be able to write the following:

    A.fn = lambda x : x*x
    f = A.fn
    f(1)
    A.fn = lambda x : x^2
    f= A.fn
    f(2)

    In other words, I want to make A.fn a reference to a function not
    known to me at the time I define class A. I want to be able to
    initialize it later.
    GZ, Apr 28, 2010
    #4
  5. GZ

    MRAB Guest

    Terry Reedy wrote:
    > On 4/27/2010 7:36 PM, GZ wrote:
    >> I want to store a reference to a function into a class property.
    >>
    >> So I am expecting that:
    >>
    >> class A:
    >> fn = lambda x: x
    >>
    >> fn = A.fn
    >> fn(1)
    >>
    >> Traceback (most recent call last):
    >> File "<string>", line 1, in<string>
    >> TypeError: unbound method<lambda>() must be called with A instance as
    >> first argument (got int instance instead)
    >>
    >>
    >> The problem is that A.fn is treated as a bounded method. I really want
    >> A.fn to be a variable that stores a reference to a function. Is there
    >> any way to achieve this?

    >
    > Use 3.1, though you will have the same issue when calling it and same
    > fix that Chris gave.
    >

    Python 3.1.1 (r311:74483, Aug 17 2009, 17:02:12) [MSC v.1500 32 bit
    (Intel)] on win32
    Type "copyright", "credits" or "license()" for more information.
    >>> class A:

    fn = lambda x: x


    >>> fn = A.fn
    >>> fn(1)

    1
    MRAB, Apr 28, 2010
    #5
  6. GZ

    alex23 Guest

    GZ <> wrote:
    > I do not think it will help me. I am not trying to define a function
    > fn() in the class, but rather I want to make it a "function reference"
    > so that I can initialize it any way I like later.


    It always helps to try an idea out before dismissing it out of hand.
    Experimentation in the interpreter is cheap and easy.

    >>> class A(object):

    .... fn = staticmethod(lambda x: x*x)
    ....
    >>> A.fn(10)

    100
    >>> A.fn = staticmethod(lambda x: x**x)
    >>> A.fn(3)

    27
    >>> def third(x): return x/3

    ....
    >>> A.fn = staticmethod(third)
    >>> A.fn(9)

    3

    However, I'm assuming you're wanting to do something like this:

    >>> class B(object):

    .... def act(self):
    .... print self.fn()

    That is, providing a hook in .act() that you can redefine on demand.
    If so, note that you only need to decorate functions as staticmethods
    if you're assigning them to the class. If you intend on overriding on
    _instances_, you don't:

    >>> B.fn = staticmethod(lambda: 'one') # assign on class
    >>> b = B() # instantiate
    >>> b.act() # act on instance

    one
    >>> B.fn = staticmethod(lambda: 'two') # assign on class
    >>> b.act() # existing instance calls new version on class

    two
    >>> b.fn = staticmethod(lambda: 'three') # assign on instance
    >>> b.act()

    Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
    File "<stdin>", line 3, in act
    TypeError: 'staticmethod' object is not callable
    >>> b.fn = lambda: 'three' # look Ma, no staticmethod!
    >>> b.act()

    three

    Incidentally, this is known as the Strategy pattern, and you can see a
    simple example of it in Python here: http://en.wikipedia.org/wiki/Strategy_pattern#Python

    Hope this helps.
    alex23, Apr 28, 2010
    #6
  7. GZ

    GZ Guest

    On Apr 27, 9:20 pm, alex23 <> wrote:
    > GZ <> wrote:
    > > I do not think it will help me. I am not trying to define a function
    > > fn() in the class, but rather I want to make it a "function reference"
    > > so that I can initialize it any way I like later.

    >
    > It always helps to try an idea out before dismissing it out of hand.
    > Experimentation in the interpreter is cheap and easy.
    >
    > >>> class A(object):

    >
    > ...   fn = staticmethod(lambda x: x*x)
    > ...>>> A.fn(10)
    > 100
    > >>> A.fn = staticmethod(lambda x: x**x)
    > >>> A.fn(3)

    > 27
    > >>> def third(x): return x/3

    > ...
    > >>> A.fn = staticmethod(third)
    > >>> A.fn(9)

    >
    > 3
    >
    > However, I'm assuming you're wanting to do something like this:
    >
    > >>> class B(object):

    >
    > ...   def act(self):
    > ...     print self.fn()
    >
    > That is, providing a hook in .act() that you can redefine on demand.
    > If so, note that you only need to decorate functions as staticmethods
    > if you're assigning them to the class. If you intend on overriding on
    > _instances_, you don't:
    >
    > >>> B.fn = staticmethod(lambda: 'one') # assign on class
    > >>> b = B() # instantiate
    > >>> b.act() # act on instance

    > one
    > >>> B.fn = staticmethod(lambda: 'two') # assign on class
    > >>> b.act() # existing instance calls new version on class

    > two
    > >>> b.fn = staticmethod(lambda: 'three') # assign on instance
    > >>> b.act()

    >
    > Traceback (most recent call last):
    >   File "<stdin>", line 1, in <module>
    >   File "<stdin>", line 3, in act
    > TypeError: 'staticmethod' object is not callable>>> b.fn = lambda: 'three' # look Ma, no staticmethod!
    > >>> b.act()

    >
    > three
    >
    > Incidentally, this is known as the Strategy pattern, and you can see a
    > simple example of it in Python here:http://en.wikipedia.org/wiki/Strategy_pattern#Python
    >
    > Hope this helps.


    Ah, this totally works. The key is to use the staticmethod function.
    Thanks a lot.
    GZ, Apr 28, 2010
    #7
  8. GZ

    GZ Guest

    On Apr 27, 9:20 pm, alex23 <> wrote:
    > GZ <> wrote:
    > > I do not think it will help me. I am not trying to define a function
    > > fn() in the class, but rather I want to make it a "function reference"
    > > so that I can initialize it any way I like later.

    >
    > It always helps to try an idea out before dismissing it out of hand.
    > Experimentation in the interpreter is cheap and easy.
    >
    > >>> class A(object):

    >
    > ...   fn = staticmethod(lambda x: x*x)
    > ...>>> A.fn(10)
    > 100
    > >>> A.fn = staticmethod(lambda x: x**x)
    > >>> A.fn(3)

    > 27
    > >>> def third(x): return x/3

    > ...
    > >>> A.fn = staticmethod(third)
    > >>> A.fn(9)

    >
    > 3
    >
    > However, I'm assuming you're wanting to do something like this:
    >
    > >>> class B(object):

    >
    > ...   def act(self):
    > ...     print self.fn()
    >
    > That is, providing a hook in .act() that you can redefine on demand.
    > If so, note that you only need to decorate functions as staticmethods
    > if you're assigning them to the class. If you intend on overriding on
    > _instances_, you don't:
    >
    > >>> B.fn = staticmethod(lambda: 'one') # assign on class
    > >>> b = B() # instantiate
    > >>> b.act() # act on instance

    > one
    > >>> B.fn = staticmethod(lambda: 'two') # assign on class
    > >>> b.act() # existing instance calls new version on class

    > two
    > >>> b.fn = staticmethod(lambda: 'three') # assign on instance
    > >>> b.act()

    >
    > Traceback (most recent call last):
    >   File "<stdin>", line 1, in <module>
    >   File "<stdin>", line 3, in act
    > TypeError: 'staticmethod' object is not callable>>> b.fn = lambda: 'three' # look Ma, no staticmethod!
    > >>> b.act()

    >
    > three
    >
    > Incidentally, this is known as the Strategy pattern, and you can see a
    > simple example of it in Python here:http://en.wikipedia.org/wiki/Strategy_pattern#Python
    >
    > Hope this helps.


    Another question: I am not sure how staticmethod works internally. And
    the python doc does not seem to say. What does it do?
    GZ, Apr 28, 2010
    #8
  9. GZ

    Chris Rebert Guest

    On Tue, Apr 27, 2010 at 11:02 PM, GZ <> wrote:
    > On Apr 27, 9:20 pm, alex23 <> wrote:
    >> GZ <> wrote:
    >> > I do not think it will help me. I am not trying to define a function
    >> > fn() in the class, but rather I want to make it a "function reference"
    >> > so that I can initialize it any way I like later.

    >>
    >> It always helps to try an idea out before dismissing it out of hand.
    >> Experimentation in the interpreter is cheap and easy.
    >>
    >> >>> class A(object):

    >>
    >> ...   fn = staticmethod(lambda x: x*x)
    >> ...>>> A.fn(10)
    >> 100
    >> >>> A.fn = staticmethod(lambda x: x**x)
    >> >>> A.fn(3)

    >> 27
    >> >>> def third(x): return x/3

    >> ...
    >> >>> A.fn = staticmethod(third)
    >> >>> A.fn(9)

    >>
    >> 3
    >>
    >> However, I'm assuming you're wanting to do something like this:
    >>
    >> >>> class B(object):

    >>
    >> ...   def act(self):
    >> ...     print self.fn()
    >>
    >> That is, providing a hook in .act() that you can redefine on demand.
    >> If so, note that you only need to decorate functions as staticmethods
    >> if you're assigning them to the class. If you intend on overriding on
    >> _instances_, you don't:
    >>
    >> >>> B.fn = staticmethod(lambda: 'one') # assign on class
    >> >>> b = B() # instantiate
    >> >>> b.act() # act on instance

    >> one
    >> >>> B.fn = staticmethod(lambda: 'two') # assign on class
    >> >>> b.act() # existing instance calls new version on class

    >> two
    >> >>> b.fn = staticmethod(lambda: 'three') # assign on instance
    >> >>> b.act()

    >>
    >> Traceback (most recent call last):
    >>   File "<stdin>", line 1, in <module>
    >>   File "<stdin>", line 3, in act
    >> TypeError: 'staticmethod' object is not callable>>> b.fn = lambda: 'three' # look Ma, no staticmethod!
    >> >>> b.act()

    >>
    >> three
    >>
    >> Incidentally, this is known as the Strategy pattern, and you can see a
    >> simple example of it in Python here:http://en.wikipedia.org/wiki/Strategy_pattern#Python
    >>
    >> Hope this helps.

    >
    > Another question: I am not sure how staticmethod works internally. And
    > the python doc does not seem to say. What does it do?


    It involves the relatively arcane magic of "descriptors".
    See http://docs.python.org/reference/datamodel.html#implementing-descriptors
    or for a more complete but advanced explanation, the "Static methods
    and class methods" section of
    http://www.python.org/download/releases/2.2.3/descrintro/

    Understanding exactly how staticmethod() and friends work is not too
    essential in practice though.

    Cheers,
    Chris
    --
    http://blog.rebertia.com
    Chris Rebert, Apr 28, 2010
    #9
  10. GZ

    GZ Guest

    On Apr 28, 1:20 am, Chris Rebert <> wrote:
    > On Tue, Apr 27, 2010 at 11:02 PM, GZ <> wrote:
    > > On Apr 27, 9:20 pm, alex23 <> wrote:
    > >> GZ <> wrote:
    > >> > I do not think it will help me. I am not trying to define a function
    > >> > fn() in the class, but rather I want to make it a "function reference"
    > >> > so that I can initialize it any way I like later.

    >
    > >> It always helps to try an idea out before dismissing it out of hand.
    > >> Experimentation in the interpreter is cheap and easy.

    >
    > >> >>> class A(object):

    >
    > >> ...   fn = staticmethod(lambda x: x*x)
    > >> ...>>> A.fn(10)
    > >> 100
    > >> >>> A.fn = staticmethod(lambda x: x**x)
    > >> >>> A.fn(3)
    > >> 27
    > >> >>> def third(x): return x/3
    > >> ...
    > >> >>> A.fn = staticmethod(third)
    > >> >>> A.fn(9)

    >
    > >> 3

    >
    > >> However, I'm assuming you're wanting to do something like this:

    >
    > >> >>> class B(object):

    >
    > >> ...   def act(self):
    > >> ...     print self.fn()

    >
    > >> That is, providing a hook in .act() that you can redefine on demand.
    > >> If so, note that you only need to decorate functions as staticmethods
    > >> if you're assigning them to the class. If you intend on overriding on
    > >> _instances_, you don't:

    >
    > >> >>> B.fn = staticmethod(lambda: 'one') # assign on class
    > >> >>> b = B() # instantiate
    > >> >>> b.act() # act on instance
    > >> one
    > >> >>> B.fn = staticmethod(lambda: 'two') # assign on class
    > >> >>> b.act() # existing instance calls new version on class
    > >> two
    > >> >>> b.fn = staticmethod(lambda: 'three') # assign on instance
    > >> >>> b.act()

    >
    > >> Traceback (most recent call last):
    > >>   File "<stdin>", line 1, in <module>
    > >>   File "<stdin>", line 3, in act
    > >> TypeError: 'staticmethod' object is not callable>>> b.fn = lambda: 'three' # look Ma, no staticmethod!
    > >> >>> b.act()

    >
    > >> three

    >
    > >> Incidentally, this is known as the Strategy pattern, and you can see a
    > >> simple example of it in Python here:http://en.wikipedia.org/wiki/Strategy_pattern#Python

    >
    > >> Hope this helps.

    >
    > > Another question: I am not sure how staticmethod works internally. And
    > > the python doc does not seem to say. What does it do?

    >
    > It involves the relatively arcane magic of "descriptors".
    > Seehttp://docs.python.org/reference/datamodel.html#implementing-descriptors
    > or for a more complete but advanced explanation, the "Static methods
    > and class methods" section ofhttp://www.python.org/download/releases/2.2.3/descrintro/
    >
    > Understanding exactly how staticmethod() and friends work is not too
    > essential in practice though.
    >
    > Cheers,
    > Chris
    > --http://blog.rebertia.com- Hide quoted text -
    >
    > - Show quoted text -


    Got it. I appreciate your help.
    GZ, Apr 28, 2010
    #10
  11. GZ a écrit :
    (snip)
    > Ah, this totally works. The key is to use the staticmethod function.


    staticmethod is not a function, it's a class.

    > Another question: I am not sure how staticmethod works internally. And
    > the python doc does not seem to say. What does it do?


    It's easy to figure this out once you understand how Python turns
    functions into methods: http://wiki.python.org/moin/FromFunctionToMethod

    Basically, the staticmethod type acts as a descriptor wrapper around the
    function object that short-circuits the function object's own descriptor
    implementation and yields the function.
    Bruno Desthuilliers, Apr 28, 2010
    #11
    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. =?Utf-8?B?UnVkeQ==?=

    to store or not to store an image

    =?Utf-8?B?UnVkeQ==?=, Mar 29, 2005, in forum: ASP .Net
    Replies:
    6
    Views:
    624
    =?Utf-8?B?UnVkeQ==?=
    Mar 30, 2005
  2. jose luis fernandez diaz

    Nonlocal Store (global and class static variables)

    jose luis fernandez diaz, Jan 2, 2004, in forum: C++
    Replies:
    8
    Views:
    1,216
    Victor Bazarov
    Jan 6, 2004
  3. Replies:
    9
    Views:
    931
  4. Sky
    Replies:
    2
    Views:
    278
    Robert Koritnik
    Oct 1, 2004
  5. Replies:
    2
    Views:
    175
Loading...

Share This Page