check if variable none

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
Dani*B
User
Beiträge: 8
Registriert: Montag 6. April 2020, 18:39

Hallo zusammen,

ich habe ein Problem und schon mehr oder weniger alles versucht aber ich komm nicht weiter.

Wir haben für eine Übung einen Zufallsgenerator programmiert bekommen, welchen wir verwenden müssen. Dieser liefert mehrere Werte. Der erste hat eine andere Bedeutung wie die anderen Werte. Hab ich alles aufgesplittet und funktioniet auch alles so wie es soll.
Nun kann es aber auch passieren, dass der Generator mal "None" liefert, dann bekomme ich natürlich immer einen Fehler in der Ausgabe.

Kann mir da vielleicht wer helfen wie ich das abfangen kann? Ich
Meine Werte habe ich in eine Liste gespeichert. Hätte dann eben schon versucht mit
if (results == 'None'):
print ("Keine Werte erhalten")
usw... alles in verschiedensten Varianten.

Danke im Voraus
Daniela
__deets__
User
Beiträge: 14536
Registriert: Mittwoch 14. Oktober 2015, 14:29

Die Pruefung auf None erfolgt mit is.

Code: Alles auswählen

a = None
if a is None:
    print('treffer')
Benutzeravatar
noisefloor
User
Beiträge: 3856
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: WW
Kontaktdaten:

Hallo,

ergänzend zu __deets__:

Code: Alles auswählen

if (results == 'None'):
Ist sowie so falsch, weil du None in Hochkommas hast, womit gegen der String 'None' geprüft wird und _nicht_ gegen das None-Objekt.

Gruß, noisefloor
Benutzeravatar
__blackjack__
User
Beiträge: 13100
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Wobei das hier ein Fall zu sein scheint bei dem man einen Vergleichsoperator auch ganz weglassen kann:

Code: Alles auswählen

if not results:
   print("Keine Werte erhalten") 
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Dani*B
User
Beiträge: 8
Registriert: Montag 6. April 2020, 18:39

danke schon mal aber so gehts leider auch nicht. Ich habe euch hier mal kurz einen Auszug aus dem kopiert wie die Zahlen kommen und was genau mein Fehler ist.

Das ist die Fehlermeldung die ich erhalte:
TypeError: 'NoneType' object is not subscriptable

so bekomme ich die Zahlen aus dem Zufallsgenerator aus der Methode PMvalues(): Die laufen dann direkt in meine power_on_selfcheck() Methode rein.
(0, [800000.0, 1200000.0, 1800000.0, 1000000.0, 1400000.0])
wie gesagt, die erste splitte ich ab und die restlichen sind dann ja ein Tupel welches ich auch umwandle - das funktioniert alles.

oder ich bekomme eben ein None zurück
__deets__
User
Beiträge: 14536
Registriert: Mittwoch 14. Oktober 2015, 14:29

Doch, das geht schon so:

Code: Alles auswählen

import random

ergebnis = (0, [1, 2, 3]) if random.random() > .5 else None
if ergebnis is not None:
    erster, rest = ergebnis
Benutzeravatar
__blackjack__
User
Beiträge: 13100
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Dani*B: ”Absplitten” ist sicher nicht die richtige Beschreibung dafür was Du machst, und die restlichen sind kein Tupel sondern eine Liste. Wenn das jetzt an den Namen ``results`` gebunden ist, wirst Du ja wahrscheinlich per ``results[1]`` auf die Liste zugreifen. Und dabei die Ausnahme bekommen wenn `results` den Wert `None` hat. Und dagegen hilft das prüfen mit ``if``, entweder explizit gegen `None` oder eben das ``if not results:`` um den Fall zu behandeln, dass es ”keine Ergebnisse gab”.

Wenn es bei Dir trotzdem zu so einem Fehler kommt, dann versuchst Du aus irgendwelchen Gründen trotz Test doch auf `None` wie auf ein Tupel zuzugreifen. Darfst Du halt nicht machen.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Sirius3
User
Beiträge: 17747
Registriert: Sonntag 21. Oktober 2012, 17:20

