Seite 1 von 1

Dynamisch Funktionsargumente bestimmen

Verfasst: Mittwoch 21. Dezember 2011, 16:19
von mzh
Liebes Forum
Ein Beispiel: ich habe eine Funktion mit drei Argumenten: y=f(x1, x2, x3). Wenn ich zwei Argumente, x_i und x_j, als Parameter a und b annehme, dann kann ich y gegen das dritte Argument x_k in 2D plotten.
Ich möchte also über eine Liste von möglichen x_k Werten die Funktion ausrechnen:

Code: Alles auswählen

X_k = [x_k1, x_k2, ..., x_kN]
for x_k in X_k:
    f(a, b, x_k)
Hier ist allerdings ein Problem, nämlich dass ich annehme, a priori zu wissen, dass x_k das letzte Argument ist, und deshalb f(a, b, x_k) schreiben kann. Wenn ich allerdings, x_i und x_k als Parameter a und c auffasse, dann müsste ich ja einen weiteren Funktionsaufruf einbauen:

Code: Alles auswählen

if type(X_i) == list:
    for x_i in X_i:
        f(x_i, b, c)
if type(X_j) == list:
    for x_j in X_j:
        f(a, x_j, c)
if type(X_k) == list:
    for x_k in X_k:
        f(a, b, x_k)
Der Ursprung dieser Frage liegt darin, dass die Funktion über ein Webinterface zugänglich gemacht wird, in dem die Parameter gesetzt werden können und in dem definiert wird, welches Argument als Variable funktionieren soll. Hoffe, dass man einigermassen verstehen kann, worum es mir geht.
Kann man das nicht besser lösen? Danke für Hinweise.

Re: Dynamisch Funktionsargumente bestimmen

Verfasst: Mittwoch 21. Dezember 2011, 16:37
von BlackJack
Ungetestet:

Code: Alles auswählen

a, b, c = X_i, X_j, X_k
variable_argument = None
for argument, values in zip('abc', [X_i, X_j, X_k]):
    if isinstance(values, list):
        variable_argument = argument
        break

if variable_argument is None:
    raise TypeError('no variable list given')

arguments = dict(a=a, b=b, c=c)
for value in values:
    arguments[variable_argument] = value
    f(**arguments)

Re: Dynamisch Funktionsargumente bestimmen

Verfasst: Mittwoch 21. Dezember 2011, 17:54
von LivingOn
Hier eine weitere Alternative. Um es einfach zu halten, habe ich mal andere Variablenamen verwendet:

Code: Alles auswählen

def show(a,b,c):
    print(a,b,c)

def doit(*args):
    variable = (v for v in "bc")
    arguments = {}
    for i in args:
        if isinstance(i, list):
            arguments['a'] = i
        else:
            arguments[variable.next()] = i
    show(**arguments)

doit([1,2,3],2,3)    
doit(1,[1,2,3],3)    
doit(1,2,[1,2,3])    

>>> ([1, 2, 3], 2, 3)
>>> ([1, 2, 3], 1, 3)
>>> ([1, 2, 3], 1, 2)

Re: Dynamisch Funktionsargumente bestimmen

Verfasst: Mittwoch 21. Dezember 2011, 18:13
von mzh
@ BlackJack: Danke für den Hinweis.

Ich versuche mein Minimalbeispiel besser an der realen Aufgabe anzupassen.
Eine HTML Form ist gegeben:

Code: Alles auswählen

<form action="thermo.cgi">
<!--n-->
<input type="text" name="particles">
<input type="radio" name="thermo" value="particles">

<!--T-->
<input type="text" name="temperature">
<input type="radio" name="thermo" value="temperature">

<!--V-->
<input type="text" name="volume">
<input type="radio" name="thermo" value="volume">

<input type="submit">
</form>
Das CGI Skript plottet also in der leicht umgestellten idealen Gasgleichung, p(n, V, T) = 1/V*nRT, den Druck p gegen entweder V, n oder T.

Das CGI Skript könnte jetzt ungefähr so aussehen:

Code: Alles auswählen

# The independent variable, its value and +/- 20% are obtained.
x_lbl = form['thermo'].value
x_val = form[x_lbl].value
x_rng = get_x_range_around(x_val)

# Get the values for the parameters
n = form['particles'].value
temperature = form['temperature'].value
volume = form['volume'].value

# Now, depending on x_lbl, a different function has to be called.
if x_lbl == 'particles':
    for x in x_rng:
        print x, ideal_gas(x, temperature, volume)

if x_lbl == 'temperature':
    for x in x_rng:
        print x, ideal_gas(n, x, volume)

if x_lbl == 'volume':
    for x in x_rng:
        print x, ideal_gas(n, temperature, x)
Die willkürliche Definition der ideal_gas Funktion

Code: Alles auswählen

def ideal_gas(n, t, v):
    return 1.0/v*n*R*t

Re: Dynamisch Funktionsargumente bestimmen

Verfasst: Mittwoch 21. Dezember 2011, 18:34
von BlackJack
@LivingOn: ``variable = (v for v in "bc")`` hätte ich ja als ``variable = iter('bc')`` geschrieben. :-)

Re: Dynamisch Funktionsargumente bestimmen

Verfasst: Mittwoch 21. Dezember 2011, 19:40
von Hyperion
@mzh: Den unteren Teil könnte man so ein wenig kompakter schreiben:

Code: Alles auswählen

for x in x_rng:
    if x_lbl == 'particles':
        print x, ideal_gas(x, temperature, volume)
    elif x_lbl == 'temperature':
        print x, ideal_gas(n, x, volume)
    elif x_lbl == 'volume':
        print x, ideal_gas(n, temperature, x)
Da Deine innere `for x`-Schleife ja in jeder Bedingung vorkommt, kann man die doch nach außen stellen.

Re: Dynamisch Funktionsargumente bestimmen

Verfasst: Mittwoch 21. Dezember 2011, 19:53
von mzh
@hyperion, ja sicher, trotzdem, frage mich wie ich die 3-ssig if's umgehen kann.