dynamische Variablennamen

Django, Flask, Bottle, WSGI, CGI…
Antworten
Pitwheazle
User
Beiträge: 873
Registriert: Sonntag 19. September 2021, 09:40

Ich hatte dieses Problem schon mal gepostet, bin mit meinem Code so nicht zufrieden.
Ich erzeuge Koordinaten für Winkel in svg. Mal brauche ich die Schenkel, mal die Winkelbögen, meistens beides. Ich erzeuge diese mit der Funktion:

Code: Alles auswählen

def winkel_koo(center_x, center_y, radius, winkel, startwinkel, color = "None", symbol = "", schenkel = 0, scheitel = False, id = 0):
    rad_start = math.radians(startwinkel)
    rad = math.radians(winkel)
    koordinaten = dict(center_x = center_x, center_y = center_y, )
    # das sind die Schenkel:
    if schenkel > 0:
        x1 = center_x - schenkel *  math.cos(rad_start)
        y1 = center_y - schenkel *  math.sin(rad_start) 
        x2 = center_x - schenkel *  math.cos(rad+rad_start) 
        y2 = center_y - schenkel *  math.sin(rad+rad_start)

        if scheitel == True:
            x3 = center_x + schenkel *  math.cos(rad_start)
            y3 = center_y + schenkel *  math.sin(rad_start) 
            x4 = center_x + schenkel *  math.cos(rad+rad_start) 
            y4 = center_y + schenkel *  math.sin(rad+rad_start)
            schenkel_koo = dict(schenkel_1_x = x3, schenkel_1_y = y3, schenkel_2_x = x4, schenkel_2_y = y4)  
        else:
            schenkel_koo = dict(schenkel_1_x = x1, schenkel_1_y = y1, schenkel_2_x = x2, schenkel_2_y = y2)  
        koordinaten.update(schenkel_koo)  
    # das ist der Bogen mit Text:                
    if color:
        start_x = center_x - radius *  math.cos(rad_start)
        start_y = center_y - radius *  math.sin(rad_start) 
        end_x = center_x - radius *  math.cos(rad+rad_start) 
        end_y = center_y - radius *  math.sin(rad+rad_start)
        if winkel <=180:
            largeArcFlag = 0
        else:
            largeArcFlag = 1
        text_x = center_x - radius*3/4 *  math.cos(rad/2+rad_start)
        text_y = center_y - radius/2 *  math.sin(rad/2+rad_start) 

        bogen_koo = dict(bogen_radius = radius, sweep_flag = 1, color = color, symbol = symbol,
            start_bogen_x = start_x, start_bogen_y = start_y, end_bogen_x = end_x, end_bogen_y =  end_y, largeArcFlag = largeArcFlag,
            text_x = text_x, text_y = text_y, )
        koordinaten.update(bogen_koo) 
    return koordinaten
Die Liste mit den Koordinaten für einen 30° Winkel mit Schenkeln sieht dann z.B. so aus:

Code: Alles auswählen

{'center_x': 200, 'center_y': 100, 'schenkel_1_x': 248.2962913144534, 'schenkel_1_y': 87.05904774487395, 'schenkel_2_x': 248.2962913144534, 'schenkel_2_y': 112.94095225512602, 'bogen_radius': 40, 'sweep_flag': 1, 'color': 'lightskyblue', 'symbol': 'β', 'start_bogen_x': 238.63703305156272, 'start_bogen_y': 89.64723819589916, 'end_bogen_x': 238.63703305156275, 'end_bogen_y': 110.35276180410081, 'largeArcFlag': 0, 'text_x': 230.0, 'text_y': 100.0}
Hier sind es 17 Einträge. Ich brauche aber oft 2, 3 oder auch vier Winkel und muss die Werte unterscheiden. Bei vier Winkeln sind das jetzt schon 68 Einträge. Ich möchte diese Gruppen jeweils mit einer ID versehen. Also z.B. "center_x_1", "center_x_2"... Diese dynamische Benennung von Variablen scheint in Python nicht vorgesehen zu sein. Ich habe mir, nach dem letzten Posting, mit "if id == 1 ... elif id ==2 ... geholfen und die Koordinaten einzeln benannt. Das sieht blöd aus. Habt ihr da keine Idee?
Benutzeravatar
pillmuncher
User
Beiträge: 1484
Registriert: Samstag 21. März 2009, 22:59
Wohnort: Pfaffenwinkel

Wenn du anfängst, Variablennamen durchzunummerieren, dann willst du vermutlich eine Liste verwenden. Außerdem wäre mir diese Funktion zu kompliziert. Ich würde versuchen, sie in mehrere Funktionen aufzuteilen. Außerdem gehören center_x und center_y ja irgendwie zusammen. Da könnte man einfach eine Punkt-Klasse definieren:

Code: Alles auswählen