Was Du da falsch machst, können wir nicht sagen, solange wir nicht den passenden Code dazu kennen. Was ist PMvalues? Und was macht power_on_selfcheck?
Dani*B
User
Beiträge: 8
Registriert: Montag 6. April 2020, 18:39

def PMvalues():
lamp_current = randint(0, 1) * randint(390, 510)
if lamp_current == 0:
lamp_current = randint(0, 1) * randint(400, 500)
detector_signal = [(randint(8, 21)/10)*10**6, (randint(8, 21)/10)*10**6, (randint(8, 21)/10)*10**6, (randint(8, 21)/10)*10**6, (randint(8, 21)/10)*10**6]
return lamp_current, detector_signal
- dies ist die Methode, die wir von unseren Übungleitern erhalten haben und mit der wir arbeiten müssen. Sie liefert uns Werte für eine Lampte und Detector-Signale zurück-

***
(0, [900000.0, 1700000.0, 1600000.0, 900000.0, 1700000.0])
so kommen dann die Werte raus

***

power_on_selfcheck() - wurde von uns geschrieben arbeitet genau mit diesen Werten dann.
wenn der Lampenwert falsch bzw. über einem gewissen Bereich liegt ist die Lampfe defekt
liegt eines der Signale nicht im Bereich muss auch ein Fehler ausgegeben werden.
Mir ist bewusst, dass es sicherlich schöner geht, diese Methode zu schreiben aber sie funktioniert und ich habe es für den Anfang gut verstanden. Solange ich eben Werte erhalte funktioniert es einwandfrei und macht in der Ausgabe alles was es soll.
Aber wenn ich keine Werte erhalte eben nicht.

def power_on_selfcheck(self):
errormessages = []
results = PMvalues()
result1 = results[0]
result2 = results[1]
a,b,c,d,e = result2
min = 0
max = 0
if (a < b):
min = a
else: min = b
if (min > c):
min = c
if (min > d):
min = d
if (min > e):
min = e
if (a > b):
max = a
else: max = b
if (max < c):
max = c
if (max < d):
max = d
if (max < e):
max = e
if (result1 == 0 | result1 < 400 or result1 > 500):
errormessages.append("Error 1: Lamp defective!")
if (min < 890000.0 or min > 2100000.0 or max < 890000.0 or max > 2100000.0):
errormessages.append("Error 2: Detector defective or beam blocked!")
return errormessages

naja und die verschiedenen Methoden funktionieren leider noch nicht oder ich hab es noch falsch eingegeben. Sorry, ich mach das noch nicht so lange und ist nicht immer so einfach :x :|
Benutzeravatar
__blackjack__
User
Beiträge: 13100
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Dani*B: Und wo testest Du da jetzt den Rückgabewert von `PMValues()`? Du hast ja gesagt Du machst das und es funktioniert nicht. In dem gezeigten Code machst Du es gar nicht, dann kann es natürlich nicht funktionieren.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Benutzeravatar
/me
User
Beiträge: 3555
Registriert: Donnerstag 25. Juni 2009, 14:40
Wohnort: Bonn

Bitte den Code in Code-Tags setzen. Ohne die Code-Tags ist er aufgrund der fehlenden Einrückungen in der Darstellung nicht sauber zu lesen.

Du hast Pythons eingebaute Funktion min aber ziemlich übel nachprogrammiert. Das geht deutlich einfacher als du das gemacht hat.

Code: Alles auswählen

>>> values = [9, 3, 7, 2, 5]
>>> min_value = min(values)
>>> print(min_value)
2
Und was hindert dich daran, nach `results = PMvalues()` abzufragen, ob `results` gleich `None` ist?

Bei den Klammern verwendest du auch zu viele. `if` ist kein Funktionsaufruf und benötigt keine Klammern.

Code: Alles auswählen

# so nicht
if (a < b):

