Seite 1 von 1
Datenstruktur Variable mit 2 Namen.
Verfasst: Donnerstag 16. April 2020, 12:27
von rob87
Hallo,
ich bekommen von einem Event (raspbian) eine
ID 1-5/300-307 usw und ein
Value.
Also zum Bespiel ID 305 Value 1.0 oder ID 4 und -31566.
Jetzt würde ich gerne ein Stück Code entwickeln wo ich die Definition nur einmal machen muss UND die die werte mittels Punktoperator auslesen kann:
Code: Alles auswählen
for event in gamepad.read_loop():
#Input speichern
if event.code in HardwareID: # ID 305 / 4
HardwareObj.HardwareID[event.code] = event.value #value 1.0 / -31566
#Output
if HardwareObj.taste = 1.0 #ID 305
LED = true
else
LED = false
PWMServo = formatint2PWM(HardwareObj.poti)
Achtung Code kann syntatische Fehler enthalten!
Ich habe viel über Tupel, Mengen, Dict und Klassen gelesen, allerdings fehlt mir die Verknüpfung wie ich nur einmal die ID (305) dem Attribut (taste) zuweisen kann.
Das einzige was mir eingefallen ist, ist ein dict mit ID und ein Klasse anlegen. Allerdings muss ich ja dann den Atributnamen 2x schreiben. Oder ein Switch Case Anweisung mit der ID als Statement.
Habe Ihr noch eine Idee?
Re: Datenstruktur Variable mit 2 Namen.
Verfasst: Donnerstag 16. April 2020, 13:14
von __blackjack__
@rob87: Falls sich die Daten nach dem erstellen nicht ändern würde ich einen Typ mit `collections.namedtuple()` erstellen. Sonst eine Klasse. Ohne ein Wörterbuch. Wozu soll das gut sein?
Re: Datenstruktur Variable mit 2 Namen.
Verfasst: Freitag 17. April 2020, 06:16
von rob87
Hi,
die Name und ID's ändern sich nicht die Value schon...Aber ich stelle gerade fest das meine Frage eine unschärfe aufweist. Richtig müsste die Frage lauten:
Wie kann ich Werte die Eventbasiert(von einem Controller) mit ID-Zuordnung und in einem zyklischen Script mit Namenszuordnung organisieren?
Ziel des Projekts: Ich will mittels Controller Analogstick (Eingabe Event) einen Motor(zyklischkontinuierliche Ausgabe) steuern.
Re: Datenstruktur Variable mit 2 Namen.
Verfasst: Freitag 17. April 2020, 15:09
von __blackjack__
@rob87: Wie verändert sich denn der Wert? Ich verstehe nicht wirklich was Du erreichen willst. In einem Wert zwei Werte zusammenfassen die dann mittels Punktoperator angefragt werden ist ein Objekt. Entweder ein unveränderliches, dann kann man `collections.namedtuple()` verwenden um den Datentyp dafür zu erstellen. Oder man schreibt eben eine Klasse mit den beiden Attributen.
Zum Code aus dem ersten Beitrag: Der wirft mehr fragen auf als er beantwortet. Zum Beispiel ist der syntaktisch nicht korrekt, kommt also nicht einmal am Compiler vorbei. Das ist schon mal kein gutes Zeichen für ein Beispiel wenn man das erst einmal ratend was denn gemeint sein könnte, repariert werden muss.
Namen werden in Python klein_mit_unterstrichen geschrieben. Ausnahmen sind Konstanten (KOMPLETT_GROSS) und Klassen (MixedCase).
Was ist denn der Geschmack mit dem Wert 1.0? SCNR

