@foo
def bar(): ...
Этот синтаксис просто сахар для этого:
def bar(): ...
bar = foo(bar)
Итак, это:
@pc.on('datachannel')
def on_datachannel(channel): ...
то же самое, что:
def on_datachannel(channel): ...
on_datachannel = pc.on('datachannel')(on_datachannel)
pc
- это некоторый объект, pc.on
- это метод на нем, pc.on('datachannel')
вызывает его и возвращает функцию, pc.on('datachannel')(on_datachannel)
вызывает эту возвращенную функцию, передавая ей функцию on_datachannel
.
Реализация of pc.on
выглядит примерно так:
class PC:
def on(self, event):
...
def wrapper(fn):
...
def inner_wrapper(*args, **kwargs):
...
fn(*args, **kwargs)
return inner_wrapper
return wrapper
pc = PC()
Вся эта внутренняя часть полностью является обычным декоратором, принимающим аргументы. То, что он определен в классе, не имеет для него никакого значения.