Welche Programmiersprache für meine spez. Interessen?

antred schrieb:
welche C++-Features brauchen deiner Meinung nach mehr Resourcen als eine entsprechende Umsetzung in C?
Ich dachte da an die Objektorientierung. Die fügt einem Programm viel Kram zur Objektverwaltung hinzu. Wenn man denn Objekte verwendet und das tut man, wenn man die Möglichkeit dazu hat. Es macht einfach so vieles bequemer.

Und was wäre der Vorteil eine so umfangreiche Sprache wie C++ auf einem Gerät zu verwenden, auf dem man locker die Hälfte der Features nicht braucht?

Ich will damit nicht sagen, dass C++-Programmierung für µC komplett unnütz ist, aber die meisten Controller sind arg eingeschränkt. C++ wäre da wie Kanonen auf Spatzen.
 
e-Laurin schrieb:
Ich dachte da an die Objektorientierung. Die fügt einem Programm viel Kram zur Objektverwaltung hinzu. Wenn man denn Objekte verwendet und das tut man, wenn man die Möglichkeit dazu hat.
Das klingt arg spekuliert. Das Schlüsselwort "class" einfach verwenden und es käme irgendein Overhead hinzu trifft nicht zu - nichtmal wenn man die Kompileroptimierung ausschaltet.

Code:
class Point
{
public:
	int x,y;
};

void funktion1(int& x, int& y)
{
	x += 1;
	y += 1;
}

void funktion2(Point& pt)
{
	pt.x += 1;
	pt.y += 1;
}
Man vergleiche beide Funktionen. Wie du siehst ähneln sie sich sehr. Geändert hat sich vor allem, das bei funktion1 zwei unabhängige Speicheradressen an die Funktion übergeben werden, bei der zweite nur eine, weil die zweite Variable y relativ zur ersten liegt.
Solange man keinen Konstruktor anlegt, passiert bei beiden auch beim Anlegen das gleiche: nichts. Auch die int's der Klasse sind Zufallswerte, ein Konstruktor wird nicht aufgerufen, weil es ja keinen gibt. Objektorientierung fügt dem ganzen erstmal rein gar nichts hinzu. Wenn man das gleiche Codebeispiel class gegen struct austauscht und man das ganze als C kompiliert , passiert: nichts. Gleicher Quellcode.

Code:
	.file	"test.cpp"
	.text
	.globl	_Z9funktion1RiS_
	.type	_Z9funktion1RiS_, @function
_Z9funktion1RiS_:
.LFB0:
	.cfi_startproc
	pushq	%rbp
	.cfi_def_cfa_offset 16
	.cfi_offset 6, -16
	movq	%rsp, %rbp
	.cfi_def_cfa_register 6
	movq	%rdi, -8(%rbp)
	movq	%rsi, -16(%rbp)
	movq	-8(%rbp), %rax
	movl	(%rax), %eax
	leal	1(%rax), %edx
	movq	-8(%rbp), %rax
	movl	%edx, (%rax)
	movq	-16(%rbp), %rax
	movl	(%rax), %eax
	leal	1(%rax), %edx
	movq	-16(%rbp), %rax
	movl	%edx, (%rax)
	popq	%rbp
	.cfi_def_cfa 7, 8
	ret
	.cfi_endproc
.LFE0:
	.size	_Z9funktion1RiS_, .-_Z9funktion1RiS_
	.globl	_Z9funktion2R5Point
	.type	_Z9funktion2R5Point, @function
_Z9funktion2R5Point:
.LFB1:
	.cfi_startproc
	pushq	%rbp
	.cfi_def_cfa_offset 16
	.cfi_offset 6, -16
	movq	%rsp, %rbp
	.cfi_def_cfa_register 6
	movq	%rdi, -8(%rbp)
	movq	-8(%rbp), %rax
	movl	(%rax), %eax
	leal	1(%rax), %edx
	movq	-8(%rbp), %rax
	movl	%edx, (%rax)
	movq	-8(%rbp), %rax
	movl	4(%rax), %eax
	leal	1(%rax), %edx
	movq	-8(%rbp), %rax
	movl	%edx, 4(%rax)
	popq	%rbp
	.cfi_def_cfa 7, 8
	ret
	.cfi_endproc
