Почему распаковка аргумента * args дает кортеж? - PullRequest
0 голосов
/ 13 января 2019

В python можно определить функцию, принимающую произвольное количество позиционных аргументов, например:

def f(*args):
    print(args)
f(1, 2, 3)  # (1, 2, 3)

При вызове f(a, b, c) все позиционные аргументы объединяются в кортеж . Это поведение описано в документации на python 2 и 3 , но я не нашел PEP для этого.

PEP 3132 , вводя расширенные итеративные состояния распаковки (first, *middle, last = seqence) в разделе «Принятие», что

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

обсуждалось. Если я напишу оболочку, я также могу захотеть обработать аргументы следующим образом:

def force_type(position, type):
    def wrapper(f):
        def new(*args, **kwargs):
            args = list(args)  # Why?
            args[position] = type(args[position])
            return f(*args, **kwargs)
        return new
    return wrapper

@force_type(1, int)
def func(a, b, c):
    assert isinstance(b, int)

Эта дальнейшая обработка усложняется тем фактом, что args является tuple. Разве обертки просто не использовались на ранних этапах? Если так, то почему это не изменилось в python3 с другими изменениями, нарушающими совместимость (PEP3132 предпочитает простоту обработки, а не согласованность (которая, по крайней мере, похожа на совместимость в изменении, нарушающем совместимость).

Почему функции *args (все еще) a tuple, хотя list позволяет облегчить дальнейшую обработку?

Ответы [ 2 ]

0 голосов
/ 13 января 2019

Я не знаю, была ли это мысль за этим, но эта легкость обработки (даже если создание экземпляра list с данными tuple не так уж сложно) приведет к возможному запутанному поведению.

def fce1(*args):
   fce2(args)
   # some more code using args

def fce2(args):
   args.insert(0, 'other_val')

fce1(1, 2, 3)

Может удивить людей, пишущих код fce1, не понимающих, что args, с которыми они имеют дело позже, - это не то, с чем была вызвана функция.

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

0 голосов
/ 13 января 2019

Почему бы и нет? Суть кортежа в том, что вы не можете изменить его после создания. Это позволяет увеличить скорость выполнения вашего скрипта, и вам на самом деле не нужен список аргументов вашей функции, потому что вам не нужно изменять заданные аргументы функции. Вам нужно добавить или удалить методы для ваших аргументов? В большинстве случаев это было бы нет. Хотите, чтобы ваша программа работала быстрее? Это было бы да. И именно так большинство людей предпочло бы иметь вещи. Из-за этого * args возвращает кортеж, и если вам действительно нужен список, вы можете преобразовать его одной строкой кода!

args = list(args)

Итак, в общем: Это ускоряет выполнение вашей программы. Вы не можете изменить аргументы. Изменить его тип несложно.

...