Ich bin neu und suche ein paar Tipps

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
isItMe?
User
Beiträge: 2
Registriert: Donnerstag 22. Juni 2017, 19:58

Hallo erstmal! Ich bin neu bei Python und habe daher ein paar Fragen. Diese ließen sich sicherlich auch durch Recherche leicht herausfinden, aber da einer der Leser die Frage vielleicht auch aus dem Kopf beantworten kann, stelle ich sie trotzdem mal. (Also bitte nicht die Mühe machen und für mich googlen)

1.) Es gibt ja py2exe, womit sich ein Script als Executable exportieren lässt.
- Wie funktioniert das ganze? Erstellt der Code ähnlich wie bei Java eine VM und führt dort den Code aus?
- Ist diese Methode im produktiven Einsatz verwendbar?
- Ist die Geschwindigkeit vergleichbar mit "normalem" Python?

2.) Gibt es Möglichkeiten Pythoncode nach .apk, also unter Android ausführbaren Dateien zu exportieren?
-> im Grunde die selben fragen wie bei 1.).

3.) Ich habe mal Testweise ein Klasse geschrieben, mit der man sich durch einfache Rechenoperationen die verschiedenen Anteile eines E-Zigaretten Liquids berechnen kann
- habt ihr (abgesehen von Kommentaren, da hat ja sowieso jeder seine eigene Philosophie) Vorschläge zu Verbesserung, oder seht ihr grobe Fehler?

Code: Alles auswählen

class Liquid:
    name = ""
    mass = 0
    pg_ratio = 0
    vg_ratio = 0
    water_ratio = 0
    nicotine_ratio = 0
    nicotine_property = 0
    aroma_ratio = []
    aroma_name = []

    def __init__(self, name, mass, pg_ratio, vg_ratio, water_ratio, nicotine_ratio, nicotine_property, aroma_ratio, aroma_name):

        if(mass <= 0):
            raise ValueError('"mass" hast to be >0')
        if(pg_ratio + vg_ratio + water_ratio != 1):
            raise ValueError('pg_ratio + vg_ratio + water_ratio has to be 1')
        if(nicotine_ratio > 1):
            raise ValueError('nicotine_ratio cant be >1')
        if(nicotine_property > 1):
            raise ValueError('nicotine_property cant be >1')
        if(len(aroma_ratio) != len(aroma_name)):
            raise ValueError('every aroma_ratio need a name and otherwise')
        r = 0
        for r in aroma_ratio:
            r+=r
        if(r > 1):
            raise ValueError('all aroma_ratio together cant be >1')

        self.name = name
        self.mass = mass
        self.nicotine_ratio = nicotine_ratio
        self.nicotine_property = nicotine_property
        self.pg_ratio = pg_ratio
        self.vg_ratio = vg_ratio
        self.water_ratio = water_ratio
        self.aroma_ratio = aroma_ratio
        self.aroma_name = aroma_name

    def get_aroma(self):
        aroma = []
        for value in self.aroma_ratio:
            aroma.append(self.mass * value)
        return aroma

    def get_nicotine(self):
        return (self.mass * self.nicotine_ratio) / self.nicotine_property

    def get_pg(self):
        return (self.mass * self.pg_ratio) - self.get_nicotine() - self.get_aroma()

    def get_vg(self):
        return self.mass * self.vg_ratio

    def get_water(self):
        return self.mass * self.water_ratio

#test code
liquid = Liquid("Test", 237, 0.4, 0.4, 0.2, 0.03, 0.5, [0.05, 0.07], ["vanille", "erdbeere"])
print(liquid.get_nicotine())

Code: Alles auswählen

EDIT:
Hab gerade gemerkt, dass ich in den falschen Bereich geposted habe. daher bitte verschieben ;)

Ich bin für jede Hilfe dankbar!
Gruß
Sirius3
User
Beiträge: 17711
Registriert: Sonntag 21. Oktober 2012, 17:20

@isItMe?: Klassenvariablen sind keine Instanzattribute; zumal Du alle Klassenvariablen durch Instanzattribute in __init__ ersetzt - also weg damit. ›if‹ ist keine Funktion, die Klammern sind überflüssig, weg damit. Floatingpoint-Arithmetik ist nicht exakt. Dass die Summe von drei Zahlen exakt 1 ergibt ist unwahrscheinlich. Verhältnisse kann man auch als 1:2:3 angeben, normier die Werte einfach. Die Schleife in Zeile 25 macht nicht das was Du denkst, da ›r‹ immer wieder überschrieben wird; nimm ›sum‹. ›arome_ratio‹ und ›aroma_name‹ sollten keine zwei getrennten Listen sein, sondern ein Wörterbuch. Die get_-Methoden könnten Properties sein.
isItMe?
User
Beiträge: 2
Registriert: Donnerstag 22. Juni 2017, 19:58

