Home > Software design >  How to combine property and function attributes in python?
How to combine property and function attributes in python?

Time:12-07

Let's say there is a class SomeClass with function func which returns int. How can we implement a similar interface?

class SomeClass:
    @overload
    @property
    def f(self) -> int:
        return 1

    @overload
    def f(self, x: int) -> int:
        return x


if __name__ == "__main__":
    obj = SomeClass()
    print(obj.f)  # print 1
    print(obj.f(5))  # print 5

Preferably a solution without external modules, but if this is problematic, it is acceptable.

P.S. overload decorator doesn't exist, this is just an example.

Edit:

Function overloading is given only as an example implementation, but it is not necessary. The main goal is to implement this interface type:

obj = SomeClass()
obj.f  # returns 1 (without brackets, works like property)
obj.f(5)  # returns 5 (with brackets, works like a normal function)

CodePudding user response:

The core of your problem here is that you want obj.f to be simultaneously an int and a function:

    print(obj.f)     # print 1
    print(obj.f(5))  # print 5

This is technically possible by creating a callable int with the desired behavior, and having your property return that:

class SomeClass:
    class TrickyInt(int):
        def __new__(cls, val):
            return super().__new__(cls, val)

        def __call__(self, val):
            return self.__class__(val)

    @property
    def f(self):
        return self.TrickyInt(1)


if __name__ == "__main__":
    obj = SomeClass()
    print(obj.f)     # prints 1
    print(obj.f(5))  # prints 5

This is a lot of trouble to go to in order to implement a very unintuitive interface, though. I would recommend having this be a regular old method:

class SomeClass:
    def f(self, val=1):
        return val


if __name__ == "__main__":
    obj = SomeClass()
    print(obj.f())   # prints 1
    print(obj.f(5))  # prints 5
  • Related