Подтвердить что ты не робот

Создание класса, вызываемого в одном экземпляре

class Foo(object):
    def tick(self):
        print("something")

class Bar(object):
    def __init__(self):
        self.foo = Foo()

    def tick(self):
        #Here what I do....
        self.foo.tick()

        #here what my goal would be
        self.foo()

b = Bar()
b.tick()

Это по сути моя цель. Из того, что я собрал, я мог бы изменить функцию тика на __call__, и это позволило бы мне делать то, что я хотел. Несколько других ответов сказали, что это сделает новый экземпляр объекта, означает ли это, что он будет использовать память self.foo? или он сделает совершенно новый объект, вновь созданный? или сделать копию self.foo?

Также приходит на ум пара недостатков, которые могут проявляться или не проявляться. Для определенной части моей программы я проверяю, есть ли у объекта __call__, чтобы определить, является ли аргумент, который я передаю, функцией или переменной, и я действительно не думаю, что я хотел бы разрешить это (хотя, я полагаю, класс технически был бы функцией в этой точке.) Есть ли способ различать функцию и вызываемый класс?

Есть ли что-нибудь еще, что сделало бы это нежелательным (и это питонический способ работать?)? Моя следующая мысль заключалась в том, что, учитывая, что другая переменная с префиксом __ не может использоваться вне их класса, но это, похоже, не так.

4b9b3361

Ответ 1

Изменение tick(self) до __call__(self) - правильное решение.

Это не имеет никакого отношения к распределению памяти. Все __call__ означает функцию, которую Python вызывает при использовании (для объекта foo) синтаксиса foo().

Для вашего более позднего вопроса: чтобы проверить, что-то есть объект, используйте isinstance или issubclass (возможно, с классом object). И на мой взгляд этот ответ лучше, чем принятый для "Как определить, является ли что-то функцией?" вопрос, который вы, вероятно, видели.

Ответ 2

Чтобы сделать экземпляр класса вызываемым, все, что вам нужно сделать, это реализовать метод __call__. Затем, чтобы вызвать метод __call__, вы просто выполните: instance(arg1,arg2,...) - другими словами, вы вызываете экземпляр так же, как вы вызываете функцию.

Обратите внимание, что вы можете использовать псевдоним __call__ с каким-либо другим методом, определенным в классе, если вы хотите:

>>> class Foo(object):
...     def tick(self):
...         print ("something")
...     __call__ = tick
... 
>>> a = Foo()
>>> a()
something
>>> a.tick()
something