.LFE1:
	.size	_Z9funktion2R5Point, .-_Z9funktion2R5Point
	.ident	"GCC: (GNU) 4.8.2 20131212 (Red Hat 4.8.2-7)"
	.section	.note.GNU-stack,"",@progbits

Auch wenn du
Code:
class Point
{
public:
	int x,y;
};

class Point3D : public Point
{
public:
	int z;
};

void funktion3(int& x, int& y, int& z)
{
	x += 1;
	y += 1;
	z += 1;
}

void funktion4(Point3D& pt)
{
	pt.x += 1;
	pt.y += 1;
	pt.z += 1;
}

schreibst, wirst du feststellen, das der Output immernoch keine Spur von Overhead aufweist. Der einzige Unterschied ist hier das leicht andere Speicherlayout. Dabei ist die C++ Variante eigentlich im Vorteil, weil die drei Variablen hintereinander im Speicherliegen und so das ganze evtl. einfacher einer SIMD Einheit des Prozessor zugeführt werden kann. Ja es gibt Features, die Overhead hinzufügen, z.B. virtual, aber um das gleiche in C zu erreichen, wirst du ihn auch dort hinzufügen müssen, nur das du es da selber schreiben musst. Aber einfach nur Vererbung usw. verwenden, kostet nichts. Hier nochmal Memberfunktionen:
Code:
void funktion5(Point3D& pt)
{
	pt.x += 1;
	pt.y += 1;
	pt.z += 1;
}

void Point3D::funktion6()
{
	x += 1;
	y += 1;
	z += 1;
}
Erzeugen beide identischen Code!
Ich empfehle hier das rumspielen mit g++ mit dem Parameter -S.
Ich würde gerne mehr Beispiele liefern, aber der Assemblercode ist immer so lang.... Also wenn du kein konkretes Gegenbeispiel kennst, glaub mir: OOP gibt's for free!
 
Zuletzt bearbeitet:
@geisterfahrer: Top dargestellt von dir. Ich hätte auch getippt, dass C++ (OOP) mehr Overhead aufbaut im Vergleich zu C. Aber dein Assemblercode ist überzeugend.
 
e-Laurin schrieb:
Btw, ich bin der Meinung, dass Akademiker eher in C++, C# und Java als in Python programmieren. Zumindest war das in meiner Hochschule so. Es kann sein, dass es woanders anders ist.
Leider ähneln sich Python und die C-artigen Sprachen nicht besonders. Es ist schade, dass man beim Lernen von Python nicht automatisch ein wenig der anderen Sprachen mitlernt.
Kommt aufs Fachgebiet drauf an. Als Informatiker nimmt man vermutlich schon eher Java und C#. Ich studier z.B. Physik und weiß von vielen Kollegen, dass sie Python mit dem ganzen numpy/scipy/matplotlib-Stack benutzen um Plots zu erzeugen, numerische Berechnungen durchführen etc. Die Computational Physics Leute nehmen natürlich C, weil ihnen der Rest zu langsam ist, aber ansonsten ist Python schon weit verbreitet.

Und natürlich lernt man nicht C wenn man Python programmiert. Aber man tut sich ja auch leichter C zu lernen, wenn man schon weiß WIE man überhaupt programmiert (egal welche Sprache).
 
Python liegt halt irgendwo zwischen C++ und Matlab/Octave. ;)

Python:
>>> x = np.A( ((2,3), (3, 5)) )
>>> y = np.B( ((1,2), (5, -1)) )
>>> np.dot(A,B)
matrix([[17, 1],
[28, 1]])

oder:

>>> np.mat(x) * np.mat(y)
matrix([[17, 1],
[28, 1]])

MATLAB
>> A=[1 2; 3 4], B=[8 7 6 5; 4 3 2 1], C=[11 12; 21 22]
A = B = C =
1 2 8 7 6 5 11 12
3 4 4 3 2 1 21 22

>> A+C >> A*B >> A^2
ans = ans = ans =
12 14 16 13 10 7 7 10
24 26 40 33 26 19 15 22

