koriander
koriander

Reputation: 3258

issue with callable, detects more than __call__

I am testing the simpleTAL templating library which makes use of callable to test if an object passed into the template is a function or not. The definition of callable says that an object is callable if it contains the magic method __call__. See also What is a "callable" in Python?.

However, an object created with the following class definition (python 2.7.4)

class H:
    def __init__(self, val):
        self.a = val
    def __getattr__(self, name):
        return 'blah'

h = H(1)
callable(h)

will return True. If, however, __getattr__ raises AttributeError, which does not make sense to do systematically, it will return False!

Can someone shed some light on this issue and possibly a solution? (I don't want h to be callable).

Upvotes: 2

Views: 87

Answers (1)

Martijn Pieters
Martijn Pieters

Reputation: 1123400

Your __getattr__ hook returns a value for all attributes:

>>> h.__call__
'blah'

and thus a test for hasattr(h, '__call__') returns True:

>>> hasattr(h, '__call__')
True

Make sure you raise a AttributeError for attributes the object doesn't support instead.

Note: this applies only to old-style instances; instances for new-style classes (the default in Python 3, and any class inheriting from object in Python 2) are not tested for the __call__ attribute; instead the class itself is consulted.

You could thus switch to new-style classes as well to mitigate this, but your __getattr__ should still not be too broad.

Upvotes: 6

Related Questions