Sirius3 hat geschrieben:@isItMe?: Klassenvariablen sind keine Instanzattribute; zumal Du alle Klassenvariablen durch Instanzattribute in __init__ ersetzt - also weg damit. ›if‹ ist keine Funktion, die Klammern sind überflüssig, weg damit. Floatingpoint-Arithmetik ist nicht exakt. Dass die Summe von drei Zahlen exakt 1 ergibt ist unwahrscheinlich. Verhältnisse kann man auch als 1:2:3 angeben, normier die Werte einfach. Die Schleife in Zeile 25 macht nicht das was Du denkst, da ›r‹ immer wieder überschrieben wird; nimm ›sum‹. ›arome_ratio‹ und ›aroma_name‹ sollten keine zwei getrennten Listen sein, sondern ein Wörterbuch. Die get_-Methoden könnten Properties sein.
@Sirius3: Super, da weiß ich, wo ich mich ransetzen kann. Vielen Dank!
BlackJack

@isItMe?:

Ad 1.) py2exe verpackt einfach CPython und den Code in eine EXE. Die Geschwindigkeit *ist* die von ”normalem” Python.

Ad 2.) Solche Möglichkeiten gibt es. Die machen im Grunde etwas ähnliches wie py2exe. Schau mal nach QPython oder Kivy.

Ad 3.) Die Klassenattribute gehören da nicht hin. Insbesondere die Listen sind dort auch ”gefährlich” weil die von allen `Liquid`-Objekten geteilt werden.

Abkürzungen in Namen die nicht allgemein bekannt sind, sollte man vermeiden. `pg_`? `vg_`? Einbuchstabige Namen sind in der Regel auch keine gute Idee. Ausnahmen: `i`, `j`, `k`, als Indexwerte, `x`, `y`, `z` als Koordinaten, und Namen die auf einen Ausdruck beschränkt sind („list comprehensions“, Generatorausdrücke, anonyme Funktionen, …).

Es sind ein paar zu viele Argumente in der `__init__()` und Attribute auf dem Objekt für meinen Geschmack. Vor allem scheinen viele davon Verhältnisse zu sein, da würde sich vielleicht ein eigener Typ und dann eine Liste als Attribut anbieten. Oder ein Wörterbuch das Zutat auf Verhältniss abbildet.

Um ``if``-Bedingungen sollten keine unnötigen Klammern stehen und vor allem sollte ``if`` auch nicht so aussehen als wäre es ein Funktionsaufruf.

„Can't“ schreibt sich mit einem Apostroph.

Die `sum()`-Funktion ist nützlich. :-) Genauso Generatorausdrücke und „list comprehensions“.

`aroma_ratio` und `aroma_name` sind in Einzahl benannt, werden aber an Listen mit mehreren Verhältnissen/Aromanamen gebunden. `get_aroma()` hat das gleiche Problem.

Die beiden Listen enthalten Werte die eigentlich paarweise zusammen gehören. Das ist unübersichtlich und fehleranfällig. Besser wäre eine Liste mit Tupeln die jeweils zusammengehörige Verhältnisse und Namen enthalten. Oder ein Wörterbuch das Namen auf Verhältnisse abbildet.

`get_pg()` hast Du offenbar nicht ausprobiert — das versucht von einer Zahl eine Liste abzuziehen.

Noch ein Hinweis auf den Style Guide for Python Code, dann lande ich als Zwischenergebnis ungefähr hier (ungetestet):

Code: Alles auswählen

class Liquid:
 
    def __init__(
        self,
        name,
        mass,
        pg_ratio,
        vg_ratio,
        water_ratio,
        nicotine_ratio,
        nicotine_property,
        aromas,
    ):
        if mass <= 0:
            raise ValueError('"mass" hast to be >0')
        if pg_ratio + vg_ratio + water_ratio != 1:
            raise ValueError('pg_ratio + vg_ratio + water_ratio has to be 1')
        if nicotine_ratio > 1:
            raise ValueError("nicotine_ratio can't be >1")
        if nicotine_property > 1:
            raise ValueError("nicotine_property can't be >1")
        if sum(ratio for _, ratio in aromas) > 1:
            raise ValueError("all aroma ratios together can't be >1")
 
        self.name = name
        self.mass = mass
        self.nicotine_ratio = nicotine_ratio
        self.nicotine_property = nicotine_property
        self.pg_ratio = pg_ratio
        self.vg_ratio = vg_ratio
        self.water_ratio = water_ratio
        self.aromas = aromas
 
    def get_aromas(self):
        return [self.mass * ratio for _, ratio in self.aromas]
 
    def get_nicotine(self):
        return (self.mass * self.nicotine_ratio) / self.nicotine_property
 
    def get_pg(self):
        return (
            self.mass * self.pg_ratio
            - self.get_nicotine()
            - sum(self.get_aromas())
        )
 
    def get_vg(self):
        return self.mass * self.vg_ratio
 
    def get_water(self):
        return self.mass * self.water_ratio
 

def main():
    liquid = Liquid(
        'Test',
        237,
        0.4,
        0.4,
        0.2,
        0.03,
        0.5,
        [('vanille', 0.05), ('erdbeere', 0.07)],
    )
    print(liquid.get_nicotine())


if __name__ == '__main__':
    main()
Antworten