Przepraszam, jeśli na moje pytanie jest już odpowiedź, przeszukałem przepełnienie stosu stosu, ale nie znalazłem nic, czego mógłbym użyć.

Uważam, jak w tej chwili tworzyć zajęcia i skonstruowałem zajęcia dotyczące jawnych metod Runge-Kutty 1-4. Nazwy zajęć są "rk_1", "rk_2", "rk_3" i "rk_4". Aby przetestować mój kod, postanowiłem rozwiązać równanie różnicowe legendy, które również stworzyłem klasę o nazwie "Legendre".

Teraz chciałem rozwiązać problem, więc napisałem funkcję, która korzysta z konkretnego schematu RK i rozwiązuje problem legendry. Chciałem to zrobić dla każdego z moich schematów RK, więc napisałem tę samą funkcję 4 razy

def solve_Legendre_1(p,Tmax,init,dt=0.001):

    f      = Legendre(p)
    solver = RK_1(init,f)

    while solver.now() < Tmax:
        solver(dt)

    return solver.state()

def solve_Legendre_2(p,Tmax,init,dt=0.001):

    f      = Legendre(p)
    solver = RK_2(init,f)

    while solver.now() < Tmax:
        solver(dt)

    return solver.state()

def solve_Legendre_3(p,Tmax,init,dt=0.001):

    f      = Legendre(p)
    solver = RK_3(init,f)

    while solver.now() < Tmax:
        solver(dt)

    return solver.state()

def solve_Legendre_4(p,Tmax,init,dt=0.001):

    f      = Legendre(p)
    solver = RK_4(init,f)

    while solver.now() < Tmax:
        solver(dt)

    return solver.state()

Jednak zdałem sobie sprawę, że musi to zrobić łatwiej. Więc myślałem, że mogę użyć pętli i str.format (), aby zmienić nazwę funkcji i uzyskać, aby wziąć je w odpowiednim schemacie RK, coś takiego

for j in range(4):
    def solve_Legendre_%s(p,Tmax,init,dt=0.001) % (j+1):

        f      = Legendre(p)
        solver = RK_%s(init,f) % (j+1)

        while solver.now() < Tmax:
            solver(dt)

        return solver.state()

Ale oczywiście to nie zadziała. Czy ktoś wie, jak powinienem do tego podejść?

Dzięki za pomoc.

1
mattos 26 czerwiec 2017, 11:29

4 odpowiedzi

Najlepsza odpowiedź

Możesz po prostu przekazać funkcję RK_n() jako parametr, aby uniknąć powielania drugiej funkcji:

def solve_Legendre(p,Tmax,init,dt=0.001, RK=RK_1):

    f      = Legendre(p)
    solver = RK(init,f)

    while solver.now() < Tmax:
        solver(dt)

    return solver.state()

A jeśli chcesz, możesz wiązać ten ostatni parametr z góry:

import functools
solve_Legendre_1 = functools.partial(solve_Legendre, RK=RK_1)
solve_Legendre_2 = functools.partial(solve_Legendre, RK=RK_2)
...
7
Duncan 26 czerwiec 2017, 08:35

Powinieneś dodać parametr do funkcji. Więc masz jedną funkcję, aby rozwiązać wszystkie swoje schematy:

def solve_Legendre(p,Tmax,init,dt=0.001, RK):

    f      = Legendre(p)
    solver = RK(init,f)

    while solver.now() < Tmax:
        solver(dt)

    return solver.state()

Jeśli chcesz, możesz ustawić wartość domyślną dla RK:

def solve_Legendre(p,Tmax,init,dt=0.001, RK=RK_1):
1
Nab Ilovich 26 czerwiec 2017, 08:39

Twoje funkcje różnią się tylko przez funkcję RK_X, którą możesz po prostu przejść przez dodatkową zmienną. Spowoduje to minimalizowanie redundancji kodu:

def solve_Legendre(RK_func, p,Tmax,init,dt=0.001):

    f      = Legendre(p)
    solver = RK_func(init,f)

    while solver.now() < Tmax:
        solver(dt)

    return solver.state()

Teraz do twojego pytania - możesz zapytać na to Globals. Funkcja Global () Zwróci mapę z każdym obiektem zdefiniowanym w globalnym zakresie kluczowanym przez identyfikator. Możesz więc napisać (używając mojej poprzedniej funkcji):

for j in range(4):
    globals()['solve_Legendre_%d' % (j + 1)] = lambda *args, **kw_args: solve_Legendre(globals()['RK_%d' % (j + 1)], *args, **kw_args)
1
Radosław Cybulski 26 czerwiec 2017, 08:38

Możesz użyć argumentów nie tylko do podania "zwykłych" rzeczy, takich jak cyfry, listy lub ciągi do funkcji, można również użyć funkcji jako parametrów:

>>> def test1():
    print(1)

>>> def test2():
    print(2)

>>> def solve_with_func(funcname):
    funcname()

>>> solve_with_func(test1)
1
>>> solve_with_func(test2)
2

W ten sposób można użyć tej samej logiki w solve_with_func i po prostu wymieniaj funkcję, która jest wykonywana.

Można oczywiście rozszerzyć się na listy funkcji:

>>> def execute_all(funclist):
    for f in funclist:
        f()


>>> execute_all([test1, test2])
1
2
1
Christian König 26 czerwiec 2017, 08:36