AnswerBun.com

Determine if __getattr__ is method or attribute call

Stack Overflow Asked by Robin Orheden on December 10, 2020

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.

3 Answers

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!

Correct answer by Martijn Pieters on December 10, 2020

It is not possible to know whether an attribute is subsequently called from __getattr__, which Martijn Pieters explains.

Although it does not determine whether an attribute has subsequently been called, it is possible to know whether an attribute can be called with callable. Another way is to use type to keep track of the various objects, or make a list of attribute names.

class Foo(object):
    bar_attribute = 'callable'

    def __getattr__(self, name):
        instanceOrValue = getattr(self, "bar_%s" %name)

        if callable(instanceOrValue):
            # Handle object that can be called
            def wrap(**kwargs):
                return "is %s" %instanceOrValue(**kwargs)
            return wrap

        # Handle object that can not be called
        return 'not %s' %instanceOrValue

    def bar_method(self, **kwargs):
        return 'callable';
    

foo=Foo()
print(foo.method()) # is callable
print(foo.attribute) # not callable

This way can only keep track of certain things and not whether a method is called, but sometimes it is enough or the right solution because you do not always need to change or influence the process of calling (__call__).

Difference between calling a method and accessing an attribute

What is a "callable"?

Python __call__ special method practical example

Answered by Diblo Dk on December 10, 2020

In short, no, there is no reliable way - the issue is that a method is an attribute in Python - there is no distinction made. It just happens to be an attribute that is a bound method.

You can check if the attribute is a method, but there is no guarantee that means it will be called, e.g:

class Test:
    def test(self):
        ...

Test().test  # This accesses the method, but doesn't call it!

There is no way for the call accessing the function to know if it's going to be called when it is returned - that's a future event that hasn't yet been processed.

If you are willing to assume that a method being accessed is a method being called, you can determine that it is a method being accessed with a check like this:

hasattr(value, "__self__") and value.__self__ is self

Where value is the attribute you want to check to see if it is a method or some other attribute, and self is the instance you want to see if it's a method for.

If you need something to happen when it is called, you could use this moment to decorate the function.

An solid code example of this can be found here.

Answered by Gareth Latty on December 10, 2020

Add your own answers!

Related Questions

Animation to play once per session

0  Asked on January 15, 2021 by alejandro-vargas

       

postgres random text in jsonb column

2  Asked on January 15, 2021 by ed1t

         

How to make TestNG print detail message about the failure

2  Asked on January 15, 2021 by gelin-luo

 

Strange igraph behaviour, generating duplicate vertices

1  Asked on January 15, 2021 by simon-mills

   

C++ printing float as nan

1  Asked on January 14, 2021 by acarter

     

Webclient isn’t dowloading everything from URL c#

1  Asked on January 14, 2021 by shynex

       

How to change the entire div content on button click

2  Asked on January 14, 2021 by liel-barouch

   

Sorting and paging nested documents

2  Asked on January 14, 2021 by taras-kohut

 

How to adjust for loop so that it prints list only once?

1  Asked on January 14, 2021 by benito-cano

         

Ask a Question

Get help from others!

© 2022 AnswerBun.com. All rights reserved. Sites we Love: PCI Database, MenuIva, UKBizDB, Menu Kuliner, Sharing RPP, SolveDir