from dataclasses import dataclass
...
@dataclass
Point:
    x: float
    y: float
...
center = Point(x=12.34, y=56.78)
...
... center.x ... center.y ...
In specifications, Murphy's Law supersedes Ohm's.
Benutzeravatar
grubenfox
User
Beiträge: 432
Registriert: Freitag 2. Dezember 2022, 15:49

Pitwheazle hat geschrieben: Sonntag 29. Oktober 2023, 14:03 Die Liste mit den Koordinaten für einen 30° Winkel mit Schenkeln sieht dann z.B. so aus:

Code: Alles auswählen

{'center_x': 200, 'center_y': 100, 'schenkel_1_x': 248.2962913144534, 'schenkel_1_y': 87.05904774487395, 'schenkel_2_x': 248.2962913144534, 'schenkel_2_y': 112.94095225512602, 'bogen_radius': 40, 'sweep_flag': 1, 'color': 'lightskyblue', 'symbol': 'β', 'start_bogen_x': 238.63703305156272, 'start_bogen_y': 89.64723819589916, 'end_bogen_x': 238.63703305156275, 'end_bogen_y': 110.35276180410081, 'largeArcFlag': 0, 'text_x': 230.0, 'text_y': 100.0}
Hier sind es 17 Einträge. Ich brauche aber oft 2, 3 oder auch vier Winkel und muss die Werte unterscheiden. Bei vier Winkeln sind das jetzt schon 68 Einträge. Ich möchte diese Gruppen jeweils mit einer ID versehen. Also z.B. "center_x_1", "center_x_2"... Diese dynamische Benennung von Variablen scheint in Python nicht vorgesehen zu sein. Ich habe mir, nach dem letzten Posting, mit "if id == 1 ... elif id ==2 ... geholfen und die Koordinaten einzeln benannt. Das sieht blöd aus. Habt ihr da keine Idee?
Das ist keine Liste, das ist ein Dictionary bzw. Wörterbuch. Steht ja schon oben im Code wo 'koordinaten' erzeugt wird. Und wenn es dann einen oder mehrere Winkel (bzw. Dicts) gibt, dann (wie schon pillmuncher schreib) einfach eine richtige Liste nehmen.

Bei der Liste kann man dann ein Element nach dem anderen ab- und verarbeiten:

Code: Alles auswählen

for ein_winkel in liste_von_winkeln:
    mache_was_mit_einem_winkel(ein_winkel)
    print('X-Koordinate:', ein_winkel['center_x'])
    print('Y-Koordinate:', ein_winkel['center_y'])
Wenn man statt dem Dictionary für einen Datensatz etwas anderes nimmt (Z.b. eine Klasse), dann müsste möglicherweise bei den Print-Anweisungen der Zugriff auf die einzelnen Daten angepasst werden.
Sirius3
User
Beiträge: 17754
Registriert: Sonntag 21. Oktober 2012, 17:20

@Pitwheazle: was ist ein koo? Benutze keine kryptischen Abkürzungen.
Der String "None" ist keine gültige Farbe. Wahrscheinlich meinst Du den Wert None.
Das Argument id wird gar nicht benutzt.
In wirklich kein hast Du aber zwei Funktionen, eine wo Du den Bogen berechnets und einen mit Schenkel.
Im Fall Schenkel != 0 berechnest Du im prinzip zweimal das selbe, schmeißt aber dann die eine Hälft wieder weg, so dass sich die erste Funktion deutlich vereinfacht:

Code: Alles auswählen

def berechne_schenkel(center_x, center_y, winkel, startwinkel, schenkel, scheitel=False):
    rad_start = math.radians(startwinkel)
    rad = math.radians(winkel)
    if scheitel:
        schenkel *= -1
    return {
        "center_x": center_x,
        "center_y": center_y,
        "schenkel_1_x": center_x - schenkel *  math.cos(rad_start),
        "schenkel_1_y": center_y - schenkel *  math.sin(rad_start),
        "schenkel_2_x": center_x - schenkel *  math.cos(rad+rad_start),
        "schenkel_2_y": center_y - schenkel *  math.sin(rad+rad_start),
    }
Und die andere Funktion:

Code: Alles auswählen

def berechne_bogen(center_x, center_y, radius, winkel, startwinkel, color="black", symbol=""):
    rad_start = math.radians(startwinkel)
    rad = math.radians(winkel)
    return {
        "center_x": center_x,
        "center_y": center_y,
        "bogen_radius": radius,
        "sweep_flag": 1,
        "color": color,
        "symbol": symbol,
        "start_bogen_x": center_x - radius *  math.cos(rad_start),
        "start_bogen_y": center_y - radius *  math.sin(rad_start),
        "end_bogen_x": center_x - radius *  math.cos(rad+rad_start),
        "end_bogen_y": center_y - radius *  math.sin(rad+rad_start),
        "largeArcFlag": int(winkel <= 180),
        "text_x": center_x - radius*3/4 *  math.cos(rad/2+rad_start),
        "text_y": center_y - radius/2 *  math.sin(rad/2+rad_start),
    }