# stattdessen so
if a < b:
Ich zweifele auch noch daran, ob du wirklich das willst was diese Zeile tut:

Code: Alles auswählen

if (result1 == 0 | result1 < 400 or result1 > 500):
Das Pipe-Zeichen ist kein logisches "oder", sondern binär.
Zuletzt geändert von /me am Mittwoch 8. April 2020, 13:51, insgesamt 1-mal geändert.
Dani*B
User
Beiträge: 8
Registriert: Montag 6. April 2020, 18:39

Ich weiß, dass es dies direkt von Python gibt. Wir dürfen dies aber ausdrücklich nicht verwenden.
Ja das mit der Abfrage hätte ich versucht hat aber auch nicht zu dem gewünschten Ergebnis geführt...

***


naja, ich nutze dann die "Ergebnisse" der power_on_selfcheck() unter anderem in meiner main....

ein_photospektrometer = Spektrometer("lab:pm_1",PSM, datetime.date(2019,4,6),"Bau B, Labor 1, Bank002","UV","VIS","IR")
print("Chemische Analyse: ", ein_photospektrometer)
print([ein_photospektrometer])
protokoll = ein_photospektrometer.power_on_selfcheck()
checkup = ein_photospektrometer.start_checkup(datetime.date.today(),'CH','repair','power cord deffect', protokoll)
print('')
ein_photospektrometer.checked = checkup
print(checkup)

***

wenn ich Werte erhalte, dann bekomme ich auch eine passende Ausgabe wie gewünscht.

Chemische Analyse: MedicalProduct((devid = lab:pm_1, devtype = Photospektrometer, lastcheck = 2019-04-06, location = Bau B, Labor 1, Bank002),[IR, UV, VIS])
[MedicalProduct((devid = lab:pm_1, devtype = Photospektrometer, lastcheck = 2019-04-06, location = Bau B, Labor 1, Bank002),[IR, UV, VIS])]

{'date': datetime.date(2020, 4, 8), 'tester': 'CH', 'type': 'repair', 'purpose': 'power cord deffect', 'test-report': {'message': ['Error 1: Lamp defective!']}, 'signature': None}

***

aber wenn eben nichts von der PMvales kommt, dann bekomme ich die Fehlermeldung:

result1 = results[0]

TypeError: 'NoneType' object is not subscriptable
Benutzeravatar
/me
User
Beiträge: 3555
Registriert: Donnerstag 25. Juni 2009, 14:40
Wohnort: Bonn

Dani*B hat geschrieben: Mittwoch 8. April 2020, 13:48 Ich weiß, dass es dies direkt von Python gibt. Wir dürfen dies aber ausdrücklich nicht verwenden.
Das ist eine völlig sinnfreie Beschränkung in der Aufgabenstellung. Aber selbst dann verwendet man doch eine Schleife.
Dani*B hat geschrieben: Mittwoch 8. April 2020, 13:48 aber wenn eben nichts von der PMvales kommt, dann bekomme ich die Fehlermeldung:

result1 = results[0]

TypeError: 'NoneType' object is not subscriptable
Du musst ja auch vorher abfragen ob results gleich None ist.
Benutzeravatar
__blackjack__
User
Beiträge: 13100
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Dani*B: Anmerkungen zum Code: Eingerückt wird vier Leerzeichen pro Ebene.

Namen werden `kein_mit_unterstrichen` geschrieben. Ausnahmen sind Konstanten (KOMPLETT_GROSS) und Klassen (MixedCase).

Namen sollten keine kryptischen Abkürzuen enthalten, in der Regel nicht nur aus Einzelbuchstaben bestehen, und nicht durchnummeriert werden. Funktionen werden nach der Tätigkeit benannt die sie durchführen. `PMvalues` beschreibt keine Tätigkeit und nimmt einem den offensichtlichen Namen für das Ergebnis dieser Funktion weg.

