Re: staticmethod and setattr

Discussion in 'Python' started by Andreas Löscher, Mar 15, 2010.

  1. Am Montag, den 15.03.2010, 05:42 -0700 schrieb Michael.Lausch:
    > On Mar 15, 11:40 am, Steven D'Aprano <st...@REMOVE-THIS-
    > cybersource.com.au> wrote:
    > > On Mon, 15 Mar 2010 01:43:02 -0700, Michael.Lausch wrote:
    > > > Hi,

    > >
    > > > I managed to get confused by Python, which is not such an easy task.

    > >
    > > > The problem i have is rooted in marshalling, JSON and Dojo. I need some
    > > > static class in function with the name "$ref" i tried:
    > > > class Foo(object):
    > > > @staticmethod
    > > > def _ref(o):
    > > > pass

    > >
    > > > setattr(Foo, "$ref", Foo._ref)

    > >
    > > That doesn't work as expected:
    > >
    > > >>> Foo.__dict__['_ref'] is Foo.__dict__['$ref']

    > >
    > > False
    > >
    > > Try this instead:
    > >
    > > >>> setattr(Foo, "$ref", Foo.__dict__['_ref'])
    > > >>> Foo.__dict__['_ref'] is Foo.__dict__['$ref']

    > >
    > > True

    >
    > Now I'm trying to understand why this is the case.
    > How is Foo.__dict__['_ref'] different from Foo._ref?
    > Shouldn't it return the same attribute?
    >
    > And after further experiments i found out that a making
    > Foo._ref a classmethod does work with my first approach.
    >


    In the class dictionary are the "raw" objects stored. For example:

    class Spam:
    @staticmethod
    def egg1():
    pass
    def egg2(self):
    pass

    >>> Spam.__dict__

    {'egg1': <staticmethod object at 0x7f0b03240b40>, '__module__':
    '__main__', 'egg2': <function egg2 at 0x7f0b0432a2a8>, '__doc__': None}

    If you try to call egg1 as staticmethod you will get an error:
    >>> Spam.__dict__['egg1']()

    Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
    TypeError: 'staticmethod' object is not callable

    getattr() is not only a shortcut for the line above. It searches all
    base classes for the specified name in the class dictionaries. If the
    name is found, and the object has an additional descriptor, it is
    applied on the object itself.

    In case of an static method, the descriptor sm_descr_get is located in
    Objects/funcobjects.c of the sources and it retriefes the encapsuled
    callable, which in this case is the function egg1.

    If you now set the function as new attribute, it is no longer a static
    method, but a normal function. If a function is retrieved via getattr(),
    it is encapsuled in an method object. (func_descr_get in the same file)
    If you now try to call the method in you example, you call a method from
    a class. This results in an unbound method, which requests an instance
    of the class as first agument.

    I hope this clears some things up.

    Best
    Andreas
    Andreas Löscher, Mar 15, 2010
    #1
    1. Advertising

  2. Am Montag, den 15.03.2010, 05:42 -0700 schrieb Michael.Lausch:
    >> On Mar 15, 11:40 am, Steven D'Aprano <st...@REMOVE-THIS-
    >> cybersource.com.au> wrote:
    >>
    >>> On Mon, 15 Mar 2010 01:43:02 -0700, Michael.Lausch wrote:
    >>>
    >>>> Hi,
    >>>>
    >>>> I managed to get confused by Python, which is not such an easy task.
    >>>>
    >>>> The problem i have is rooted in marshalling, JSON and Dojo. I need some
    >>>> static class in function with the name "$ref" i tried:
    >>>> class Foo(object):
    >>>> @staticmethod
    >>>> def _ref(o):
    >>>> pass
    >>>>
    >>>> setattr(Foo, "$ref", Foo._ref)
    >>>>
    >>> That doesn't work as expected:
    >>>
    >>>
    >>>>>> Foo.__dict__['_ref'] is Foo.__dict__['$ref']
    >>>>>>
    >>> False
    >>>
    >>> Try this instead:
    >>>
    >>>
    >>>>>> setattr(Foo, "$ref", Foo.__dict__['_ref'])
    >>>>>> Foo.__dict__['_ref'] is Foo.__dict__['$ref']
    >>>>>>
    >>> True
    >>>

    >> Now I'm trying to understand why this is the case.
    >> How is Foo.__dict__['_ref'] different from Foo._ref?
    >> Shouldn't it return the same attribute?
    >>
    >> And after further experiments i found out that a making
    >> Foo._ref a classmethod does work with my first approach.
    >>
    >>


    When you declared _ref as static, a static object has been stored in Foo.
    Using Foo.__dict__ you can access this static object, which is *not* the
    _ref function
    Using Foo._ref, you trigger the lookup mechanism which do much more than
    accessing the dict. Especially, if it finds a __get__ method in the
    object, it will return the __get__ result instead of the object itself.

    Foo._ref is equivalent in your case to
    Foo.__dict__['_ref'].__get__(None, Foo)


    JM
    Jean-Michel Pichavant, Mar 15, 2010
    #2
    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. Andrew Bennetts

    Re: __getitem__ and classmethod/staticmethod

    Andrew Bennetts, Jun 25, 2004, in forum: Python
    Replies:
    0
    Views:
    480
    Andrew Bennetts
    Jun 25, 2004
  2. Karl Chen
    Replies:
    0
    Views:
    334
    Karl Chen
    Jun 25, 2004
  3. C Gillespie

    staticmethod and classmethod

    C Gillespie, May 24, 2005, in forum: Python
    Replies:
    5
    Views:
    5,760
    =?iso-8859-1?Q?Fran=E7ois?= Pinard
    May 26, 2005
  4. darnzen

    staticmethod and namespaces

    darnzen, Feb 26, 2010, in forum: Python
    Replies:
    0
    Views:
    259
    darnzen
    Feb 26, 2010
  5. Michael.Lausch

    staticmethod and setattr

    Michael.Lausch, Mar 15, 2010, in forum: Python
    Replies:
    3
    Views:
    319
    Bruno Desthuilliers
    Mar 15, 2010
Loading...

Share This Page