Naturwissenschaftler nutzen eben diese Tools (besonders bei MATLAB/Oktave) eher "skriptförmig", um ihre Algorithmen zu testen und dabei den Überblick über den Algorithmus zu behalten, dieser und ggf. dessen Optimierung steht dabei im Vordergrund.
OOP würde hier durch Klassenstrukturen den Überblick auf den Kern erschweren.

Einen fertigen Algorithmus kann man dann halt immer noch (ggf. mit schöner GUI) in irgendeiner Programmiersprache JAVA, C++, C# umsetzen als "fertiges Programm für andere Anwender, die den Algorithmus dann nutzen".
Hier liegt IMO der wesentliche Unterschied.

Python steht dabei irgendwo zwischen beiden "Welten".
Aber ich würde im experimentellen Stadium für Algorithmen eher A * B schreiben können und MATLAB/Octave weiß, dass ich eine Matrix-Multiplikation ausführen will, als wenn ich np.mat(A) * np.mat(B) schreiben müsste.
 
Zuletzt bearbeitet:
Einen kleinen Arduino Uno Nachbau für 15 ,- € und das "Arduino für Anfänger" Buch dazu ist schon recht nett für den Einstieg.

Der Arduino versteckt mit seiner Library sehr viel der Hardwareansteuerung und ermöglicht daher schnelle Erfolgserlebnisse.
Mann muss sich halb nicht mit Registern und binären UND/ODER herumschlagen um Ports zu schreiben.
Der echte Hardwareaufbau ist nicht relevant - Das erleichtert einiges.

Programmiert wird in C(++). Somit ist die Syntax schon mal ähnlich der verbreitetsten Sprachen wie Java, C#, JavaScript oder PHP.
 
LF-X schrieb:
Der Arduino versteckt mit seiner Library sehr viel der Hardwareansteuerung und ermöglicht daher schnelle Erfolgserlebnisse.
Mann muss sich halb nicht mit Registern und binären UND/ODER herumschlagen um Ports zu schreiben.
Der echte Hardwareaufbau ist nicht relevant - Das erleichtert einiges.

Das stimmt, nur genau dieser Punkt ist auch dann zu hinterfragen, wenn man sich zum Ziel macht aus Interesse (so habe ich den TE verstanden) sich mit hardwarenaher Programmierung und Embedded-Systemen zu beschäftigen.
Schneller Erfolgserlebnisse - klar. Aber für mich hatten eben genau diese bitweisen Maskierungen, ab und an sogar mal Bits schieben oder Rotieren und das genau und vor allem direkt auf den Ports, die für die Hardwarefunktion verantwortlich sind, diesen besonderen Reiz. Auch Interrupt-Register sind etwas Feines auf µC's.
Aber klar - Auswahlkriterium hier ist das Ziel oder Anliegen des Gesamtvorhabens.
 
Schiller72 schrieb:
Python steht dabei irgendwo zwischen beiden "Welten".
Aber ich würde im experimentellen Stadium für Algorithmen eher A * B schreiben können und MATLAB/Octave weiß, dass ich eine Matrix-Multiplikation ausführen will, als wenn ich np.mat(A) * np.mat(B) schreiben müsste.

Das liegt eventuell daran, dass du numpy falsch benutzt. Erstens ist dein Code schonmal falsch (was ist np.A und np.B? Dann weißst du an x und y etwas zu, arbeitest danach aber mit A und B?)
Numpy hat auch eine Matrix-Klasse:
Code:
>>> import numpy as np
>>> A = np.matrix([[2,3], [3, 5]])
>>> B = np.matrix([[1,2], [5,-1]])
>>> A*B
matrix([[17,  1],
        [28,  1]])
>>> A+B
matrix([[3, 5],
        [8, 4]])
>>> A**2
matrix([[13, 21],
        [21, 34]])
>>> np.sin(A)
matrix([[ 0.90929743,  0.14112001],
        [ 0.14112001, -0.95892427]])
Damit kannst du A*B schreiben ;)
 