Die Funktion gibt entweder ein Ergebnis zurück oder *implizit* den Wert `None`. Das sollte so nicht passieren. Falls `None` ein regulärer Rückgabewert ist, dann sollte das auch deutlich mit einem *expliziten* ``return None`` in der Funktion stehen.

Den Ausdruck für den Zufalls-Signalwert sollte man da nicht tatsächlich fünf mal im Code stehen haben. Dafür gibt es Schleifen, oder in diesem Fall eine „list comprehension“.

`result1` und `result2` sind sauschlechte Namen für `lamp_current` und `detector_signal`.

Um ``if``-Bedingungen gehören keine unnötigen Klammern und auch bei nur einer Anweisung gehört das nicht hinter den Doppelpunkt sondern in einen eigenen Block.

Ich mag die ganzen ``if``\s jetzt auch gar nicht nachvollziehen, sondern gehe einfach mal davon aus das Du die `min()` und `max()`-Funktion verwenden wolltest, statt das da manuell so umständlich zu lösen.

Der Bitoperator ``|`` sollte nicht als logisches ``or`` missbraucht werden. Neben der schlechten Lesbarkeit hat der einen anderen Operatorvorrang und wird auch immer vollständig ausgewertet.

Bei den ganzen ``<``/``>``-Vergleichen würde man Operatorverkettung verwenden um das kürzer und deutlicher zu schreiben.

`min` und `max` beide gehen Ober- und Untergrenze zu testen macht nicht so viel Sinn.

`power_on_selfcheck()` ist keine Methode sondern eine Funktion die in eine Klasse gesteckt wurde. Entweder sollte man das als Funktion herausziehen, oder mit `staticmethod()` deutlich machen, dass man das absichtlich macht.

Ungetestet:

Code: Alles auswählen

def get_pm_values():
    if randint(0, 1) != 0:
        return None

    lamp_current = randint(0, 1) * randint(400, 500)
    detector_signal = [(randint(8, 21) / 10) * 10 ** 6 for _ in range(5)]
    return lamp_current, detector_signal


def power_on_selfcheck():
    pm_values = get_pm_values()
    #
    # FIXME Check `pm_values` against `None`.
    #
    lamp_current, detector_signal = pm_values
    errormessages = []
    if not 400 <= lamp_current <= 500:
        errormessages.append("Error 1: Lamp defective!")
    if min(detector_signal) < 890_000 or max(detector_signal) > 2_100_000:
        errormessages.append("Error 2: Detector defective or beam blocked!")
    return errormessages
Da ist jetzt immer noch der Fehler drin. Bitte fixen.

Edit: Warum gibt `get_pm_values()` eigentlich mit einer 50%igen Wahrscheinlichkeit `None` zurück? Was soll das bedeuten?
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Dani*B
User
Beiträge: 8
Registriert: Montag 6. April 2020, 18:39

Namen werden `kein_mit_unterstrichen` geschrieben. Ausnahmen sind Konstanten (KOMPLETT_GROSS) und Klassen (MixedCase).
- > weiß ich, es steht aber leider so in der Aufgabenstellung und deshalb ist die Funktion auch so benannt

Namen sollten keine kryptischen Abkürzuen enthalten, in der Regel nicht nur aus Einzelbuchstaben bestehen, und nicht durchnummeriert werden. Funktionen werden nach der Tätigkeit benannt die sie durchführen. `PMvalues` beschreibt keine Tätigkeit und nimmt einem den offensichtlichen Namen für das Ergebnis dieser Funktion weg.
-> wie schon geschrieben, ist dies eine vorgefertigte Version die wir so verwenden müssen. Daher kann ich nichts ändern...

min und max (von Python direkt) dürfen wir nicht verwenden...

Edit: Warum gibt `get_pm_values()` eigentlich mit einer 50%igen Wahrscheinlichkeit `None` zurück? Was soll das bedeuten?
-> warum das so ist, kann ich leider auch nicht sagen, da diese eben so vorgegeben wurde. Find ich auch ziemlich blöd das ganze...