Man sollte sich für Deutsch oder Englisch entscheiden. In der Regel Englisch, weil die Schlüsselworte von Python und alle anderen Bibliotheken auch Englisch verwenden.
Kann es sein, dass Du eigentlich ein Wörterbuch suchst das IDs auf Attributnamen abbildet und die `setattr()`-Funktion?
Das ``if``/``else`` ist überflüssig wenn man einen Wahrheitswert zuweisen will der auf dem Ergebnis der ``if``-Bedingung beruht. Die Bedingung selbst wird doch schon zu einem Wahrheitswert ausgewertet.
Ungetestet:
Code: Alles auswählen
event_code_to_attribute_name = {305: "key", 4: "poti"}
...
for event in gamepad.read_loop():
attribute_name = event_code_to_attribute_name.get(event.code)
if attribute_name:
setattr(hardware_object, attribute_name, event.value)
led = hardware_object.key == 1
servo_pwm = format_int2pwm(hardware_object.poti)
Wobei `hardware_object` ein ziemlich schlechter Name ist IMHO.
Re: Datenstruktur Variable mit 2 Namen.
Verfasst: Freitag 17. September 2021, 20:48
von rob87
Hallo, lang ists her doch das Projekt ist nicht tot.
Zur Nutzung von async bin ich jetzt von Python2.7 auf python3.8 gewechselt. Leider funktioniert die Klasseninitialisierung nicht mehr, bzw. der Compiler meckert
AttributeError: type object 'Stick' has no attribute 'X'
.
In 2.7 funktioniert folgender code (gekürzt)
Code: Alles auswählen
class Stickachse:
def __init__(self, B0100 = 0.0, B100100 = 0.0, B1000 = 0.0):
pass
def input(self,val):
global B0100,B100100,B1000
self.B100100=val
class Stick:
def __init__(self, X = Stickachse,Y = Stickachse, Button = 0.0):
pass
linker_stick = Stick
rechter_stick = Stick
for i in range(0,5):
linker_stick.X.input(i)
print(linker_stick.X.B100100)
Wo liegt mein fehler?
Da ich mit dem Code bereits einen Servo gesteuert habe bin ich relativ ratlos...
Re: Datenstruktur Variable mit 2 Namen.
Verfasst: Freitag 17. September 2021, 20:55
von __blackjack__
@rob87: Nein der Code funktioniert nicht in Python 2.7. (Und schon wieder ``global``…)
Re: Datenstruktur Variable mit 2 Namen.
Verfasst: Samstag 18. September 2021, 18:15
von rob87
__blackjack__ hat geschrieben: Freitag 17. September 2021, 20:55
@rob87: Nein der Code funktioniert nicht in Python 2.7. (Und schon wieder ``global``…)
Magst du mir vll. verraten wie ich die Klassen definieren muss damit der folgende Code Funktioniert?
Code: Alles auswählen
...
for i in range(0,5):
linker_stick.X.input(i)
print(linker_stick.X.B100100)
...
Re: Datenstruktur Variable mit 2 Namen.
Verfasst: Samstag 18. September 2021, 18:37
von rogerb
@rob87,
dies definiert eine Klasse mit dem Namen "A"
jetzt sind "A" und "a" Namen für die selbe zuvor definierte Klasse
jetzt ist "a" eine Instanz der Klasse mit dem Namen "A".
Das sollte den Fehler in deinem Programm erklären. Es gibt da noch einige andere Merkwürdigkeiten, aber ich verstehe nicht ganz was du da eigentlich erreichen willst.
Re: Datenstruktur Variable mit 2 Namen.
Verfasst: Samstag 18. September 2021, 19:24
von sparrow
@rob87: Deine Codebeispiele und deine Erklärung helfen leider nicht zu verstehen, was du eigentlich machen möchtest.
Vielleicht Ist daher das, was du für die Lösung hälst, eigentlich nicht korrekt und du solltest mal das grundlegende Problem beschreiben.
Re: Datenstruktur Variable mit 2 Namen.
Verfasst: Samstag 18. September 2021, 20:09
von rob87
sparrow hat geschrieben: Samstag 18. September 2021, 19:24
@rob87: Deine Codebeispiele und deine Erklärung helfen leider nicht zu verstehen, was du eigentlich machen möchtest.
Vielleicht Ist daher das, was du für die Lösung hälst, eigentlich nicht korrekt und du solltest mal das grundlegende Problem beschreiben.
Naja wie ich Eingang schon geschrieben habe bekommen ich
ID und
Value als aktuellen Zustand eines
Xbox Controllers über Bluetooth (
events).
Jetzt will ich im weiteren Programm aber nicht mit der
ID aus einer List oder einem dict Arbeiten sondern mit Objektvariablen arbeiten.
So, der Controller hat
2 Sticks/Knüppel oder wie auch immer man es nennen möchte. Jeder
Stick hat
2 (Stick)achsen (Horizintale Richtung - X /Vertikale Richtung - Y) und
einen Button.
Diese Stickachse wird in
3 Bereiche unterteilt: Links mit mitte (
B1000), Links bis rechts(
B100100) und Mitte bis rechts (
B0100)
Wenn ich also wissen will zu wie viel Prozent des
Linken
Sticks der Auschlag in
X Richtung auf der
rechten Seite ist, frage ich im Programm die Variable
Controller.LS.X.B0100 ab.
Auch muss ich der Umrechnungsfunktion den Eventwert zuschieben.
Wenn das Programm anhand der ID erkennt (if /elif -Funktion), ah der Eventinput kommt von der
X Achse
Linker Stick also rufe ich folgende Funktion auf:
Controller.LS.X.input(Eventvalue) -> Diese Funktion berechnet nun die Stellung in einem Bereich von -1.0(ganz links) und 1.0(ganz rechts) und beschreibt die drei Variablen B1000; B100100; B0100 entsprechend.
@rogerb du hast recht, ich habe die Klammern vergessen.
Ich weiß halt nur nicht wie ich die Variable innerhalb einer Klassen definieren muss damit sie A: von außen zugreifbar sind und B: Beim initialisieren der Instanz einmalig auf 0.0 gesetzt werden?
Ich versuche es mal platischer (aber vermutlich noch falsch)
Code: Alles auswählen
class Finger():
daumen #Variable anlegen
def __init__(self):
self.daumen = "Gerade"
def kruemmen(self)
self.daumen = "Krumm"
def strecken(self)
self.daumen = "Gerade"
#weitere Fingerdefinition gespart
class Hand()
rechts= Finger()
links = Finger()
def main()
haende = Hand()
print(hand.rechts.daumen)
hand.rechts.kruemmen()
print(hand.rechts.daumen)
print(hand.links.daumen)
Ausgabe sollte dann sein:
Gerade
Krumm
Gerade
wie sollte es richtig gecoded werden?
Re: Datenstruktur Variable mit 2 Namen.
Verfasst: Samstag 18. September 2021, 20:31
von rogerb
@rob87,
wenn du die offensichtlichen Syntax-Fehler behebst, funktioniert es doch wie erwartet.
Re: Datenstruktur Variable mit 2 Namen.
Verfasst: Samstag 18. September 2021, 20:58
von narpfel
@rob87: In Python müssen Attribute nicht irgendwie vorher „angelegt“ werden. Ein `daumen` auf Klassenebene hat keinen Effekt außer einen `NameError` auszulösen, wenn `daumen` vorher nicht (als globale Variable oder im gleichen `class`-Block) angelegt wurde. Das legt
nicht ein Attribut für Instanzen der Klasse an.
Wenn ein Attribut beim Initialisieren angelegt werden soll, dann musst du es
beim Initialisieren (also in `__init__`) anlegen bzw. an `self` binden. Damit es von außen zugreifbar ist, musst du gar nichts machen: In Python sind
alle Attribute
immer von außen zugreifbar.
Variablen, die im `class`-Block definiert werden, sind Klassenvariablen (was in anderen Sprachen auch „statisch“ genannt wird). Damit teilen sich dann alle Instanzen das gleiche Objekt, und das will man in 99% aller Fälle nicht.
Korrekt müsste es also in etwa so sein:
Code: Alles auswählen
class Finger:
def __init__(self):
self.zustand = "gerade"
def krümmen(self):
self.zustand = "krumm"
def strecken(self):
self.zustand = "gerade"
class Hand:
def __init__(self):
self.daumen = Finger()
self.zeigefinger = Finger()
def main():
linke_hand = Hand()
print(linke_hand.daumen.zustand)
linke_hand.zeigefinger.krümmen()
print(linke_hand.daumen.zustand)
print(linke_hand.zeigefinger.zustand)
In deinem Code macht die Aufteilung der Klassen keinen Sinn, das habe ich also etwas angepasst. Zumindest hat bei mir nicht jeder Finger einen Daumen, und meine Hände haben auch keine „linken“ und „rechten“ Finger.
Wichtigster Unterschied ist, dass die einzelnen `Finger` nicht Attribute der Klasse `Hand` sind, sondern Attribute von
Instanzen der Klasse `Hand`.
Re: Datenstruktur Variable mit 2 Namen.
Verfasst: Dienstag 21. September 2021, 10:07
von rob87
narpfel hat geschrieben: Samstag 18. September 2021, 20:58
@rob87:
Korrekt müsste es also in etwa so sein:
Code: Alles auswählen
class Finger:
def __init__(self):
self.zustand = "gerade"
...
class Hand:
def __init__(self):
self.daumen = Finger()
self.zeigefinger = Finger()
...
1000 Dank für dieses Beispiel! Mir war die Bedeutung des "self."- Operators noch nicht ganz klar. Jetzt kann ich meinen Code umsetzen. Echt spritze !!!
Re: Datenstruktur Variable mit 2 Namen.
Verfasst: Donnerstag 23. September 2021, 11:23
von rob87
narpfel hat geschrieben: Samstag 18. September 2021, 20:58
@rob87:
Korrekt müsste es also in etwa so sein:
Code: Alles auswählen
class Finger:
def __init__(self):
self.zustand = "gerade"
def krümmen(self):
self.zustand = "krumm"
class Hand:
def __init__(self):
self.daumen = Finger()
self.zeigefinger = Finger()
def main():
linke_hand = Hand()
print(linke_hand.daumen.zustand)
linke_hand.zeigefinger.krümmen()
print(linke_hand.daumen.zustand)
print(linke_hand.zeigefinger.zustand)
Jetzt dachte ich, ich habe kapiert und dann doch nicht...
Eigentlich wollte ich beim überschreiten eines Schwellwerts einen Speicher setzen und beim erneuten Überstreiten rücksetzen
Dee Frage für mich ist wieso wird Zeile 38 nur ausgführt(bzw geprinted) und warum wird alt_val nich gespeichert?
Ausgabe:
OFF 0.77
OFF 0.78
ON 0.8300000000000001
OFF 0.91 <--!! hier sollte eigentlich weiterhin "ON" stehen
ON 0.9400000000000001
Wo ist der Fehler:
Code: Alles auswählen
import time
import random
class Flanke:
def __init__(self):
self.alt_val = 0.0
def pos(self,val,schwelle= 0.75):
if val > schwelle and self.alt_val<schwelle: # erstes mal die Schwelle überschritten
return True
else:
return False
self.alt_val = val # aktuellen wert speichern
print(self.alt_val)
def neg(self,val,schwelle= 0.75):
if val<schwelle and self.alt_val>schwelle:
return True
else:
return False
self.alt_val = val
class Toggle:
def __init__(self):
self.zustand= False
self.flanke = Flanke() # instanz Flanke inkl. speicher für -alt_val- erzugen
def status(self,val, schaltschwelle = 0.5):
if self.flanke.pos(val,schaltschwelle):
self.zustand = not self.zustand # Zustand wechseln
return self.zustand
def simu_input(input): #input zwischen 0.4 und 1.0 schwingen lassen
input_richtung =1.0
add=(random.randint(1, 10))*0.01
if input+add > 1.0:
input_richtung =-1.0
elif input - add < 0.4:
input_richtung =1.0
return input + (add*input_richtung)
def main():
schalter= Toggle() # bistabiler Schalter
stick = 0.7 #eingabeelement von Hardware
while True:
if schalter.status(stick,0.8):
str = 'ON %s'%(stick)
else:
str = 'OFF %s'%(stick)
print(str)
stick=simu_input(stick)
time.sleep(0.2)
input_richtung=1.0
main()
Re: Datenstruktur Variable mit 2 Namen.
Verfasst: Donnerstag 23. September 2021, 11:46
von __blackjack__
@rob87: Da ist ein unbenutztes `input_richtung` auf Modulebene. Und was ist denn bei Dir Zeile 38? Bei mir ist das ``if input+add > 1.0:`` in der `simu_input()`-Funktion.
In `Flanke.pos()` und `Flanke.neg()` steht jeweils toter Code nach dem ``if``/``else``. Denn dort steht in beiden Zweigen ein ``return``, womit der Code danach nie ausgeführt werden kann.
Re: Datenstruktur Variable mit 2 Namen.
Verfasst: Donnerstag 23. September 2021, 11:46
von __deets__
Wie sollte denn in Flanke.pos deiner Meinung nach Self.alt_val gesetzt werden, wenn du aus beiden if-Zweigen darüber mit Return die Methode verlässt?
Re: Datenstruktur Variable mit 2 Namen.
Verfasst: Donnerstag 23. September 2021, 12:05
von rob87
__blackjack__ hat geschrieben: Donnerstag 23. September 2021, 11:46
@rob87: Da ist ein unbenutztes `input_richtung` auf Modulebene. Und was ist denn bei Dir Zeile 38? Bei mir ist das ``if input+add > 1.0:`` in der `simu_input()`-Funktion.
In `Flanke.pos()` und `Flanke.neg()` steht jeweils toter Code nach dem ``if``/``else``. Denn dort steht in beiden Zweigen ein ``return``, womit der Code danach nie ausgeführt werden kann.
Ok wird nach "return" kein Code mehr abgearbeitet? dann müsste man es so umschrieben:
Code: Alles auswählen
def pos(self,val,schwelle= 0.75):
if val > schwelle and self.alt_val<schwelle: # erstes mal die Schwelle überschritten
ret_val= True
else:
ret_valFalse
self.alt_val = val # aktuellen wert speichern
print(self.alt_val)
return ret_val
Re: Datenstruktur Variable mit 2 Namen.
Verfasst: Donnerstag 23. September 2021, 12:17
von rob87
So funktionierts jetzt:
Code: Alles auswählen
import time
import random
class Flanke:
def __init__(self):
self.alt_val = 0.0
def pos(self,val,schwelle= 0.75):
if val >= schwelle and self.alt_val<schwelle:
ret_val= True
else:
ret_val= False
self.alt_val = val # aktuellen wert speichern
return ret_val
def neg(self,val,schwelle= 0.75):
if val<=schwelle and self.alt_val>schwelle:
ret_val= True
else:
ret_val= False
self.alt_val = val
return ret_val
class Toggle:
def __init__(self):
self.zustand= False
self.flanke = Flanke()
def status(self,val, schaltschwelle = 0.5):
if self.flanke.pos(val,schaltschwelle):
self.zustand = not self.zustand
return self.zustand
def simu_input(input): #input zwischen 0.4 und 1.0 schwingen lassen
input_richtung =1.0
add=(random.randint(1, 10))*0.01
if input+add > 0.88:
input_richtung =-1.0
elif input - add < 0.4:
input_richtung =1.0
return input + (add*input_richtung)
def main():
schalter= Toggle() # bistabiler Schalter
stick = 0.7 #eingabeelemnt von Hardware
while True:
if schalter.status(stick,0.8):
str = 'ON %s'%(stick)
else:
str = 'OFF %s'%(stick)
print(str)
stick=simu_input(stick)
time.sleep(0.2)
input_richtung=1.0
main()
Re: Datenstruktur Variable mit 2 Namen.
Verfasst: Freitag 24. September 2021, 08:00
von Sirius3
@rob87: eingerückt wird immer mit 4 Leerzeichen pro Ebene, keine Tabs. Wenn man eine if-Abfrage nur dazu benutzt, einer Variable True oder False zuzuweisen, dann kann man gleich die Bedinung der Variable zuweisen.
Benutze keine Abkürzungen, statt alt_val würde man alternative_value schreiben, oder sollte das alter_wert heißen? Die Mischung aus deutsch und englisch ist hier sehr verwirrend.
In simu_input ist der elif-Zeig unnötig, da darin input_richtung gar nicht verändert wird. Der Kommentar stimmt nicht damit überein, was die Funktion macht.
`str` ist der Name einer eingebauten Klasse und sollte nicht überschrieben werden.
Code: Alles auswählen
import time
import random
class Flanke:
def __init__(self):
self.alter_wert = 0.0
def pos(self, wert, schwelle=0.75):
resultat = wert >= schwelle and self.alter_wert < schwelle
self.alter_wert = wert
return resultat
def neg(self, wert, schwelle=0.75):
resultat = wert <= schwelle and self.alter_wert > schwelle
self.alter_wert = wert
return resultat
class Toggle:
def __init__(self):
self.zustand = False
self.flanke = Flanke()
def status(self, wert, schaltschwelle=0.5):
if self.flanke.pos(wert, schaltschwelle):
self.zustand = not self.zustand
return self.zustand
def simuliere_eingabe():
""" input zwischen 0.4 und 1.0 schwingen lassen """
wert = 0.7
richtung = 1.0
while True:
add = random.randint(1, 10) * 0.01
if wert + add > 1.0:
richtung = -1.0
elif wert - add < 0.4:
richtung = 1.0
wert += add * richtung
yield wert
def main():
stick = simuliere_eingabe()
schalter = Toggle() # bistabiler Schalter
while True:
wert = next(stick)
if schalter.status(wert, 0.8):
text = f'{wert:.2f} ON'
else:
text = f'{wert:.2f} OFF'
print(text)
time.sleep(0.2)
if __name__ == "__main__":
main()