Python: найкращий спосіб вирішити функції з довгим списком аргументів?

Я знайшов різні детальні пояснення про те, як передавати довгі списки аргументів у функцію, але я все ще сумніваюся, що це правильний спосіб зробити це.

Іншими словами, я підозрюю , що я роблю це неправильно, але я не можу бачити, як це зробити праворуч .

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

Що я закінчу з цим виглядає так:

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

... і я хочу побачити зміни, які я зробив на оригінальних змінних (в C я просто передам посилання, але я чую, що в Python це завжди копія?).

Вибачте, якщо ноуб, я не знаю, як фразу це питання, щоб я міг знайти відповідні відповіді.

1
Ця відповідь допоможе вам зрозуміти, як поводяться параметри відносно посилання -> stackoverflow.com/a/986145/15931
додано Автор E.Z., джерело
У python це ніколи копію
додано Автор John La Rooy, джерело
Не могли б ви навести конкретний приклад?
додано Автор Markus Unterwaditzer, джерело

7 Відповіді

Наприклад, це звичайно використовується в 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}

І ви можете ставитися до них так, як захочете.

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 передано посиланням , зміни в функції зберігаються.

2
додано

Я не знаю, де ви зрозуміли, що Python копіює значення при переході до функції. Це дійсно не зовсім .

Навпаки: кожен параметр у функції - це додаткове ім'я, що стосується оригінального об'єкта. Якщо ви змінюєте значення цього об'єкта в певному сенсі - наприклад, якщо це список, і ви змінюєте один з його учасників, - тоді оригінал також побачить цю зміну. Але якщо ви переможете назву на щось інше - скажіть, виконавши alpha = my_completely_new_value - тоді оригінал залишається незмінним.

1
додано
Хоча технічно правильно сказати, що "кожен параметр у функції - це додаткове ім'я, що відноситься до оригінального об'єкта" , поведінка незмінних типів - це не той, кого очікує бути змінною " за посиланням "(як у С). Якщо параметр int змінюється в межах функції (скажімо, виконавши alpha + = 1 ), оригінальна змінна не буде впливати.
додано Автор E.Z., джерело
Технічно пітон (як і будь-яка інша велика мова програмування, за замовчуванням принаймні) використовує семантику "pass by value". от кого він отримав цю ідею. І так, це незрозуміло.
додано Автор Elazar, джерело

Ви можете спокусити щось подібне до цього:

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
додано

ви можете захопити не модифіковані значення в закритті:

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

(До речі, це єдиний спосіб написати справжню рекурсивну функцію в Python.)

1
додано

Ви можете передати в словник і повернути новий словник. Або покладіть свій метод у клас і маєте атрибути alpha, beta та ін.

0
додано

Ви повинні поставити myFunction у клас. Налаштуйте клас з відповідними атрибутами та викликайте відповідні функції. Держава тоді добре міститься в класі.

0
додано
ІТ КПІ - Python
ІТ КПІ - Python
625 учасників

Канал обговорень про всякі штуки зі світу пайтону. Прохання: 0. мати повагу одне до одного; 1. не матюкатися в сторону людей; 2. не захламляти тред повідомленнями по одному слову;