e-Laurin schrieb:
Meiner Meinung nach ist Mikrocontroller-Programmierung = C-Programmierung. Warum denke ich so? C wird seit Urzeiten dafür verwendet. Dafür gibt es einen Grund: Man kann damit schnell und simpel programmieren. Auf einem µC laufen nur simple Programme, für mehr sind eh keine Ressourcen da. Man braucht da in den meisten Fällen nicht das schweizer Taschenmesser C++.

Jetzt könnte man sagen, mit C++ kann man auch einfache Programme schreiben. Das ist richtig, aber von den vielen Konzepten, die man damit umsetzen kann, werden die meisten nicht benötigt oder können mangels Systemressourcen nicht eingesetzt werden. Wenn man zB nur 8 KB Speicher hat, muss man damit haushalten.


Das höre ich zum ersten Mal. Es ist richtig das C seit Urzeiten für Mikrocontroller genutzt wird, aber es ist einfach falsch zu behaupten das C die resourcensparendere oder simplere Alternative sei. Die Tatsache das C weniger Konzepte bietet ist bedingt nicht automatisch schmalere Programme.
 
@Schiller72: Die Arduino-Welt verhindert das binäre ansprechen der Hardware ja nicht. Eigentlich könnte man sich sogar im Quellcode der Arduino-Bibliothek anschauen, wie man das macht. Aber auf anderen Plattformen hat man in der Tat keine andere Wahl.

In der aktuellen ct Hacks (1/2014) ist ein Grundkurs für die MSP430 µC PLattform. Die wird deutlich hardwarenäher programmiert und ist dabei auch noch günstiger als die meisten Arduino-Boards - Dabei mindestens genauso stark, wenn nicht sogar leistungsfähiger (mehr Ports, weniger stromverbrauch).
 
Beim Thema hardwarenaher Programmierung geht es mir in gewisser Weise um beides: Ich will einerseits nicht jedesmal das Rad neu erfinden müssen, viele Bibliotheken für häufig wiederkehrende Standardaufgaben wären als durchaus willkommen. Natürlich insbesondere dann, wenn es eben doch primär um das Ergebnis geht. Bspw. mal die Realisierbarkeit irgendeiner Idee mit einem schnell zusammengebastelten Prototypen zu testen. Andererseits möchte ich aber wie Schiller72 korrekt feststellt aus Interesse auch diverse grundlegende Funktionen eines Mikrocontrollers/Prozessors auf möglichst hardwarenaher Ebene verstehen. Habe ich dieses und jenes dann einmal grundlegend verstanden würde es mir reichen die jeweiligen Funktionen auch auf bequemere Weise unter Rückgriff auf vorhandene Bibliotheken zu nutzen. Es wäre halt nett zu wissen, daß man bei Bedarf auch mal einige kleine Details vorhandener Module an die eigenen Bedürfnisse anpassen kann. Wohlgemerkt alles stets ohne den Anspruch jetzt ein Profi im Bereich hardwarenaher Programmierung zu werden..
 
geisterfahrer schrieb:
Das klingt arg spekuliert. Das Schlüsselwort "class" einfach verwenden und es käme irgendein Overhead hinzu trifft nicht zu - nichtmal wenn man die Kompileroptimierung ausschaltet.
Uff, das ist mehr Assembler als ich erwartet habe. So viel für so wenig? Liegt das an den Kompileroptionen?

Ich bin bis jetzt davon ausgegangen, dass der Compiler etwas in dieser Richtung ausspuckt:
Code:
.DATA
    var_a DD ?
    var_b DD ?

.CODE
funktion1:
    pushl
    inc DWORD PTR [var_a]
    inc DWORD PTR [var_b]
    popl
    ret
(Der Code ist vermutlich unvollständig. Mein letzter Assembler-Code ist etwas länger her.)


Kannst du sagen, wie das kommt?
 
