Get rid of recursive call __getattr__

Discussion in 'Python' started by Pelmen, Dec 14, 2005.

  1. Pelmen

    Pelmen Guest

    How can I get rid of recursive call __getattr__ inside this method, if
    i need to use method or property of the class?
    Pelmen, Dec 14, 2005
    #1
    1. Advertising

  2. Pelmen wrote:
    > How can I get rid of recursive call __getattr__ inside this method, if
    > i need to use method or property of the class?
    >

    Sorry, but I don't understand your question. Which recursive calls to
    __getattr__ ? __getattr__ is only called if a/ it's defined and b/ the
    attribute has not been found (see below).

    Have you overriden __setattr__ or __getattribute__ ? If yes, please read
    the corresponding sections of the Fine Manual.


    >>> class Toto(object):

    .... def __init__(self, name):
    .... self.name = name
    .... def __getattr__(self, attname):
    .... print "__getattr__ called for %s" % attname
    .... return "%s doesn't exists" % attname
    ....
    >>> t = Toto('toto')
    >>> t.name = name

    Traceback (most recent call last):
    File "<stdin>", line 1, in ?
    NameError: name 'name' is not defined
    >>> t.name

    'toto'
    >>> t.age

    __getattr__ called for age
    "age doesn't exists"

    --
    bruno desthuilliers
    python -c "print '@'.join(['.'.join([w[::-1] for w in p.split('.')]) for
    p in ''.split('@')])"
    bruno at modulix, Dec 14, 2005
    #2
    1. Advertising

  3. Pelmen wrote:
    > How can I get rid of recursive call __getattr__ inside this method, if
    > i need to use method or property of the class?


    Hi Pelmen,

    Having read the docs included with my Python distribution on
    __getattr__, I don't see yet how you will get recursive calls to the
    method... (It's called only when the attribute cannot be looked up via
    normal means)

    If you are seeing recursive calls to __getattr__, perhaps you can
    highlight the problem with some sample-code?

    regards,

    --Tim
    Tim N. van der Leeuw, Dec 14, 2005
    #3
  4. Pelmen

    Pelmen Guest

    thanks, i should been read more closely
    Pelmen, Dec 14, 2005
    #4
  5. Pelmen

    Pelmen Guest

    thanks, i understood my mistake
    i try to get attribute, that wasn't defined
    Pelmen, Dec 14, 2005
    #5
  6. Pelmen

    Steve Holden Guest

    Pelmen wrote:
    > How can I get rid of recursive call __getattr__ inside this method, if
    > i need to use method or property of the class?
    >

    The usual mistake here is to write a __getattr__() implementation that
    references an undefined self-relative name, which leads to a recursive
    call of __getattr__(), which ...

    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/
    Steve Holden, Dec 14, 2005
    #6
  7. Pelmen

    Pelmen Guest

    as __repr__ for example?
    Pelmen, Dec 14, 2005
    #7
  8. Pelmen

    Pelmen Guest

    thanks, i found the problem
    Pelmen, Dec 14, 2005
    #8
  9. Pelmen

    Pelmen Guest

    >>> class Test:
    def __getattr__(self, attr):
    print attr

    def foo(x):
    print x

    >>> t = Test()
    >>> print t

    __str__

    Traceback (most recent call last):
    File "<pyshell#23>", line 1, in -toplevel-
    print t
    TypeError: 'NoneType' object is not callable

    what i have to do? define __str__ explicitly?
    Pelmen, Dec 14, 2005
    #9
  10. Pelmen

    Peter Otten Guest

    Pelmen wrote:

    > >>> class Test:

    >           def __getattr__(self, attr):
    >             print attr
    >
    >           def foo(x):
    >             print x
    >
    > >>> t = Test()
    > >>> print t

    > __str__
    >
    > Traceback (most recent call last):
    >   File "<pyshell#23>", line 1, in -toplevel-
    >     print t
    > TypeError: 'NoneType' object is not callable
    >
    > what i have to do? define __str__ explicitly?


    By seemingly not returning anything your __getattr__() method actually
    returns None. Instead you should raise an AttributeError when your
    __getattr__() encounters the name of an attribute it doesn't handle.
    Let's assume Test.__getattr__() should implement an attribute 'alpha' and
    nothing else:

    >>> class Test:

    .... def __getattr__(self, name):
    .... print "looking up", name
    .... if name == "alpha":
    .... return 42
    .... print "lookup failed for", name
    .... raise AttributeError
    ....
    >>> print Test()

    looking up __str__
    lookup failed for __str__
    looking up __repr__
    lookup failed for __repr__
    <__main__.Test instance at 0x4029248c>

    When the lookup fails in the instance it is deferred to the class.
    By the way, new-style classes handle __special__ methods a bit differently
    -- try deriving Test from object

    class Test(object):
    # same as above

    to see the difference.

    Peter
    Peter Otten, Dec 14, 2005
    #10
  11. Pelmen

    Pelmen Guest

    thanks, now all clear
    Pelmen, Dec 14, 2005
    #11
  12. Pelmen

    Steve Holden Guest

    Peter Otten wrote:
    > Pelmen wrote:
    >
    >
    >>>>>class Test:

    >>
    >> def __getattr__(self, attr):
    >> print attr
    >>
    >> def foo(x):
    >> print x
    >>
    >>
    >>>>>t = Test()
    >>>>>print t

    >>
    >>__str__
    >>
    >>Traceback (most recent call last):
    >> File "<pyshell#23>", line 1, in -toplevel-
    >> print t
    >>TypeError: 'NoneType' object is not callable
    >>
    >>what i have to do? define __str__ explicitly?

    >
    >
    > By seemingly not returning anything your __getattr__() method actually
    > returns None. Instead you should raise an AttributeError when your
    > __getattr__() encounters the name of an attribute it doesn't handle.
    > Let's assume Test.__getattr__() should implement an attribute 'alpha' and
    > nothing else:
    >
    >
    >>>>class Test:

    >
    > ... def __getattr__(self, name):
    > ... print "looking up", name
    > ... if name == "alpha":
    > ... return 42
    > ... print "lookup failed for", name
    > ... raise AttributeError


    or, rather better IMHO,

    raise AttributeError("lookup failed for %s" % name)
    > ...
    >

    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/
    Steve Holden, Dec 14, 2005
    #12
  13. Pelmen

    Peter Hansen Guest

    Pelmen wrote:
    >>>>class Test:

    >
    > def __getattr__(self, attr):
    > print attr
    >
    > def foo(x):
    > print x
    >
    >
    >>>>t = Test()
    >>>>print t

    >
    > __str__
    >
    > Traceback (most recent call last):
    > File "<pyshell#23>", line 1, in -toplevel-
    > print t
    > TypeError: 'NoneType' object is not callable
    >
    > what i have to do? define __str__ explicitly?


    Yes. Or subclass "object" as it has a default __str__ already.

    (By the way, you do realize that the NoneType message comes because your
    __getattr__ is returning None, don't you? So technically you could also
    return a real value (in this case a callable) and it would also work,
    though it's very likely not what you wanted.

    class Test:
    def __getattr__(self, name):
    def callable_attribute():
    return 'i am attr %s' % name
    return callable_attribute

    >>> t = Test()
    >>> print t

    i am attr __str__

    -Peter
    Peter Hansen, Dec 14, 2005
    #13
  14. Steve Holden wrote:
    > Peter Otten wrote:
    >
    >> Pelmen wrote:
    >>
    >>
    >>>>>> class Test:
    >>>
    >>>
    >>> def __getattr__(self, attr):
    >>> print attr
    >>>
    >>> def foo(x):
    >>> print x
    >>>
    >>>
    >>>>>> t = Test()
    >>>>>> print t
    >>>
    >>>
    >>> __str__
    >>>
    >>> Traceback (most recent call last):
    >>> File "<pyshell#23>", line 1, in -toplevel-
    >>> print t
    >>> TypeError: 'NoneType' object is not callable
    >>>
    >>> what i have to do? define __str__ explicitly?

    >>
    >>
    >>
    >> By seemingly not returning anything your __getattr__() method actually
    >> returns None. Instead you should raise an AttributeError when your
    >> __getattr__() encounters the name of an attribute it doesn't handle.
    >> Let's assume Test.__getattr__() should implement an attribute 'alpha' and
    >> nothing else:
    >>
    >>
    >>>>> class Test:

    >>
    >>
    >> ... def __getattr__(self, name):
    >> ... print "looking up", name
    >> ... if name == "alpha":
    >> ... return 42
    >> ... print "lookup failed for", name
    >> ... raise AttributeError

    >
    >
    > or, rather better IMHO,
    >
    > raise AttributeError("lookup failed for %s" % name)


    or still better in IMNSHO:
    raise AttributeError("%s object has no attribute %s" %
    \ (self.__class__.__name__,
    name))

    (which is the 'standard' AttributeError message)



    --
    bruno desthuilliers
    python -c "print '@'.join(['.'.join([w[::-1] for w in p.split('.')]) for
    p in ''.split('@')])"
    bruno at modulix, Dec 15, 2005
    #14
    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. glomde
    Replies:
    5
    Views:
    514
    glomde
    Mar 29, 2007
  2. n00m
    Replies:
    12
    Views:
    1,102
  3. vamsi
    Replies:
    21
    Views:
    2,048
    Keith Thompson
    Mar 9, 2009
  4. Alok
    Replies:
    3
    Views:
    238
  5. Yohan N. Leder
    Replies:
    19
    Views:
    231
    Yohan N. Leder
    Jul 2, 2006
Loading...

Share This Page