singledispatch на несколько распакованных аргументов - PullRequest
0 голосов
/ 05 июня 2019

У меня есть fancyfunction, определенный для того, чтобы что-то сделать с одним аргументом. Я украшаю его, чтобы он стал универсальной функцией, чтобы он знал, что делать, если ему дан кортеж.

from functools import singledispatch

@singledispatch
def fancyfunction(arg):
    print(arg)

@fancyfunction.register
def _(arg: tuple):
    for a in arg:
        fancyfunction(a)

Конечно, действительные подписи вызовов для двух указанных выше функций:

fancyfunction(foo)
fancyfunction((foo, bar, ...))

Что я хочу сделать

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

fancyfunction(foo)
fancyfunction(foo, bar, baz, ...)

Для этого мне нужна перегруженная функция для распаковки ее позиционных аргументов:

@singledispatch
def fancyfunction(arg):
    print(arg)

@fancyfunction.register
def _(*arg):
    for a in arg:
        fancyfunction(a)

Конечно, последний фрагмент кода выше не работает. Делаем это:

fancyfunction(foo, bar, baz)

вызовет обобщенную функцию вместо перегруженной функции.

Можно ли заставить singledispatch распознавать, что декорированная функция вызывается с * -формой аргументов? Постскриптум Какое официальное название подписи для вызова?

1 Ответ

1 голос
/ 05 июня 2019

Это немного сбивает с толку - вы говорите, что хотите «сказать» функции, что делать, когда первый аргумент является кортежем, но вы не хотите передавать кортеж (т.е. вам не нужны скобки).похоже, это третий случай - вы хотите передать кортеж, но также иметь возможность передавать несколько аргументов.

может быть что-то в этом духе

from functools import singledispatch

@singledispatch
def fancyfunction(arg, *args):
    print(arg)
    for a in args:
        print(a)

@fancyfunction.register
def _(arg: tuple, *args):
    fancyfunction(*(*arg, *args))

другой вариант - иметь вспомогательную функцию

from functools import singledispatch

def fancyfunction(*args):
    for a in args:
        helperfunction(a)

@singledispatch
def helperfunction(arg):
    print(arg)

@helperfunction.register
def _(arg: tuple):
    for a in arg:
        helperfunction(a)

в обоих случаях при вызове, подобном этому

fancyfunction(1)
fancyfunction(2, 3)
fancyfunction((4,5))
fancyfunction((6, 7) ,8, 9)
fancyfunction((10, 11), (12, 13))
fancyfunction([14, 15])

даст следующий результат

1
2
3
4
5
6
7
8
9
10
11
(12, 13)
[14, 15]
>>>
...