Bool Object is not callable, benötige Hilfe beim verändern des Codes

Code-Stücke können hier veröffentlicht werden.
Antworten
Tilltall
User
Beiträge: 6
Registriert: Samstag 30. November 2019, 15:32

Hallo zusammen,
ich bin noch ein ziemlicher Python Anfänger und weiß nicht so richtig wie ich meinen Code verändern muss um diesen Error loszuwerden. Vielleicht könnt ihr mir ja ein wenig unter die Arme greifen. Hier ist mein Code:

Code: Alles auswählen

class Drink:
    """
    Klasse Drink
    """
    def __init__(self, temperature):
        """
        Parameter
        Temperature: float
        """
        self._temperature=temperature
    def get_temperature(self):
        """Temperatur"""
        return self._temperature
    def drinkable(self):
        """Trinkbarkeit testen"""
        if float(self._temperature)>=4 and float(self._temperature)<=50:
            return True
        else:
            return False
    temperature=property(get_temperature)
    drinkable=property(drinkable)
d1 = Drink(14)
assert d1.drinkable()
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Du musst die Klammern in der letzten Zeile loswerden. Das property das du da definiert hast (auf ungewöhnlich veraltete Art und Weise) liefert schon ohne Aufruf den Wert zurück.
Tilltall
User
Beiträge: 6
Registriert: Samstag 30. November 2019, 15:32

Danke dir für die schnelle Antwort. Problem ist ich darf die asserts nicht verändern. Die sind vorgegeben und ich muss meinen Code so verändern das die asserts funktionieren.
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Also Hausaufgaben? Dann les dir nochmal meine Antwort durch - ich erwähne ja was dazu führt, das drinkable keine Methode ist. Wenn du dich mit dem Konzept in der Doku vertraut machst, kannst du auch erkennen, wie du es NICHT verwendest.
Tilltall
User
Beiträge: 6
Registriert: Samstag 30. November 2019, 15:32

Okay, ich verstehe leider nicht wirklich was du meinst und wie ich den Code ändern soll... Könntest du vielleicht ein wenig konkreter werden? Aber danke dir auf jeden Fall für deine Antworten!
Benutzeravatar
snafu
User
Beiträge: 6745
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Einfach in der letzten Zeile nach "drinkable" die Klammern wegmachen:

Code: Alles auswählen

# Falsch
assert d1.drinkable()

# Richtig
assert d1.drinkable
Denn durch die Verwendung von property() wird die Rückgabe der Methode bereits beim Ansprechen des Propertys geliefert. Ein Aufruf würde sich dann auf die Rückgabe beziehen. Die ist aber ein Wahrheitswert und somit ihrerseits nicht mehr aufrufbar. Daher die Fehlermeldung.

In Code gesprochen gilt (zumindest hier):

Code: Alles auswählen

d1.drinkable == d1.get_drinkable()
Und dein Versuch wäre demnach:

Code: Alles auswählen

d1.get_drinkable()()
Zuletzt geändert von snafu am Samstag 30. November 2019, 16:43, insgesamt 1-mal geändert.
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

@snafu: hast du gelesen was hier so geschrieben wurde?
Tilltall
User
Beiträge: 6
Registriert: Samstag 30. November 2019, 15:32

Wie schon bereits erwähnt darf ich die asserts bei der Aufgabe nicht verändern. Daher muss es irgendwie möglich sein meine Code so zu verändern das es funktioniert.
Benutzeravatar
snafu
User
Beiträge: 6745
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Die Lösung ist, dass du überhaupt kein property() brauchst. Greif doch einfach direkt auf das Attribut zu.

EDIT: Oder gib der Methode halt den anderen Namen, wenn es als Aufruf gewünscht ist.
Zuletzt geändert von snafu am Samstag 30. November 2019, 16:48, insgesamt 1-mal geändert.
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Ist es auch. Hast du dir wie vorgeschlagen die Dokumentation zu properties auf die ich hinwies durchgelesen? Was daran ist dir unklar?
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

