Параметр функции Python: кортеж / список - PullRequest
6 голосов
/ 17 ноября 2010

Моя функция ожидает список или кортеж в качестве параметра. На самом деле все равно, что это, все, что он делает, это передает его другой функции, которая принимает либо список, либо кортеж:

def func(arg): # arg is tuple or list
  another_func(x)
  # do other stuff here

Теперь мне нужно немного изменить функцию, чтобы обработать дополнительный элемент:

def func(arg): #arg is tuple or list
  another_func(x + ['a'])
  # etc

К сожалению, это не сработает: если arg кортеж, я должен сказать x + ('a',).

Очевидно, я могу заставить его работать, приведя аргумент arg к списку. Но это не опрятно.

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

Ответы [ 9 ]

7 голосов
/ 17 ноября 2010

Если another_func просто хочет повторить, вы можете передать ему itertools.chain(x,'a').

4 голосов
/ 17 ноября 2010

Как насчет изменения другой функции для принятия списка параметров вместо?

def func(arg): # arg is tuple or list
  another_func('a', *x)
3 голосов
/ 17 ноября 2010

как насчет:

l = ['a']
l.extend(x)

Редактировать: перечитывая вопрос, я думаю, это больше, чем вы хотите (использование arg и x немного сбивает с толку):

tuple(arg) + ('a',)

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

2 голосов
/ 18 ноября 2010

Если итерируемого достаточно, вы можете использовать itertools.chain, но имейте в виду, что если функция A (первая вызвана), также выполняет итерацию по итерируемому после вызова B, тогда вы могут возникнуть проблемы, так как итерации не могут быть переписаны. В этом случае вы должны выбрать последовательность или использовать iterable.tee, чтобы сделать копию итерируемого:

import itertools as it

def A(iterable):
    iterable, backup = it.tee(iterable)
    res = B(it.chain(iterable, 'a'))
    #do something with res
    for elem in backup:
        #do something with elem

def B(iterable):
   for elem in iterable:
       #do something with elem

Несмотря на то, что itertools.tee не очень эффективен, если B потребляет все или большинство из итерируемого, в этот момент проще просто преобразовать iterable в tuple или list.

2 голосов
/ 17 ноября 2010
def f(*args):
    print args

def a(*args):
    k = list(args)
    k.append('a')
    f(*k)

a(1, 2, 3)

Выход:

(1, 2, 3, 'a')
1 голос
/ 17 ноября 2010

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

from itertools import chain

def func(iterable):
    it = iter(iterable)
    another_func(type(iterable)(chain(it, ('a',))))

def another_func(arg):
    print arg

func((1,2))
# (1, 2, 'a')
func([1,2])
# [1, 2, 'a']
1 голос
/ 17 ноября 2010

Мое предложение:

def foo(t):
    bar(list(t) + [other])

Хотя это не очень эффективно, вам лучше обойти изменчивые вещи, если вы будете, ну, в общем, мутировать их.

0 голосов
/ 18 ноября 2010

Я бы сказал, что Сантьяго Лезица отвечает на вопрос

def foo(t):
    bar(list(t) + [other])

лучший, потому что он самый простой. (нет необходимости импортировать вещи из itertools и использовать гораздо менее читаемые цепные вызовы). Но используйте его, только если вы ожидаете, что он будет маленьким. Если t может быть большим, вы должны использовать одно из других решений.

0 голосов
/ 17 ноября 2010

Ваша функция может принимать любые итерации. Затем используйте itertools.chain, чтобы добавить любую итерацию, которую вы хотите, к итерируемой.

from itertools import chain

def func(iterable):
    another_func(chain(iterable, ('a',)))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...