Seite 1 von 1

TypeError: super() argument 1 must be type, not ...

Verfasst: Dienstag 11. Dezember 2018, 17:26
von nieselfriem
Hallo,

ich ackere gerade ein schönes Aufgabenbuch für Python durch. Dort ist auch das Thema Vererbung dran und ich scheitere Gerade an der ersten Aufgabe. Das Buch ist offenbar für Python 2.x geschreiben worden, so dass ich nicht in der Musterlösung nachgucken kann. Ich versuche es in Python 3.6.3.

Ich habe folgenden Code

Code: Alles auswählen

class Article():
    def __init__(self, articleNumber, price):
        self.__price = price
        self.__articleNumber = articleNumber

    def getPrice(self):
        return self.__price


class Book(Article):
    def __init__(self, articleNumber, price, author, title, year):
        super().__init__(articleNumber, price)
        self.__VAT = 0.07
        self.__author = author
        self.__title = title
        self.__year = year


class DVD(Article):
    def __init__(self, articleNumber, price, name, duration, countryCode):
        super().__init__(articleNumber, price)
        self.__VAT = 0.19
        self.__name = name
        self.__duration = duration
        self.__countryCode = countryCode


class ShoppingCard:
    def __init__(self):
        self.__shoppingCard = []

    def addArticeltoCard(self, artice):
        self.__shoppingCard.append(artice)

    def getBill(self):
        for item in self.__shoppingCard:
            print(type(item))
            print(super(item, self).getPrice())


book1 = Book(12, 12.50, "Der schreiberling", "das leben des X", 1993)
sc = ShoppingCard()
sc.addArticeltoCard(book1)
sc.getBill()
Wenn ich diesen ausführen möchte, bekomme ich die Fehlermeldung

Code: Alles auswählen

[TypeError: super() argument 1 must be type, not Book]
Ich habe da auch recherchiert und habe oft die Info erhalten, dass die Klasse im Oldstyle angelegt worden ist also

Code: Alles auswählen

class Article:
Also habe ich die Masterklasse mit "class Article():" angelegt. Dennoch kommt es zu dieser Meldung. Was mach ich hier falsch?

VG niesel

Re: TypeError: super() argument 1 must be type, not ...

Verfasst: Dienstag 11. Dezember 2018, 17:36
von __deets__
Bitte beim naechsten mal den vollen Traceback, nicht nur eine Zeile. Denn so machst du es unnoetig schwer bei den drei Stellen, an denen super zum Einsatz kommt, die zu finden, an der dein Fehler ist.

Und das ist bei getPrice der Fall - und da muss man auch einfach mal fragen: wozu versurchst du da super einzusetzen?

Dann noch ein paar Anmerkungen:

- lass das mit den doppelten Unterstrichen. Wenn das aus deinem Buch ist, dann ist das mal wieder eines der vielen Buecher, die das falsch machen. Das ist NICHT fuer "private" attribute. Sondern gegen Namenskollisionen. Ein _ reicht.
- die Namen sind nicht pythonisch. Attribute und Variablen schreibt man shopping_cart, nicht shoppingCart.
- es ist ein cart, also ein Korb. Nicht card, eine Karte.

Re: TypeError: super() argument 1 must be type, not ...

Verfasst: Dienstag 11. Dezember 2018, 17:37
von sls
Du willst den Preis vom Objekt Item, warum nicht einfach so: print(item.getPrice())

Mit super() möchte man doch eher bestehende Methoden und Attribute von Elternklassen übernehmen.

Re: TypeError: super() argument 1 must be type, not ...

Verfasst: Dienstag 11. Dezember 2018, 18:25
von __blackjack__
@nieselfriem: Ich würde von `super()` komplett die Finger lassen. Das Problem was das löst kann sowieso nur bei Mehrfachvererbung auftreten, von der ich auch die Finger lassen würde. Lesestoff: Python's Super is nifty, but you can't use it.

Ich würde sagen bei den meisten `__*` würde ich sogar gar keinen Unterstrich schreiben, also nicht einmal einen. Denn das sind ja alles Attribute bei denen man als nächstes mindestens einen Getter schreiben würde um damit dann auch etwas machen zu können.

Edit: Bei `getBill()` würde man erwarten eine Rechnung als Rückgabewert zu bekommen und nicht das eine per `print()` ausgegeben wird.

Re: TypeError: super() argument 1 must be type, not ...

Verfasst: Dienstag 11. Dezember 2018, 18:33
von snafu
__deets__ hat geschrieben: Dienstag 11. Dezember 2018, 17:36 - es ist ein cart, also ein Korb. Nicht card, eine Karte.
Nur um mal klugzuscheißen: Cart heißt Wagen (siehe Go-Kart, Kart-Rennbahn, ...), demnach steht Shopping Cart für Einkaufswagen. Die Übersetzung als Warenkorb ist nur im übertragenen Sinne so, weil es im Deutschen halt üblicherweise so genannt wird. Korb an sich heißt normalerweise Basket. ;-)

Re: TypeError: super() argument 1 must be type, not ...

Verfasst: Dienstag 11. Dezember 2018, 18:48
von __deets__
Wo du recht hast.

Re: TypeError: super() argument 1 must be type, not ...

Verfasst: Dienstag 11. Dezember 2018, 18:58
von __blackjack__
Ich benutze heutzutage ja gerne das `attr`-Modul:

Code: Alles auswählen

#!/usr/bin/env python3
from attr import attrib, attrs


