Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

How to combine property and function attributes in python?

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.

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

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)

>Solution :

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
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading