Servus allerseits
Benutze Python (v2.7.5) dazu, um meine MCU-Projekte waehrend der
Entwicklung vom PC aus zu testen.
Python Programm sendet also einen Befehl, und die MCU macht irgendwas.
Solange die Anzahl der Befehle nicht gross ist bzw. deren Reihenfolge
nicht staendig sich aendert, ist die Welt in Ordnung.
Nun habe ich aber leider auf der MCU-Seite eine sich staendig aendernde
Situation.
Waehend mein C-Programm ein schlichtes
1
enumBefehle
2
{
3
CMD_READY,
4
CMD_SYSTEM_RESET,
5
...
6
CMD_END_OF_LIST,
7
};
hat, habe ich beim Python ein Modul, das so aussieht
CMD_READY = 0
CMD_SYSTEM_RESET = 1
...
Jede kleinste Aenderung im enum führt dazu, dass ich im Phyton die
Aermel hochkrempeln muss.
Weiss jemand eine etwas elegantere Lösung?
Da du vermutlich auf dem PC crosscompilierst: den Headerfile, in dem das
enum steht, in Python einlesen und auswerten. Dann kann sich das
Pythonprogramm selbst anpassen
MfG Klaus
Klaus, meine Pyhton-Kenntnisse sind eher bescheidener Natur.
Sicher könnte ich mit (für mich) viel Aufwand dies irgendwie hinkriegen;
aber leider bin ich mit meiner Zeit etwas knapp und deshalb würde ich es
vorziehen, wie bis anhin auf die Zaehne zu beissen und das Python-Modul
umzustrukturieren.
Es gibt auch noch andere Möglichkeiten, die Enum-Klasse zu
initialisieren, aber die gezigte ist die kürzeste. Schön an dieser
Klasse ist, dass
- die Enum-Werte als Symbol und nicht nur als Zahl ausgegeben werden und
- sie nicht wie in C zu int kompatibel sind, man also keine
unbeabsichtigen Typkonvertierungen vornehmen kann.
Für diejenigen, die die Enums trotzdem wie Integers behandeln möchten,
gibt es die Klasse IntEnum.
@neuer PIC Freund
Zwar verstehe ich die Zeilen so in etwa; aber bis zum Aha-Erlebnis
müsste ich mich doch sehr intensiv und lange am Kopf kratzen.
@Yalu
Python 3.4 spuckt mir ein paar Fehler mit der seriellen Kommunikation
aus, weshalb ich z.Zt. bei 2.7 verbleiben möchte.
Ich sehe gerade, dass es gibt einen Backport von Enum auf ältere Pythons
ab 2.4 gibt:
https://pypi.python.org/pypi/enum34/
Falls du den nicht installieren möchtest, ist hier noch eine sehr
einfache Enum-Klasse, die immerhin die Elemente automatisch nummeriert,
ohne dass man – wie in meinem allerersten Vorsachlag – die Gesamtzahl
der Elemente angeben muss.
Yalu, bei diesem Bespiel kriege ich die Meldung:
MyEnum instance has no attribute '__setattr__'
Aber wie schon gesagt: Dein erstes Bespiel reicht mir vollkommen.
Off topic betreffend CMD_DRINK_BEER.
Seit die AKP in der Türkei an der Macht ist, hat sie die Steuern für
alkoholische Getraenke um 700% erhöht.
Als letzthin ein paar Freunde aus Deutschland bei mir waren, gab ich
ihnen mit zitternder Hand je eine Flasche Bier. Und mit zitternder
Stimme: "Sehr teuer, also langsam trinken"
So erfuhr ich, dass man in Deutschland für den Preis einer Flasche Bier
made in turkey (2 EUR) ein 6-er Pack bei Aldi bekommt.
Mehmet K. schrieb:> Python 3.4 spuckt mir ein paar Fehler mit der seriellen Kommunikation> aus, weshalb ich z.Zt. bei 2.7 verbleiben möchte.
Und welche fehler wären das?
Ins blaue geraten:
Beim Aufrufen der serial.write() funktion bekommst du einen Fehler
"TypeError: an integer is required" oder ähnliches?
Ja, da hat sich was geändert zwischen Python 2.x und Python 3.x. Wenn es
der Fehler ist, das lässt sich sehr leicht beheben, siehe hier->
Beitrag "Re: Serielle Kommunikation zwischen Python und µC"
Mehmet K. schrieb:> Yalu, bei diesem Bespiel kriege ich die Meldung:> MyEnum instance has no attribute '__setattr__'
Mist, ich habe das aus Versehen nur mit Python 3 getestet. Richtig
muss die Zeile so lauten:
1
setattr(self, name, value)
Da funktioniert in beiden Pythons. Ich hab's mal oben korrigiert.
> Aber wie schon gesagt: Dein erstes Bespiel reicht mir vollkommen.
Bis auf den kleinen Schönheitsfehler, dass man die Anzahl der Elemente
explizit als Range-Argument hinschreibe muss, gefällt mir die Methode
eigentlich auch ganz gut, weil man dazu weder eine Klassendefinition
nich einen Import braucht.
Dennis S. schrieb:> Yalu X. schrieb:>> CMD_READY, CMD_SYSTEM_RESET, CMD_DRINK_BEER, CMD_EAT_SNAKES = range(4)>> Sehr cool.. :-)
Da hier angewandte coole Feature heißt Pattern-Matching. Schade, dass es
so etwas nicht in allen Programmiersprachen gibt. Das würde sehr viele
inhaltsarme Codezeilen einsparen.
Yalu X. schrieb:> Da hier angewandte coole Feature heißt Pattern-Matching.
Nö, eher "tupling".
Mit pattern matching (regexp und seine Freunde) hat es nix am Hut.
EDiT: Aber ein cooles Feature ist es trotzdem :-)
Das ist Pattern-Matching für Strings.
Eric B. schrieb:> Yalu X. schrieb:>> Da hier angewandte coole Feature heißt Pattern-Matching.>> Mit pattern matching (regexp und seine Freunde) hat es nix am Hut.
Regexes machen Pattern-Matching auf Strings. Es gibt aber auch Pattern-
Matching auf Datenstrukturen, was vor allem in Funktionalsprachen weit
verbreitet ist. Python deckt mit der Zuweisung zu Target-Lists einen,
allerdings auch nur einen Aspekt dieser Form des Pattern-Matching ab.
Insofern ist der Begriff sicherlich etwas zu hoch gegriffen, und ich
nehme ihn hiermit zurück.
> Nö, eher "tupling".
Tupling kenne ich als Programmiertechnik zur Effizienzsteigerung von
rekursiv definierten Funktionen. Auch die meisten Google-Treffer zeigen
in diese Richtung. Und eigentlich ist das, was Python bei Zuweisungen
tut, eher ein "Detupling".
Da auch die Python-Referenz das Kind nicht wirklich beim Namen nennt,
habe ich etwas recherchiert und bin auf den Begriff "Destructuring" bzw.
"Destructuring Assignment" gestoßen, der IMHO den Sachverhalt IMHO ganz
gut trifft, auch wenn in Python das Destructuring auf (möglicherweise
verschachtelte) Iterables (Tuples, Listen usw.) beschränkt ist.
> EDiT: Aber ein cooles Feature ist es trotzdem :-)
Deswegen hätte ich es eben auch gerne in C und C++, egal wie die
dortigen Sprachentwickler es nennen mögen :)
Yalu X. schrieb:> Deswegen hätte ich es eben auch gerne in C und C++, egal wie die> dortigen Sprachentwickler es nennen mögen
Es ist nicht notwendig die Sprachen damit zu Überladen, da dies bereits
möglich ist.
In C++ könnte das dann so aussehen:
Der vollständige Code ist im Anhang. Getestet mit gcc 4.9.2, compiliert
mit "g++ -std=c++11 -Wall -Wextra -Werror -pedantic set.cpp -o set"
In C wären mit Macros noch viel extremere Dinge möglich.
Daniel A. schrieb:> In C++ könnte das dann so aussehen:
Respekt! Das sieht wirklich gut aus.
Ich habe gerade gesehen, dass es in der Standardbibliothek das
function template tie gibt, das in etwa deinem tupleReference
entspricht:
http://www.cplusplus.com/reference/tuple/tie/
Allerdings lässt sich tie im Gegensatz zu deinem tupleReference
nicht verschachteln, da die Argumente normale non-const references sind,
weswegen kein tie-Tupel übergeben werden kann.
Du hast stattdessen rvalue references genommen, so dass auch
Verschachtelung möglich ist, was natürlich näher an das Python-Vorbild
herankommt. Ebenfalls mit rvalue references arbeitet das function
template forward_as_tuple der Standardbibliothek:
http://www.cplusplus.com/reference/tuple/forward_as_tuple/
Damit sind Verschachtelungen möglich, allerdings steht da geschrieben:
1
This function is designed to forward arguments, not to store its result
2
in a named variable, since the returned object may contain references to
3
temporary variables.
Da ich mit den neuen C++11/14-Features (noch) nicht so vertraut bin,
frage ich mich, ob das ein Problem ist und wenn ja, ob dieses Problem
auch bei deinen Funktionen auftreten kann. Aus dem Gefühl heraus hätte
ich gesagt, dass kein Problem entsteht, solange als Argumente keine
rvalues übergeben werden, was ja für das unpacking sowieso keinen Sinn
ergäbe. Übergibt man allerdings versehentlich doch einen rvalue, erhält
man keine Fehlermeldung des Compilers, sondern evtl. einen Crash bei der
Ausführung, da Zuweisungen an nicht mehr existente Objekte erfolgen. Man
erkauft sich also mehr Funktionalität (Verschachtelung) durch eine etwas
reduzierte Typsicherheit.
Da du sehr fit in C++ zu sein scheinst, würde mich interessieren, wie du
das siehst.
@Mehmet:
Da dir meine erste Antwort offensichtlich weitergeholfen hat, hoffe ich,
es stört dich nicht allzu sehr, dass dein Thread gerade etwas abdriftet.
Wenn doch, sag Bescheid, dann fange ich einen neuen Thread an. Ansonsten
hat sich das C++-Thema sicher auch schnell wieder erledigt.
Yalu X. schrieb:> Da dir meine erste Antwort offensichtlich weitergeholfen hat, hoffe ich,> es stört dich nicht allzu sehr, dass dein Thread gerade etwas abdriftet.> Wenn doch, sag Bescheid, dann fange ich einen neuen Thread an. Ansonsten> hat sich das C++-Thema sicher auch schnell wieder erledigt.
Um alles in der Welt, natürlich stört mich das nicht. Im Gegenteil!
Yalu X. schrieb:> frage ich mich, ob das ein Problem ist und wenn ja, ob dieses Problem> auch bei deinen Funktionen auftreten kann.
Ja, es ist ein Designproblem, welches bei meiner Variante sogar noch
vergrößert wird, da ich aus rvalue Referenzen lvalue Referenzen mache
und diese zurückgebe, ohne std::forward zu verwenden um die
Typsicherheit sicherzustellen.
> Aus dem Gefühl heraus hätte> ich gesagt, dass kein Problem entsteht, solange als Argumente keine> rvalues übergeben werden, was ja für das unpacking sowieso keinen Sinn> ergäbe. Übergibt man allerdings versehentlich doch einen rvalue, erhält> man keine Fehlermeldung des Compilers, sondern evtl. einen Crash bei der> Ausführung, da Zuweisungen an nicht mehr existente Objekte erfolgen.
Das ist soweit alles korrekt.
> Man erkauft sich also mehr Funktionalität (Verschachtelung) durch eine etwas> reduzierte Typsicherheit.
Ja, schon, aber man kann auch Verschachtelung mit etwas stärkerer
Typprüfung realisieren, indem man für std::tuple eine Fallunterscheidung
mittels SFINAE durchführt.
> Da du sehr fit in C++ zu sein scheinst, würde mich interessieren, wie du> das siehst.
So fit bin ich momentan eigentlich nichtmehr in C++, mein letzter C++
Code war vor vielleicht vor einem halben Jahr. Und rvalue referenzen
korrekt zu nutzen finde ich immer noch schwierig. Mein vorheriges
beispiel enthielt zwei weitere Designfehler:
* Bei "constexpr const tupleSetter& operator=( const U&& values )" kann
dem = opperator keine lvalue zugewiesen werden
* Die Definitionen von tupleValues können miteinander in Konflikt
geraten.
Ich habe eine Verbesserte und etwas Erweiterte Version erstellt, aber
sie ist sicher noch nicht Perfekt.
Daniel A. schrieb:> Bei "constexpr const tupleSetter& operator=( const U&& values )" kann> dem = opperator keine lvalue zugewiesen werden
Ich meinte natürlich rvalue, sorry.