Как функция может вернуть динамическое значение, которое зависит от количества получателей в Python? - PullRequest
2 голосов
/ 29 ноября 2011

Я пытался сделать «странную» (но полезную в моем случае) функцию, которая может возвращать динамический список, длина которого зависит от количества получателя.

Например:

f () возвращает динамический список None, поэтому я могу сделать следующее:

a = f()  => a = None
a, b = f()  => a=b= None
(a, b) = f() => a=b= None
(a, b, c, d, e, f) = f()  => a=b=c=d=e=f= None

Я думаю, что это может быть сделано с помощью генератора или итератора, но я был заблокирован, как получить сумму получателя,Возможно я был не в том направлении.Вы бы посоветовали мне несколько советов?

Любая помощь будет оценена.

Большое спасибо,

Tiezhen

Ответы [ 6 ]

3 голосов
/ 29 ноября 2011

Это невозможно в Python. Функция на правом сайте не знает контекста, в котором она была вызвана. Правый сайт оценивается до того, как произойдет любое связывание имен.

1 голос
/ 29 ноября 2011

К сожалению, Python распаковывает возвращенные кортежи, используя подход Pythonic «Проще просить прощения, чем разрешения». То есть, если у вас есть заявление:

a,b,c = f()

За кулисами, он делает что-то вроде:

try:
    a = returned[0]
    b = returned[1]
    c = returned[2]
except IndexError:
    raise ValueError('need more than k values to unpack')

try:
    _ = returned[4]
except IndexError:
    pass
else:
    raise ValueError('too many values to unpack')

Так что он динамически определяет количество возвращаемых значений. К сожалению, это не позволяет нам быть умными и создавать новый тип для обработки возвращаемых переменных:

class VariableReturn(object):
    def __getitem__(self, index):
        return ...

В Python 3 вы можете делать то, что просите, но нагрузка на вызывающего, а не на вызываемую функцию. Функция должна всегда возвращать одно и то же количество результатов, но остальные результаты будут отлавливаться с помощью расширенной распаковки кортежей , как показано в этого вопроса StackOverflow .

Используя этот подход, вы можете вернуть столько результатов, сколько захотите, но вам нужно всегда возвращать как минимум столько, сколько вам нужно в максимальном случае. Остальные упаковываются в завершающий кортеж.

a,*others = f()
a,b,*others = f()
a,b,c,*others = f()
1 голос
/ 29 ноября 2011

Если вы не возражаете против использования Python 3, вы можете игнорировать то, что вам не нужно, например:

a, b, c, d, *_ = (x for x in range(100))
0 голосов
/ 29 ноября 2011

довольно не приятно, но, возможно, это поможет вам:

def f(x):
    for i in x:
        globals()[i] = None

f(['a','b','c'])
0 голосов
/ 29 ноября 2011

Не может быть сделано.

Функции в Python возвращают только одно значение.Хотя иногда это может выглядеть как больше, это все равно всего лишь одно значение: кортеж.Множественное назначение - это процесс распаковка кортежа .

Ваш вопрос может быть переформулирован: можем ли мы создать объект, который действует как кортеж различной длины, в зависимости от того, сколько значений необходимо распаковать?И это просто не доступно в качестве опции.

Вероятно, самое близкое, что я могу придумать, это использовать генератор и получить желаемое количество предметов с помощью itertools.islice:

a = itertools.count()
x, y, z = itertools.islice(a, 3) # 0, 1, 2
u, v = itertools.islice(a, 2)    # 3, 4

Но это довольно далеко от того, на что мы надеялись.1013 *

0 голосов
/ 29 ноября 2011

Попробуйте это:

def f(n):
    return (None, ) * n

Например:

a, b, c = f(3)

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

...