2013-06-21 3 views
1

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

Другими словами, я подозреваю, , что я делаю неправильно, но я не могу видеть, как сделать это право.

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

То, что я в конечном итоге это STH так:

def myFunction(alpha, beta, gamma, zeta, alphaList, betaList, gammaList, zetaList): 
    <some operations> 
    myFunction(alpha, beta, modGamma, zeta, modAlphaList, betaList, gammaList, modZetaList) 

... и я хочу, чтобы увидеть изменения, которые я сделал на исходных переменных (в CI просто передать ссылку, но я слышал, что в Python это всегда копия?).

Извините, если noob, я не знаю, как сформулировать этот вопрос, чтобы найти соответствующие ответы.

+1

Не могли бы вы привести конкретный пример? –

+0

В python это _never_ a copy –

+0

Этот ответ поможет вам понять, как ведут себя параметры относительно ссылки -> http://stackoverflow.com/a/986145/15931 –

ответ

0

Вы должны положить myFunction в класс. Настройте класс с соответствующими атрибутами и вызовите соответствующие функции. Состояние тогда хорошо содержится в классе.

0

Вы можете перейти в словарь и вернуть новый словарь. Или поместите свой метод в класс и получите альфа, бета и т. Д. Атрибуты.

2

Вы можете обернуть все параметры в классе, например:

class FooParameters: 
    alpha = 1.0 
    beta = 1.0 
    gamma = 1.0 
    zeta = 1.0 
    alphaList = [] 
    betaList = [] 
    gammaList = [] 
    zetaList = [] 

, а затем ваша функция принимает один экземпляр параметра:

def myFunction(params): 
    omega = params.alpha * params.beta + exp(params.gamma) 
    # more magic... 

призывающую как:

testParams = FooParameters() 
testParams.gamma = 2.3 
myFunction(testParams) 
print params.zetaList 

Поскольку экземпляр params передается ссылка, изменения в функции сохраняются.

1

Я не знаю, откуда у вас возникла мысль, что Python копирует значения при переходе в функцию. То есть совсем нет true.

Наоборот: каждый параметр в функции является дополнительным именем, относящимся к исходному объекту. Если вы измените значение этого объекта в некотором роде - например, если это список и вы меняете один из его членов, тогда оригинал также увидит это изменение. Но если вы переустановите имя на что-то другое - скажем, сделав alpha = my_completely_new_value - тогда оригинал остается неизменным.

+0

Хотя технически правильно говорить * «каждый параметр в функция - это дополнительное имя, относящееся к исходному объекту «*, поведение для неизменяемых типов - это не тот, который кто-то ожидал бы для переменной, переданной« по ссылке »(как в C). Если параметр «int» изменяется внутри функции (например, делая «alpha + = 1'), исходная переменная не будет затронута. –

+0

Технически, python (как и любой другой основной язык программирования, по крайней мере по умолчанию) использует семантику «pass by value». откуда он получил эту идею. И да, это сбивает с толку. – Elazar

2

Это обычно используется, например, в matplotlib.Они проходят длинный список аргументов, с помощью * или **, как: Вызов функции

def function(*args, **kwargs): 
    do something 

:

function(1,2,3,4,5, a=1, b=2, b=3) 

Здесь 1,2,3,4,5 пойдет args и a=1, b=2, c=3 пойдет kwargs, как словарь. Чтобы они подошли к вашей функции:

args = [1,2,3,4,5] 
kwargs = {a:1, b:2, c:3} 

И вы можете обращаться с ними так, как вы хотите.

1

Вы можете захотеть что-то похожее на это:

def myFunction(*args): 
    var_names = ['alpha','beta','gamma','zeta'] 
    locals().update(zip(var_names,args)) 
    myFunction(alpha,beta,gamma,zeta) 

Однако это «часто» не будет работать. Я предлагаю введение другое пространство имен:

from collections import OrderedDict 
def myFunction(*args): 
    var_names = ['alpha','beta','gamma','zeta'] 
    vars = OrderedDict(zip(var_names,args)) 

    #get them all via vars[var_name] 

    myFunction(*vars.values()) #since we used an orderedDict we can simply do *.values() 
1

вы можете захватить не-modfied значения в затворе:

def myFunction(alpha, beta, gamma, zeta, alphaList, betaList, gammaList, zetaList): 
    def myInner(g=gamma, al, zl): 
     <some operations> 
     myInner(modGamma, modAlphaList, modZetaList) 
    myInner(al=alphaList, zl=zetaList) 

(BTW, это почти единственный способ, чтобы написать действительно рекурсивную функцию в Python.)

Смежные вопросы