[Chicago] Prevent access to method as attribute

Adam Forsyth agforsyth at gmail.com
Wed Oct 17 05:31:31 CEST 2012

Since this seems like it would mostly be useful for beginners, I'd focus on
the most common case -- forgetting to call an instance method in a boolean
context (like an "if" statement).

from types import MethodType

class UnBoolableCallable(object):
    def __init__(self, call):
        self.call = call
    def __call__(self, *args, **kwargs):
        return self.call(*args, **kwargs)
    def __len__(self): # why doesn't __bool__ work? check on this.
        raise Exception("You forgot to call me!")

# we could do this in __new__ on the class
# since we're only customizing instance creation, not class creation
class AngryObject(type):
    def __call__(cls, *args, **kwargs):
        # create the instance
        instance = super(AngryObject, cls).__call__(*args, **kwargs)
        # for each attribute in the class dict
        for attr in vars(cls):
            # get the object from the instance (so as to bind methods)
            value = getattr(instance, attr)
            # if it's an instance method
            if isinstance(value, MethodType):
                # wrap it in an un-boolable type
                setattr(instance, attr, UnBoolableCallable(value))
        return instance

class A(object):
    __metaclass__ = AngryObject
    def isValid(self):
        return False

# first two work, third raises
for result in A().isValid(), A.isValid, A().isValid:
    print result, type(result), bool(result)

P.S. If you really want this behavior use Ruby.

On Tue, Oct 16, 2012 at 11:58 AM, Brian Ray <brianhray at gmail.com> wrote:

> Question came up from a colleague:
> I wonder, if there is a simple way in Python to add a hook to class that
> makes sure methods don't not get called as attributes.
> class A:
>     def isValid(self):
>            return False
> if A().isValid:
>     print 'Always True'
> I had some wacky and wild thoughts about subclassing something to
> check each and every call and using inspect module to see how it was
> called. Generally, I know it is the callers responsibility to know
> what they are doing. We are all responsible adults here, correct?
> --
> Brian Ray
> @brianray
> (773) 669-7717
> _______________________________________________
> Chicago mailing list
> Chicago at python.org
> http://mail.python.org/mailman/listinfo/chicago
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/chicago/attachments/20121016/0ae876df/attachment.html>

More information about the Chicago mailing list