В Python, как перегрузить возврат / получить в зависимости от типа возвращаемого значения? - PullRequest
0 голосов
/ 06 сентября 2018

В питоне, возможно ли перегрузить тип возвращаемого значения?По сути, я пытаюсь понять, могу ли я сделать что-то вроде этого:

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'

Ответы [ 2 ]

0 голосов
/ 06 сентября 2018

Ниже я делаю класс Node, который является подклассом int, просто добавляя метод hello. Container использует property, чтобы превратить int значения в Node s за кадром.

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!
0 голосов
/ 06 сентября 2018

Это невозможно. Вы можете определить метод __int__, чтобы указать, что должно происходить, когда int вызывается для экземпляра вашего класса, так что int(container.node) будет 3. Но вы не можете иметь container.node на самом деле быть 3, тогда как container.node часть container.node.hello() - это нечто другое. Оценка ссылок на атрибуты в container.node.hello() происходит слева направо, поэтому container.node оценивается без «знания», что вы позже попытаетесь вызвать метод для него.

Как Патрик Хау предлагает в своем ответе, вы можете подкласс int, так что container.node - это то, что ведет себя как число 3, но также имеет метод .hello(). Но все же вы не заставляете container.node иметь разные значения в разных контекстах; вы заставляете его иметь одно значение, которое объединяет нужные вам функции в двух контекстах. На самом деле это значение не 3, а экземпляр Node, который может иметь значение в некоторых ситуациях. Тем не менее, это часто может быть законным способом достижения эффекта, подобного тому, что вы, похоже, хотите.

Можно также использовать __setattr__, чтобы container.node = 3 установило значение, отличное от 3 (например, для некоторого объекта-оболочки), но это не изменит вышеприведенного. Когда вы оцениваете container.node, оно может иметь только одно значение во всех контекстах.

...