简体   繁体   中英

In python, how to overload return/get based on return type?

In python, is it possible to overload the return type? Basically, I'm trying to see if I can do something like this:

class Node(object):
   def __init__(self):
       self.value = 5

   def hello(self):
       print('hello')

class Container(object):
   def __init__(self):
       self.node = Node()

   def __setattr__(self, name, value):
       if self.__dict__.get(name, False) and name == 'node':
          obj = getattr(self, name)
          obj.value = value
       else:
          self.__dict__[name] = value

       # some method overloading... to return base on type

container = Container()
container.node = 3
print (container.node.value) # outputs 3
int_val = 0
int_val = container.node  # assign int_val to 3
container.node.hello() # prints out 'hello'

That's not possible. You can define an __int__ method to specify what should happen when int is called on an instance of your class, so that int(container.node) would be 3. But you can't have container.node actually be 3, while the container.node part of container.node.hello() is something else. Evaluation of the attribute references in container.node.hello() occurs left to right, so container.node is evaluated without "knowing" that you will later try to call a method on it.

As Patrick Haugh suggests in his answer, you could subclass int so that container.node is something that behaves like the number 3 but also has a .hello() method. But still you're not causing container.node to have different values in different contexts; you're causing it to have one value that combines the features you want across the two contexts. The value is not actually 3 but a Node instance, which can matter in some situations. Still, this can often be a legitimate way to achieve a similar effect to what you seem to want.

It is also possible to use __setattr__ so that container.node = 3 will set the value to something other than 3 (for instance, to some wrapper object), but that won't change the above. When you evaluate container.node , it can only have one value across all contexts.

Below, I make a Node class that is a subclass of int , basically just adding a hello method. Container uses property to turn int values into Node s behind the scenes.

class Node(int):
    def __new__(cls, value, *args, **kwargs):
        return super(Node, cls).__new__(cls, value, *args, **kwargs)
    def hello(self):
        print("Hello!")

class Container(object):
    def __init__(self):
        self.node = 5
    @property
    def node(self):
        return self._node
    @node.setter
    def node(self, value):
        self._node = Node(value)

container = Container()
container.node = 3
print(container.node)  # 3
container.node.hello()  # Hello!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM