Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
316 views
in Technique[技术] by (71.8m points)

python - Determine if __getattr__ is method or attribute call

Is there any way to determine the difference between a method and an attribute call using __getattr__?

I.e. in:

class Bar(object):
    def __getattr__(self, name):
        if THIS_IS_A_METHOD_CALL:
            # Handle method call
            def method(**kwargs):
                return 'foo'
            return method
        else:
            # Handle attribute call
            return 'bar'

foo=Bar()
print(foo.test_method()) # foo
print(foo.test_attribute) # bar

The methods are not local so it's not possible to determine it using getattr/callable. I also understand that methods are attributes, and that there might not be a solution. Just hoping there is one.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

You cannot tell how an object is going to used in the __getattr__ hook, at all. You can access methods without calling them, store them in a variable, and later call them, for example.

Return an object with a __call__ method, it'll be invoked when called:

class CallableValue(object):
    def __init__(self, name):
        self.name = name
    def __call__(self, *args, **kwargs):
        print "Lo, {} was called!".format(self.name)

class Bar(object):
    def __getattr__(self, name):
        return CallableValue(name)

but instances of this will not be the same thing as a string or a list at the same time.

Demo:

>>> class CallableValue(object):
...     def __init__(self, name):
...         self.name = name
...     def __call__(self, *args, **kwargs):
...         print "Lo, {} was called!".format(self.name)
... 
>>> class Bar(object):
...     def __getattr__(self, name):
...         return CallableValue(name)
... 
>>> b = Bar()
>>> something = b.test_method
>>> something
<__main__.CallableValue object at 0x10ac3c290>
>>> something()
Lo, test_method was called!

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...