0

I have one class A which extends B, and B has one method count(). Now I want to allow user call both A.count and A.count(). A.count means count is one field of A while A.count() means it is method derived from B.

zjffdu
  • 25,496
  • 45
  • 109
  • 159
  • you'll need to implement something on your class __getattr__, but really, i'm unable to see a good use case for that scenario ant that seems to be a bad design choice. Anyway, you can take a look at that question http://stackoverflow.com/questions/20120983/determine-if-getattr-is-method-or-attribute-call, it may help your case – Diogo Martins Feb 04 '16 at 03:33

2 Answers2

2

This is impossible in Python, and here's why:

You can always assign a method (or really any function) to a variable and call it later.

hello = some_function
hello()

is semantically identical to

some_function()

So what would happen if you had an object of your class A called x:

x = A()
foo = x.count
foo()

The only way you could do this is by storing a special object in x.count that is callable and also turns into e.g. an integer when used in that way, but that is horrible and doesn't actually work according to specification.

L3viathan
  • 26,748
  • 2
  • 58
  • 81
0

As i said, it's not exactly impossible, as told by other answers. Lets see a didactic example:

class A(object):
    class COUNT(object):
        __val = 12345

        def __call__(self, *args, **kwargs):
            return self.__val

        def __getattr__(self, item):
            return self.__val

        def __str__(self):
            return str(self.__val)

    count = COUNT()

if __name__ == '__main__':
    your_inst = A()

    print(your_inst.count)
    # outputs: 12345
    print(your_inst.count())
    # outputs: 12345

As you may notice, you need to implement a series of things to accomplish that kind of behaviour. First, your class will need to implement the attribute count not as the value type that you intent, but as an instance of another class, which will have to implement, among other things (to make that class behave, by duck typing, as the type you intent) the __call__ method, that should return the same as you A class __getattr__, that way, the public attribute count will answer as a callable (your_inst.count()) or, as you call, a field (your_inst.count), the same way.

By the way, i don't know if the following is clear to you or not, but it may help you understand why it isn't as trivial as one may think it is to make count and count() behave the same way:

class A(object):
    def count(self):
        return 123

if __name__ == '__main__':
    a = A()

    print(type(a.count))
    # outputs: <class 'method'>
    print(type(a.count()))
    # outputs: <class 'int'>

. invokes the a class __getattr__ to get the item count. a.count will return the referente to that function (python's function are first class objects), the second one, will do the same, but the parentheses will invoke the __call__ method from a.count.

Community
  • 1
  • 1
Diogo Martins
  • 917
  • 7
  • 15