Natürlich wird das nochmal einfacher, wenn man die x- und y-Werte zu einem Tuple zusammenfasst:

Code: Alles auswählen

def berechne_punkt(punkt, winkel, radius, radius2=None):
    if radius2 is None:
        radius2 = radius
    return (
        punkt[0] - radius *  math.cos(math.radians(winkel)),
        punkt[1] - radius2 *  math.sin(math.radians(winkel)),
    )


def berechne_schenkel(center, winkel, startwinkel, schenkel, scheitel=False):
    if scheitel:
        schenkel *= -1
    return {
        "center": center,
        "schenkel_1": berechne_punkt(center, startwinkel, schenkel),
        "schenkel_2": berechne_punkt(center, startwinkel + winkel, schenkel),
    }


def berechne_bogen(center, radius, winkel, startwinkel, color="black", symbol=""):
    return {
        "center": center,
        "bogen_radius": radius,
        "sweep_flag": 1,
        "color": color,
        "symbol": symbol,
        "start_bogen": berechne_punkt(center, startwinkel, radius),
        "end_bogen": berechne_punkt(center, startwinkel + winkel, radius),
        "largeArcFlag": int(winkel <= 180),
        "text_position": berechne_punkt(center, startwinkel + winkel/2, radius*3/4, radius/2),
    }
Wenn Du mehrere Winkel haben möchtest, dann wäre das einfachste, diese Funktion mehrfach aufzurufen.
Pitwheazle
User
Beiträge: 873
Registriert: Sonntag 19. September 2021, 09:40

@sirius3: Wiedermal vielen Dank für die Verbesserungen.
Sirius3 hat geschrieben: Sonntag 29. Oktober 2023, 17:36 Wenn Du mehrere Winkel haben möchtest, dann wäre das einfachste, diese Funktion mehrfach aufzurufen.
...
Das Argument id wird gar nicht benutzt.
... aber dies ist ja gerade mein Problem. Natürlich rufe ich die Funktion mehrmals auf. Wenn ich aber 4 Winkel an svg übergebe, brauchen die auch verschiedenen Keys - daher die ID, die wird noch nicht benutzt weil ich nicht weiß wie.
Sirius3 hat geschrieben: Sonntag 29. Oktober 2023, 17:36 Der String "None" ist keine gültige Farbe. Wahrscheinlich meinst Du den Wert None.
Ich zitiere hier mal aus dem SELFHTML-Wiki:
Beachten Sie:
Wenn Sie die Eigenschaft fill undefiniert lassen, wird das Objekt dann in der Standardfarbe schwarz dargestellt. Dies gilt nicht nur für Kreise und Rechtecke, sondern auch für offene Formen wie Pfade und Polygonzüge.
Wenn Sie das Innere des Objekts nicht darstellen wollen, müssen Sie fill="none" setzen.
Sirius3 hat geschrieben: Sonntag 29. Oktober 2023, 17:36 In wirklich kein hast Du aber zwei Funktionen, eine wo Du den Bogen berechnest und einen mit Schenkel.
Im Fall Schenkel != 0 berechnest Du im prinzip zweimal das selbe, schmeißt aber dann die eine Hälft wieder weg, so dass sich die erste Funktion deutlich vereinfacht:
Klar, das sind eigentlich sogar drei Funktionen. Es gibt Aufgaben, in denen ich einen Winkel mit Schenkel und Bogen brauche, dann übergebe ich die Länge des Bogens und den Text im Winkel Und bekomme 17 Einträge im Dict):
Bild
Hier erzeuge ich mit "scheitel = True" auch gleich die Schenkel des Scheitelwinkels und setze dann vom Scheitelwinkel nur den Bogen ein (erzeugt einmal 17 Einträge und einmal nur noch 11:
Bild
Hier erzeuge ich ein Polygon und brauche nur vier Winkelbogen (zum Polygon kommen nur 4 mal 11 Einträge):
Bild
Und hier will ich zufällig Winkel mal links, rechts, oben oder unten an den Ecken des Dreiecks:
Bild
Benutzeravatar
grubenfox
User
Beiträge: 432
Registriert: Freitag 2. Dezember 2022, 15:49

wie/womit werden denn die svg-Daten bzw. -Dateien erzeugt?
Sirius3
User
Beiträge: 17754
Registriert: Sonntag 21. Oktober 2012, 17:20

@grubenfox: das ist ein ganz normales Django-Template.
@Pitwheazle: und die einzelnen Winkel-Wörterbücher packst Du einfach in ein weiteres Wörterbuch, oder eine Liste und greifst dann in Deinem Template auf über eine weitere Ebene drauf zu.
Antworten