@attrs(frozen=True)
class Article:
    VAT = None
    
    article_number = attrib()
    price = attrib()
    

@attrs
class Book(Article):
    VAT = 0.07
    
    author = attrib()
    title = attrib()
    year = attrib()


@attrs
class DVD(Article):
    VAT = 0.19
    
    name = attrib()
    duration = attrib()
    country_code = attrib()
    

class ShoppingCart:
    
    def __init__(self):
        self.items = list()
    
    def __len__(self):
        return len(self.items)
    
    def __iter__(self):
        return iter(self.items)

    def add_article(self, article):
        self.items.append(article)

    def print_bill(self):
        for item in self:
            print(type(item), item.price)


def main():
    book = Book(12, 12.50, 'Der Schreiberling', 'Das Leben des X', 1993)
    cart = ShoppingCart()
    cart.add_article(book)
    cart.print_bill()


if __name__ == '__main__':
    main()

Re: TypeError: super() argument 1 must be type, not ...

Verfasst: Samstag 2. Februar 2019, 19:55
von Atalanttore
__deets__ hat geschrieben: Dienstag 11. Dezember 2018, 17:36 - lass das mit den doppelten Unterstrichen. Wenn das aus deinem Buch ist, dann ist das mal wieder eines der vielen Buecher, die das falsch machen. Das ist NICHT fuer "private" attribute. Sondern gegen Namenskollisionen. Ein _ reicht.
Es gibt nicht nur Bücher, die das falsch machen, sondern auch mindestens eine Webseite eines Dipl.-Informatikers.

Wie macht man private Attribute in Python richtig?

Gruß
Atalanttore

Re: TypeError: super() argument 1 must be type, not ...

Verfasst: Samstag 2. Februar 2019, 19:57
von __deets__
Der Kurs ist ja auch bekannt schlecht. Und ich gebe die Antwort doch. Sogar in deinem Zitat 🤷🏼‍♂️

Re: TypeError: super() argument 1 must be type, not ...

Verfasst: Samstag 2. Februar 2019, 20:02
von Atalanttore
Steht ein Unterstrich nicht schon für "protected" oder gibt es diesen Zugriffsmodifikator in Python nicht?

Gruß
Atalanttore

Re: TypeError: super() argument 1 must be type, not ...

Verfasst: Samstag 2. Februar 2019, 20:04
von __deets__
Ich schreibe doch explizit "private". Wie kommst du also auf protected? Und eine solche feingranulare Unterscheidung macht Python einfach nicht. Da man eh IMMER an alles rankommt, __-Attribute inklusive.

Re: TypeError: super() argument 1 must be type, not ...

Verfasst: Samstag 2. Februar 2019, 20:06
von Sirius3
@Atalanttore: es gibt gar keinen Zugriffsschutz in Python. Ist auch gar nicht nötig, wenn man sich an die einfache Konvention hält, nicht auf _-Attribute zuzugreifen

Re: TypeError: super() argument 1 must be type, not ...

Verfasst: Samstag 2. Februar 2019, 20:09
von Atalanttore
Dann haben die Ersteller meiner bisherigen Python-Tutorials immer den gleichen Fehler beim Zugriffsschutz gemacht. :roll:

Ein weiteres fehlerhaftes Python-Tutorial gibt es hier ...

Gruß
Atalanttore

Re: TypeError: super() argument 1 must be type, not ...

Verfasst: Samstag 2. Februar 2019, 20:16
von __deets__
Es ist dir freigestellt, zu vertrauen, wem du magst. Die Meinung hier (und im Rest der Community) ist klar: _ reicht fuer alles, was "schuetzenswert" respektive nicht-oeffentlich ist. Denn wirklichen Schutz gibt es nicht:

Code: Alles auswählen

class Unsinn:
    def __init__(self):
        self.__so_geheim = 1000

u = Unsinn()
print(u._Unsinn__so_geheim)
Doppelte Unterstriche verhindern Namenskollisionen. Das war's. Und wenn ich mir die restlichen Codeschnipsel auf dieser Seite anschaue, dann sehe ich falsche Namenskonventionen fuer Methoden, getter und setter, __del__ zu erwaehnen statt es einfach als Fortgeschrittenes Thema wegzulassen... dann mag der Herr in diversen Sprachen programmieren koennen. Idiomatisch Python aber nicht.

Re: TypeError: super() argument 1 must be type, not ...

Verfasst: Samstag 2. Februar 2019, 20:25
von Sirius3
@Atalanttore: der zweite von Dir verlinkte Artikel erklärt das ja ganz richtig, versucht aber typische Eigenschaften wie private oder protected aus anderen Sprachen nach Python zu übersetzen. Fehlerhaft ist das nicht. Die Meinung hier im Forum ist aber die Wörter einfach ganz zu vermeiden.

Re: TypeError: super() argument 1 must be type, not ...

Verfasst: Samstag 2. Februar 2019, 20:51
von __deets__
Ich finde auch den zweiten Artikel nicht wirklich substantiell besser, denn er erwaehnt nicht die legitimenen Einsatzzwecke fuer __ - Verhinderung von Namenskollisionen. Und macht immer noch die unsaegliche "private/protected"-Geschichte auf.

Der hier ist IMHO besser: https://hackernoon.com/understanding-th ... 9d1a029edc

Re: TypeError: super() argument 1 must be type, not ...

Verfasst: Samstag 2. Februar 2019, 20:57
von Atalanttore
Danke für den Link.