Что такое "вызываемый" в Python?
Теперь понятно что такое метакласс-это, есть связанная концепция, которую я использую все время, не зная, что это на самом деле означает.
Я полагаю, что все когда-то сделали ошибку с круглыми скобками, в результате чего исключение "объект не вызывается". Более того, используя __init__
и __new__
интересно, что это за чертов __call__
можно использовать для.
не могли бы вы дать мне некоторые пояснения, в том числе примеры с магическим методом ?
12 ответов
вызываемый-это все, что можно назвать.
на встроенный вызвать (PyCallable_Check в объектах.c) проверяет, является ли аргумент является либо:
- экземпляр класса с __call__ способ или
- имеет тип, который имеет не null tp_call (C struct) член, который указывает на вызываемость в противном случае (например, в функциях, методах и т. д.)
метод с именем __call__ is (согласно документации)
вызывается, когда экземпляр "вызывается" как функция
пример
class Foo:
def __call__(self):
print 'called'
foo_instance = Foo()
foo_instance() #this is calling the __call__ method
из источников Python .
x
вызываемый iff x->ob_type->tp_call != NULL
описание tp_call
поле:
ternaryfunc tp_call
необязательный указатель на функцию, реализующую вызов объекта. Это должно быть NULL, если объект не вызывается. Подпись такая же, как для PyObject_Call(). Это поле наследуется подтипами.
вы всегда можете использовать встроенный callable
функция, чтобы определить, является ли данный объект вызываемым или нет; или еще лучше просто вызвать его и поймать TypeError
позже. callable
удалены в Python 3.0 и 3.1, используйте callable = lambda o: hasattr(o, '__call__')
или isinstance(o, collections.Callable)
.
пример упрощенного кэша реализация:
class Cached:
def __init__(self, function):
self.function = function
self.cache = {}
def __call__(self, *args):
try: return self.cache[args]
except KeyError:
ret = self.cache[args] = self.function(*args)
return ret
использование:
@Cached
def ack(x, y):
return ack(x-1, ack(x, y-1)) if x*y else (x + y + 1)
пример из стандартной библиотеки, file site.py
, определение встроенного exit()
и quit()
функции:
class Quitter(object):
def __init__(self, name):
self.name = name
def __repr__(self):
return 'Use %s() or %s to exit' % (self.name, eof)
def __call__(self, code=None):
# Shells like IDLE catch the SystemExit, but listen when their
# stdin wrapper is closed.
try:
sys.stdin.close()
except:
pass
raise SystemExit(code)
__builtin__.quit = Quitter('quit')
__builtin__.exit = Quitter('exit')
вызываемый объект позволяет использовать круглые скобки () и в конечном итоге передавать некоторые параметры, как и функции.
каждый раз, когда вы определяете функцию Python создает вызываемый объект. Например, вы можете определить функцию func таким образом (это то же самое):
class a(object):
def __call__(self, *args):
print 'Hello'
func = a()
# or ...
def func(*args):
print 'Hello'
вы можете использовать этот метод вместо метода как doit или run, Я думаю, что просто более ясно видеть obj (), чем параметр obj.doit ()
позвольте мне объяснить назад:
рассмотреть этот вопрос...
foo()
... как синтаксический сахар для:
foo.__call__()
здесь foo
может быть любой объект, который реагирует на __call__
. Когда я говорю любой объект, я имею в виду: встроенные типы, ваши собственные классы и их экземпляры.
в случае встроенных типов, когда вы пишете:
int('10')
unicode(10)
вы по существу делаете:
int.__call__('10')
unicode.__call__(10)
вот почему у вас нет foo = new int
в Python: вы просто сделайте объект class возвращающим экземпляр его на __call__
. То, как Python решает это, на мой взгляд, очень элегантно.
вызываемым является объект, который имеет __call__
метод. Это означает, что вы можете подделать вызываемые функции или делать аккуратные вещи, такие как Применение Частичной Функции где вы берете функцию и добавляете что-то, что улучшает ее или заполняет некоторые параметры, возвращая что-то, что можно вызвать в свою очередь (известный как карринг в функциональных кругах программирования).
некоторые типографские ошибки будут иметь интерпретатор, пытающийся вызвать то, что вы сделали не намереваться, например (например) строку. Это может привести к ошибкам, когда интерпретатор пытается выполнить не вызываемое приложение. Вы можете увидеть это в интерпретаторе python, сделав что-то вроде транскрипта ниже.
[nigel@k9 ~]$ python
Python 2.5 (r25:51908, Nov 6 2007, 15:55:44)
[GCC 4.1.2 20070925 (Red Hat 4.1.2-27)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> 'aaa'() # <== Here we attempt to call a string.
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'str' object is not callable
>>>
__call__
делает любой объект вызываемым как функция.
этот пример выведет 8:
class Adder(object):
def __init__(self, val):
self.val = val
def __call__(self, val):
return self.val + val
func = Adder(5)
print func(3)
в Python вызываемым является объект, тип которого имеет __call__
способ:
>>> class Foo:
... pass
...
>>> class Bar(object):
... pass
...
>>> type(Foo).__call__(Foo)
<__main__.Foo instance at 0x711440>
>>> type(Bar).__call__(Bar)
<__main__.Bar object at 0x712110>
>>> def foo(bar):
... return bar
...
>>> type(foo).__call__(foo, 42)
42
так просто:)
Это конечно может быть перегружен:
>>> class Foo(object):
... def __call__(self):
... return 42
...
>>> f = Foo()
>>> f()
42
Это то, что вы можете поставить "(args)" после и ожидать, что это сработает. Вызываемый обычно является методом или классом. Вызываются методы, создаются экземпляры классов.
для проверки функции или метода класса вызывается или нет, что означает, что мы можем вызвать эту функцию.
Class A:
def __init__(self,val):
self.val = val
def bar(self):
print "bar"
obj = A()
callable(obj.bar)
True
callable(obj.__init___)
False
def foo(): return "s"
callable(foo)
True
callable(foo())
False
Callable-это тип или класс "встроенной функции или метода" с помощью метода вызов
>>> type(callable)
<class 'builtin_function_or_method'>
>>>
пример: печати является вызываемым объектом. Со встроенной функцией __call__ При вызове печати функция, Python создает "объект" в печать типа и вызывает его метод __call__ передача параметров, если таковые имеются.
>>> type(print)
<class 'builtin_function_or_method'>
>>> print.__call__(10)
10
>>> print(10)
10
>>>
спасибо. С уважением, Марис!--5-->