Naja, du liest einfach die Variablen aus dem Datensegment und übergibst sie nicht per Stack. Ein Stackframe nimmt ein wenig Platz ein. Einerseits kann ein x86-64 Prozessor nicht in allen Registern rechnen (im Gegensatz zu einigen RISC Architekturen), sodass per Stack erst die Adressen der Variablen (sind ja nur Pointer!) entgegengenommen werden, deren Wert ins richtige Register verschoben werden, die Berechnung durchgeführt wird (deswegen die vielen mov Operationen). Wobei der angegebene Assemblercode selbst für unoptimierten Assemblercode merkwürdig ist, da er da unnötigerweise einen Stackframe aufbaut, obwohl bei 64Bit dieser bei kurzen Funktionen wie die angebenen überflüssig sind (denn hier werden die Parameter in begrenztem Umfang in Registern übergeben werden!), der Compiler tut irgendwie ein bisschen so, als wäre auf einem x86-32.
Deswegen hier der Vollständigkeit halber der optimierte Assemblercode:
Code:
	.file	"test.cpp"
	.text
	.p2align 4,,15
	.globl	_Z9funktion1RiS_
	.type	_Z9funktion1RiS_, @function
_Z9funktion1RiS_:
.LFB0:
	.cfi_startproc
	addl	$1, (%rdi)
	addl	$1, (%rsi)
	ret
	.cfi_endproc
.LFE0:
	.size	_Z9funktion1RiS_, .-_Z9funktion1RiS_
	.p2align 4,,15
	.globl	_Z9funktion2R5Point
	.type	_Z9funktion2R5Point, @function
_Z9funktion2R5Point:
.LFB1:
	.cfi_startproc
	addl	$1, (%rdi)
	addl	$1, 4(%rdi)
	ret
	.cfi_endproc
.LFE1:
	.size	_Z9funktion2R5Point, .-_Z9funktion2R5Point
	.ident	"GCC: (GNU) 4.8.2 20131212 (Red Hat 4.8.2-7)"
	.section	.note.GNU-stack,"",@progbits
Hätte ich mal gleich machen sollen. Da sieht man auch auf den ersten Blick, das bei der ersten Funktion zwei unterschiedliche Adressen per zwei unterschiedlichen Registern übergeben werden (was bei x86-32 nicht möglich gewesen wäre), bei der zweiten eben nur per einzelnem Register, die zweite Variable dann eben nur um 4Byte verschoben eingelesen wird. Der Rest sind nur Sprungmarken und irgendwelchen Gedöns der nicht ausgeführt wird.

Der Vollständigkeit der alte Assemblercode teilweise beschrieben:
Code:
	pushq	%rbp @bp = basepointer sichern
	movq	%rsp, %rbp
	movq	%rdi, -8(%rbp) @hier scheint ein künstlicher Stackframe aufgebaut zu werden. Es wird jedenfalls der erste Parameter relativ zum basepointer kopiert.
	movq	%rsi, -16(%rbp) @hier der zweite (weil es 64 Bit Pointer sind, sind die Adresse um 8 Byte verschoben und nicht die vier Byte der ints)
	movq	-8(%rbp), %rax @hier wird der Wert des ersten Pointers in Register verschoben (zuvor gabs nur einen Pointer)
	movl	(%rax), %eax  @hier wird der Wert dann gleich wieder kopiert, nämlich ins 32Bit Accumulator Register (eax)
	leal	1(%rax), %edx @addition
	movq	-8(%rbp), %rax @hier wird nochmal die Speicheradresse hervorgeholt
	movl	%edx, (%rax) @die Speicheradresse wird verwendet, um das Ergebnis aus eax an das Ziel der Speicheradresse zu schreiben
	movq	-16(%rbp), %rax @ab hier beginnt das gleiche Spiel mit dem zweiten Parameter
	movl	(%rax), %eax
	leal	1(%rax), %edx
	movq	-16(%rbp), %rax
	movl	%edx, (%rax)
	popq	%rbp @den alten basepointer wiederherstellen
	ret @return

Da ich von tumbleweed den entscheidenen Tipp bekommen habe mit den Spoilern, hier noch ein weiteres Beispiel:
Code:
template<typename T>
class Point
{
public:
	T w,x,y;
};

class Point4D : public Point<int>
{
public:
	int z;
};

void funktion3(int& w, int& x, int& y, int& z)
{
	w += 1;
	x += 1;
	y += 1;
	z += 1;
}