Ich danke euch auf jeden Fall allen für die ganzen Antworten und eure Zeit.
Sirius3
User
Beiträge: 17747
Registriert: Sonntag 21. Oktober 2012, 17:20

@Dani*B: auch wenn ihr min und max aus irgendeinem Grund nicht verwendet dürft, so programmiert man trotzdem selbst min und max als eigene Funktion. Das so im Quelltext stehen zu haben, ist einfach nur unübersichtlich.

Code: Alles auswählen

def min(iterable):
    iterable = iter(iterable)
    result = next(iterable)
    for value in iterable:
        if result > value:
            result = value
    return result
Das None soll wahrscheinlich einen Messfehler simulieren. Dann sollte man aber nach einer Pause noch mehrmals versuchen, doch ein Messsignal zu bekommen.
Benutzeravatar
__blackjack__
User
Beiträge: 13100
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Dani*B: Wenn die `PMvalues()`-Funktion tatsächlich so vorgegeben wurde, dann würde ich mal sagen dass die unvollständig oder sonst irgendwie fehlerhaft ist. Denn alleine schon das Vorgehen beim auswürfeln der 50%igen Wahrscheinlichkeit das `None` zurückgegeben wird, ist nicht rational erklärbar. Das Original sieht ja so aus (Ausdruck für Definition `detector_signal` ausgenommen, weil nicht relevant):

Code: Alles auswählen

def PMvalues():
    lamp_current = randint(0, 1) * randint(390, 510)
    if lamp_current == 0:
        lamp_current = randint(0, 1) * randint(400, 500)
        detector_signal = ...
        return lamp_current, detector_signal
Der am Anfang erzeugte `lamp_current` wird nur in der ``if``-Bedingung verwendet, das heisst man kann den Ausdruck auch dort gleich einsetzen:

Code: Alles auswählen

    if randint(0, 1) * randint(390, 510) == 0:
Das Ergebnis der linken Seite der Vergleichsoperation wird nur auf Gleichheit gegen 0 geprüft. Ob die linke Seite 0 ergibt hängt aber nur von dem ersten `randint()`-Aufruf ab, und überhaupt nicht von dem zweiten `randint()`-Aufruf. Warum steht der da also, und warum gerade mit *den* Grenzwerten? Das ist komplett sinnfrei und hat genau den gleichen Effekt wie:

Code: Alles auswählen

    if randint(0, 1) == 0:
Und da 0 im boole'schen Kontext unwahr und jede andere ganze Zahl wahr ist, kann man das sogar auf folgendes verkürzen:

Code: Alles auswählen

    if randint(0, 1):
Im Kontext der Funktion:

Code: Alles auswählen

def PMvalues():
    if randint(0, 1):
        lamp_current = randint(0, 1) * randint(400, 500)
        detector_signal = ...
        return lamp_current, detector_signal
Und es fehlt das explizite behandeln des ``else``-Falles, damit der Leser weiss, dass die Funktion nicht unvollständig ist, und das `None` tatsächlich, absichtlich als Rückgabewert gewählt wurde:

Code: Alles auswählen

def PMvalues():
    if randint(0, 1):
        lamp_current = randint(0, 1) * randint(400, 500)
        detector_signal = ...
        return lamp_current, detector_signal
    else:
        return None
So müsste die Funktion eigentlich aussehen damit ich persönlich *nicht* beim Autor nachfragen würde warum die am Anfang so unsinnig und am Ende offenbar noch nicht fertig ist.

Was `None` als Rückgabewert bedeuten soll weisst Du aber schon, oder? Falls nicht, wie gehst Du damit dann um? Und kann es nicht doch sein, dass das ein Fehler in der `PMvalues()` ist, dass die `None` zurückgeben kann?

@Sirius3: Bei 50% Messfehler würde ich ja die (simulierte) Hardware zurückgehen lassen wollen. 🙂

Edit: Und bei den 50% wo die Messung geht, ist dann in 50% der Fälle die Lampe im Gerät kaputt.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Antworten