@snafu: das assert darf nicht verändert werden, und stellt einen Methodenaufruf dar. UND das Attribut ist berechnet. Wie soll ‚ Greif doch einfach direkt auf das Attribut zu.‘ da Abhilfe schaffen?
Tilltall
User
Beiträge: 6
Registriert: Samstag 30. November 2019, 15:32

Alles klar jetzt hab ich es auch gechecked! Vielen lieben Dank euch für die schnelle und hiflreiche Lösung des Problems. Ich wünsche euch noch ein schönes restliches Wochenende!
Benutzeravatar
snafu
User
Beiträge: 6745
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

@Tilltall: Wie ich sehe, ist die drinkable()-Methode doch bereits definiert. Warum setzt du an der Stelle überhaupt ein property() ein? Was erhoffst du dir davon bzw was glaubst du, damit zu bewirken?
Tilltall
User
Beiträge: 6
Registriert: Samstag 30. November 2019, 15:32

Ich hatte generell für jeden getter ein property erstellt. Hab bei den asserts nicht gesehen das der Test die Methode schon direkt aufruft.
Benutzeravatar
snafu
User
Beiträge: 6745
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Da warste wohl nicht der Einzige hier... :oops:
Benutzeravatar
__blackjack__
User
Beiträge: 13143
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Tilltall: Die Methode `drinkable()` ist unnötig kompliziert. Erst einmal ist das umwandeln in `float()` überflüssig, denn das Attribut sollte ja bereits eine Zahl sein. Dann würde man da nicht zwei Vergleiche mit ``and`` Verbinden sondern die einfach verketten, so wie man das in der Mathematik auch schreiben würde.

Wenn es einen Getter und/oder ein Property gibt, dann sollte man das auch benutzen. Wobei es auch nicht Getter *und* Property geben sollte, denn dann hat man zwei Wege um das gleiche zu erreichen ohne dass einer einen Vorteil gegenüber dem anderen hätte. Was soll derjenige der diese Objekte benutzt denn dann wählen und warum? Das stiftet nur Verwirrung. Letztendlich würde ich da weder Getter noch Property definieren sondern einfach ein öffentliches Attribut.

Und das ``if``/``else`` ist überflüssig. Die Bedingung beim ``if`` ergibt bereits `True` oder `False`. Genau das kann man dann auch einfach direkt zurückgeben.

Der Docstring der Klasse `Drink` sagt einfach nur "Klasse Drink". Das ist für die Tonne weil das genau Null Mehrwert hat. Der von der `__init__` ist auch nicht so besonders. Das `float` ist nicht so wichtig, denn das sollte auch funktionieren wenn die Temperator als Ganzzahl, Bruch, oder ähnliches angegeben wird. Was für den Leser viel interessanter wäre, ist die Einheit in der die Temperatur angegeben werden soll. Die Zahlen bei `drinkable` lassen vermuten, dass es nicht Kelvin ist und/oder die Zielgruppe für diese Drinks keine Menschen sind. 😉

Ich würde die Docstrings auch in englischer Sprache abfassen, sonst klingt das teilweise doof wenn man die englischen Bezeichner da mit rein bringt.

Komplette Klasse:

Code: Alles auswählen

class Drink:
    def __init__(self, temperature):
        """
        Initialisiere einen `Drink` mit der gegebenen `temperature` in °C.
        """
        self.temperature = temperature

    def drinkable(self):
        """Test ob der Drink eine trinkbare Temperatur hat."""
        return 4 <= self.temperature <= 50
Ist allerdings etwas dünn da nur die Temperatur mit einer einzigen Methode in eine Klasse zu stecken. Dafür hätte auch eine Funktion ausgereicht.
“There will always be things we wish to say in our programs that in all known languages can only be said poorly.” — Alan J. Perlis
Antworten