void funktion4(Point4D& pt)
{
	pt.w += 1;
	pt.x += 1;
	pt.y += 1;
	pt.z += 1;
}
Code:
_Z9funktion3RiS_S_S_:
.LFB0:
	addl	$1, (%rdi) @hier ist hübsch zu sehen, das die neuen R-Register der 64Bitter sich bezahlt machen..
	addl	$1, (%rsi)
	addl	$1, (%rdx)
	addl	$1, (%rcx)
	ret
_Z9funktion4R7Point4D:
.LFB1:
	movdqu	(%rdi), %xmm0 @Paramter entgegen nehmen und in SSE Register kopieren
	paddd	.LC0(%rip), %xmm0 @Das besagte SSE Register mit der Konstante an LC0 addieren
	movdqu	%xmm0, (%rdi) @Ergebnis zurückschreiben
	ret
.LC0:
	.long	1
	.long	1
	.long	1
	.long	1
Hier sieht man das Templates rein gar nichts anrichten (werden zu Compilezeit aufgelöst), Vererbung ändert auch nichts. Nur das veränderte Speicherlayout sorgt hier dafür, dass das Ergebnis für die Objektvariante im SIMD Register (xmm) berechnet wird und nicht einzeln. Würde ich in der Nicht-Objektvariante das ganze als Array übergeben, würde dort der gleiche Code generiert werden. Im grunde kann man sagen, eine class/struct ein Array mit fester Länge und inhomogenen Typen ist, das nicht per numerischen Index, sondern per Name ansprochen wird. Eine Memberfunktion ist erstmal nicht vielmehr als eine normale Funktion, die als ersten Parameter einen this Pointer übergeben bekommt. Wenn man den this-Pointer dann nicht benutzt, weil es auch eine static Funktion hätte sein können, hat man dann tatsächlich einen Overhead, nämlich den unnötigen this Pointer erzeugt. Deswegen sollte man dann einfach static davor schreiben -> Problem gelöst.
 
"Vererbung ändert auch nichts" stimmt aber auch nur, solange man keine virtuelle Methoden benutzt. Und jeder, der Vererbung in C++ benutzt, wird auch virtuelle Methoden benutzen, sonst kann man keine Funktionen überschreiben.

Und bei virtuellen Methoden hat man einen Performance-Verlust, da die richtige Funktionsadresse erst dynamisch zur Laufzeit aus der vtable bestimmt wird. Aber du hast schon recht, wenn du sagst, dass man in C vor dem gleichen Problem steht, nur dass man da halt die Sache mit den Funktionspointern selbst schreiben müsste.
 
stwe schrieb:
[..] Und jeder, der Vererbung in C++ benutzt, wird auch virtuelle Methoden benutzen, sonst kann man keine Funktionen überschreiben.

Und bei virtuellen Methoden hat man einen Performance-Verlust, da die richtige Funktionsadresse erst dynamisch zur Laufzeit aus der vtable bestimmt wird.[..]
Mal abgesehen davon das ich da schon selber darauf hingewiesen habe, finde ich die Bedeutung von virtuellen Funktionen etwas übertrieben dargestellt. Überschreiben kann man ja Funktionen auch ohne virtual, solange man den richtigen Zeigertyp parat hat. Und ich finde es gibt genügend Anwendungfälle in denen das zutrifft.
Der Performanceverlust von virtual an sich ist eher gering, problematischer bei kleinen Funktionen ist, das die Funktionen nicht ge-inline-d werden können. Naja, lässt sich oft mit Templates vermeiden, wenn's performancekritisch ist. Zum Dank gibt's dann ewig lange Kompilierzeiten, wegen des vielen Codes in Headern...

