Параметр функции Python: кортеж/список
моя функция ожидает список или кортеж в качестве параметра. Его не волнует, что это все она делает, это передать его в другую функцию, которая принимает список или кортеж:
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 ответов
Как насчет изменения другой функции, чтобы принять список параметров вместо этого ?
def func(arg): # arg is tuple or list
another_func('a', *x)
как насчет:
l = ['a']
l.extend(x)
изменить:
Перечитывая вопрос, я думаю, это больше того, что вы хотите (использование arg
и x
было немного запутанно):
tuple(arg) + ('a',)
как говорили другие, это, вероятно, не самый эффективный способ, но это очень ясно. Если ваши кортежи / списки малы, я мог бы использовать это над менее четкими решениями, поскольку производительность будет незначительной. Если ваши списки велики, используйте более эффективные решения.
def f(*args):
print args
def a(*args):
k = list(args)
k.append('a')
f(*k)
a(1, 2, 3)
выход:
(1, 2, 3, 'a')
если достаточно iterable, вы можете использовать itertools.chain
, но имейте в виду, что если функция A
(первый вызываемый), также выполняет итерацию по iterable после вызова B
, тогда у вас могут возникнуть проблемы, так как iterables нельзя перемотать. В этом случае вы должны выбрать последовательность или использовать iterable.tee
чтобы сделать копию iterable:
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, в этот момент проще просто преобразовать iterable
до tuple
или list
.
мое предложение:
def foo(t):
bar(list(t) + [other])
Это не очень эффективно, хотя, вам было бы лучше передавать изменчивые вещи, если вы собираетесь, ну, мутировать их.
вы можете использовать тип iterable, переданный первой функции, чтобы построить то, что вы передаете второй:
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']
пусть ваша функция принимает любую итерацию. Тогда используйте itertools.chain
чтобы добавить любую последовательность, которую вы хотите к iterable.
from itertools import chain
def func(iterable):
another_func(chain(iterable, ('a',)))
Я бы сказал, что ответ Сантьяго Lezica делать
def foo(t):
bar(list(t) + [other])
является лучшим, потому что это самый простой. (нет необходимости импортировать материал itertools и использовать гораздо менее читаемые цепные вызовы). Но используйте его, только если вы ожидаете, что t будет маленьким. Если t может быть большим, вы должны использовать одно из других решений.