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

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
Benutzeravatar
nieselfriem
User
Beiträge: 135
Registriert: Sonntag 13. Januar 2013, 16:00

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
__deets__
User
Beiträge: 14494
Registriert: Mittwoch 14. Oktober 2015, 14:29

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.
Benutzeravatar
sls
User
Beiträge: 480
Registriert: Mittwoch 13. Mai 2015, 23:52
Wohnort: Country country = new Zealand();

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.
When we say computer, we mean the electronic computer.
Benutzeravatar
__blackjack__
User
Beiträge: 13004
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@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.
“Most people find the concept of programming obvious, but the doing impossible.” — Alan J. Perlis
Benutzeravatar
snafu
User
Beiträge: 6731
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

__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. ;-)
__deets__
User
Beiträge: 14494
Registriert: Mittwoch 14. Oktober 2015, 14:29

Wo du recht hast.
Benutzeravatar
__blackjack__
User
Beiträge: 13004
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

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()
“Most people find the concept of programming obvious, but the doing impossible.” — Alan J. Perlis
Atalanttore
User
Beiträge: 407
Registriert: Freitag 6. August 2010, 17:03

__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
__deets__
User
Beiträge: 14494
Registriert: Mittwoch 14. Oktober 2015, 14:29

Der Kurs ist ja auch bekannt schlecht. Und ich gebe die Antwort doch. Sogar in deinem Zitat 🤷🏼‍♂️
Atalanttore
User
Beiträge: 407
Registriert: Freitag 6. August 2010, 17:03

Steht ein Unterstrich nicht schon für "protected" oder gibt es diesen Zugriffsmodifikator in Python nicht?

Gruß
Atalanttore
__deets__
User
Beiträge: 14494
Registriert: Mittwoch 14. Oktober 2015, 14:29

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.
Sirius3
User
Beiträge: 17711
Registriert: Sonntag 21. Oktober 2012, 17:20

@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
Atalanttore
User
Beiträge: 407
Registriert: Freitag 6. August 2010, 17:03

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
__deets__
User
Beiträge: 14494
Registriert: Mittwoch 14. Oktober 2015, 14:29

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.
Sirius3
User
Beiträge: 17711
Registriert: Sonntag 21. Oktober 2012, 17:20

@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.
__deets__
User
Beiträge: 14494
Registriert: Mittwoch 14. Oktober 2015, 14:29

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
Atalanttore
User
Beiträge: 407
Registriert: Freitag 6. August 2010, 17:03

Danke für den Link.
Antworten