Kann man bei Bedarf eigentlich umkompliziert C++-Code und Bibliotheken in Python Programme "einbauen", um bspw. auf dessen Stärken bei speziellen hardwarenahen Aufgaben zurückzugreifen, für die übrigen Programmteile hingegen die Stärken (und vlt. auch den u. Umständen geringeren Programmieraufwand) von Python nutzen?
Selbstverständlich kann man C/C++ Code von Python aus nutzen. Deswegen gibt es ja auch etliche C++ Bibliotheken wie Qt und OpenCV auch für Python. Ist natürlich mit extra Aufwand verbunden, aber ein legetimer Weg*. Man kann jedenfalls die Stärken der Sprachen so miteinander kombinieren, also neben hardwarnahem Kram auch den performancekritischen** Kram in C(++) schreiben. Auch OpenCL Kernel kann man von Python aus nutzen. Letzteres haben bspw die Macher von SPRAY, einem Algorithmus zu Straßenerkennung gemacht. Der funktioniert übrigens per maschinellem Lernen (GentleBoost).
(http://www.cvlibs.net/datasets/kitti/eval_road.php erster Eintrag jeweils in den Evaluationstabellen). Wenn du oben auf "Stereo" klickst und dort die Evaluationstabellen anschaust, siehst du welche Programmiersprache bei sehr performancekritischen Zeug eingesetzt wird.


*bspw. durch Boost.Python oder SWIG umsetzbar.
** das Original CPython ist eher, hmm, sagen wir gemütlich
 
Zuletzt bearbeitet:
So, ich werde jetzt wohl erstmal mit Python anfangen. C oder C++ kommen für ausgewählte Aufgaben zur Hardwaresteuerung aber sicher bald dazu. Für alles andere werde ich aber sofern es möglich ist und keine relevanten Geschwindigkeitsnachteile bringt erstmal nur Python verwenden. Es wird dann also darauf hinauslaufen, daß ich ergänzenden C oder C++ Code für hardwarenahe Aufgaben in Python Programme einbinde.

Noch eine Frage zu Editoren: ist es empfehlenswert gleich einen Editor mit Debugger zu verwenden, um den Umgang damit zu lernen?
Ich habe hier mal nachgeschaut: https://wiki.python.org/moin/PythonEditors
Die Auswahl an Editoren erschlägt einen Anfänger ja ziemlich. Wobei viele allerdings keinen debugger haben.
 
thecain schrieb:
IDLE tut die arbeit doch zum einsteigen...
Stimmt eigentlich. Bei der Frage nach einer anfängergeeigneter IDE bzw. Editor sind die Antworten wahrscheinlich eh stark von persönlichen Vorlieben geprägt.
Was mir momentan mehr Kopfzerbrechen bereitet ist das Problem, daß man mit Python 2.7 und Python 3.x quasi zwei parallel laufende Versionen hat. Neben der Frage, mit welcher Version ich denn dann anfangen soll werde ich wohl zwangsläufig irgendwann mit Versionskonflikten der Nichtstandardbibliotheken konfrontiert werden, weil ich bei meinen Interessen sicher viele Bibliotheken nutzen werde, die vielleicht mal in der einen und mal in der anderen Version aktuell sind.
 
Tellurium schrieb:
Was mir momentan mehr Kopfzerbrechen bereitet ist das Problem, daß man mit Python 2.7 und Python 3.x quasi zwei parallel laufende Versionen hat. Neben der Frage, mit welcher Version ich denn dann anfangen soll werde ich wohl zwangsläufig irgendwann mit Versionskonflikten der Nichtstandardbibliotheken konfrontiert werden, weil ich bei meinen Interessen sicher viele Bibliotheken nutzen werde, die vielleicht mal in der einen und mal in der anderen Version aktuell sind.

Hey,
so tragisch ist es auch wieder nicht. Es gibt ein paar Syntax-Änderungen (z.B. print() anstatt print-Statement, "except Error as e" anstatt "except Error, e"), aber die hat man wirklich schnell raus. Es wurden auch paar Bibliotheksnamen geändert, aber das ist eh kein Problem weil niemand alle Namen auswendig lernt sondern eh immer nachschaut.

Ich würde bei neuen Projekten immer Python 3 verwenden, da es früher oder später kein Python 2 mehr geben wird. Die meisten Bibliotheken sind auf Python 3 schon portiert. Wenn eine Bibliothek für Python 3 portiert wird (und die meisten sind das) ist sie auch genau so aktuell wie die Python 2-Version. Ich würde mir darüber erstmal weniger Gedanken machen, am Anfang reicht vermutlich eh lange Zeit die Standardbibliothek.
 

Ähnliche Themen

Antworten
47
Aufrufe
190.672
D
Antworten
35
Aufrufe
3.845
Zurück
Oben