VSCode Editor

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
Ben_2003
User
Beiträge: 8
Registriert: Dienstag 22. April 2025, 19:17

Hallo,

im VSCode-Editor wird ein Fehler angezeigt, der beim Aufruf fehlerfrei durchläuft:

Bild

Es geht um die Methode test_subcls(). In dieser Methode wird mySub,greet() als fehlerhaft markiert, obwohl diese Methode in der Klasse vorhanden ist.

Als Fehlerbeschreibung steht: Auf das Attribut „greet“ für die Klasse „Userdata“ kann nicht zugegriffen werden
Das Attribut „greet“ ist unbekannt Pylance(reportAttributeAccessIssue)
(function) greet: Unknown

Bild

Aus welchem Grunde wird in VSCode ein Fehler angezeigt, der keiner ist? Hat jemand eine Vermutung?
Benutzeravatar
__blackjack__
User
Beiträge: 13997
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Ben_2003: Pylance hat anscheinend nicht mal mitbekommen, dass `SubCls` existiert, denn es denkt es handelt sich um ein `Userdata`-Objekt. Kann es sein, dass sich das noch auf eine ältere Version des Quelltextes bezieht und man die Prüfung erneut anwerfen muss, beispielsweise durch speichern der Datei? Ich hätte auch erwartet, dass unnötige f-Zeichenketten eine Warnung bekommen würden.
“The best book on programming for the layman is »Alice in Wonderland«; but that's because it's the best book on anything for the layman.” — Alan J. Perlis
Ben_2003
User
Beiträge: 8
Registriert: Dienstag 22. April 2025, 19:17

Hallo blackjack,

vielen Dank für die Infos.
__blackjack__ hat geschrieben: Mittwoch 28. Mai 2025, 23:02 Pylance hat anscheinend nicht mal mitbekommen, dass `SubCls` existiert, denn es denkt es handelt sich um ein `Userdata`-Objekt.
Die Klasse SubCls ist eine abgeleitete Klasse, die von der Basisklasse Userdata abgeleitet wurde.
__blackjack__ hat geschrieben: Mittwoch 28. Mai 2025, 23:02 Ich hätte auch erwartet, dass unnötige f-Zeichenketten eine Warnung bekommen würden.
Weitere Prüfungen wurden von mir deaktiviert (Deaktivierung von weiteren Erweiterungen), um die falsche Fehlermeldung besser erkennen zu können.
__blackjack__ hat geschrieben: Mittwoch 28. Mai 2025, 23:02 Kann es sein, dass sich das noch auf eine ältere Version des Quelltextes bezieht und man die Prüfung erneut anwerfen muss, beispielsweise durch speichern der Datei?
Das kann nicht sein, da die Dateien immer mit Strg+S bewusst gespeichert werden. Nach dem Speichern werden erst erneut Prüfungen durchgeführt.
Benutzeravatar
__blackjack__
User
Beiträge: 13997
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Ben_2003: Dass `Userdata` die Basisklasse ist weiss ich, aber warum sollte die in der Fehlermeldung auftauchen als wenn es `SubCls` nicht gäbe? Das ist mindestens mal ungewöhnlich, denn bei folgendem Code…

Code: Alles auswählen

class Userdata:
    pass


class SubCls(Userdata):
    pass


SubCls().greet()
…sagt mir Pylint:

Code: Alles auswählen

E1101: Instance of 'SubCls' has no 'greet' member (no-member)
…und Mypy:

Code: Alles auswählen

error: "SubCls" has no attribute "greet"  [attr-defined]
Und das würde ich auch erwarten, denn sonst müsste man ja wissen oder herausfinden, was die Basisklasse ist. In diesem Fall ist das ja nur so offensichtlich weil beide Klassen von Dir selber geschrieben sind. Und was wäre wenn da mehr als zwei Vererbungsebenen involviert wären, oder mehr als eine Basisklasse? Wobei das mit den Ebenen sogar der Fall ist, denn `Userdata` erbt von `object`. Das würde sehr schnell sehr unübersichtlich werden für nicht-triviale Fälle da nicht einfach den direkten Typ in der Fehlermeldung zu haben.

Pylance cached ja anscheinend einiges an Analysedaten. Vielleicht gibt es ja eine Möglichkeit das zu löschen und wirklich komplett frisch analysieren zu lassen‽
“The best book on programming for the layman is »Alice in Wonderland«; but that's because it's the best book on anything for the layman.” — Alan J. Perlis
Ben_2003
User
Beiträge: 8
Registriert: Dienstag 22. April 2025, 19:17

Die Vererbung habe ich nur deswegen verwendet, um in einem Testfall feststellen, zu können, ob nur eine Instanz von einer Klasse existiert.

Das Test-Verfahren wurde zwischenzeitlich verworfen und durch ein Vergleich von beiden Klasen-Variablen ersetzt.

Code: Alles auswählen

clsone = Userdata(...)
clstwo = Userdata(...)

if clsone is clstwo:
    #Test bestanden
else:
    # Test nicht bestanden
Wollte dennoch wissen, wie es mit der Vererbung von Klassen funktioniert, wie es z.B. bei C++ der Fall ist.
Benutzeravatar
snafu
User
Beiträge: 6850
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Ben_2003 hat geschrieben: Donnerstag 29. Mai 2025, 14:07 Wollte dennoch wissen, wie es mit der Vererbung von Klassen funktioniert, wie es z.B. bei C++ der Fall ist.
Die Vererbung läuft so, dass Python den gewünschten Namen zuerst in der abgeleiteten Klasse sucht und anschließend die Vererbungshierarchie nach oben läuft. Den ersten Treffer nimmt Python und gibt dessen Wert zurück bzw. ruft ihn auf. Je nachdem ob man Klammern dahinter gesetzt hat oder nicht.

Letzteres mag etwas banal klingen, aber es ist tatsächlich so, dass der Zugriff auf ein Attribut technisch genau so abläuft wie der Zugriff auf eine Methode. Denn im Falle einer Methode ist die Rückgabe des Attributs ein Funktionsobjekt. Da könnte anstelle der Funktion aber genau so der Integer 123 stehen.

Gemäß des Duck-Typing-Prinzips weiß Python erst durch den (Versuch eines) Aufruf(s), ob es sich tatsächlich um ein "Callable" handelt und würde ggf. einen Fehler werfen. Daher geben nicht vorhandene Methoden auch einen AttributeError und keinen MethodError oder ähnliches zurück.

Code: Alles auswählen

>>> class Foo:
...     def spam(self):
...         return "spam"
...
>>> foo = Foo()
>>> foo.spam
<bound method Foo.spam of <__main__.Foo object at 0x00000191CB59C590>>
>>> foo.spam.__func__
<function Foo.spam at 0x00000191CB5275E0>
Das Method-Objekt hatte ich jetzt übersprungen. Intern wird das aber als Funktion realisiert, die eben als erstes Argument (self) eine Instanz der Klasse mitbekommt.

Das alles wird hier noch sehr viel ausführlicher erklärt:
https://docs.python.org/3/tutorial/classes.html

Übrigens auch recht leicht auf Deutsch zu bekommen. Ich nutze dafür die in Chrome eingebaute Übersetzen-Funktion, die man - wenn es nicht schon von selbst angeboten wird - durch Rechtsklickt über das Kontextmenü erhält.
Benutzeravatar
__blackjack__
User
Beiträge: 13997
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Ben_2003: Die Erklärung ist etwas verwirrend und hat ja auch mit der Meldung nichts zu tun. Das sieht halt danach aus als wenn Du entweder ein Fehler in pylance ist, oder wir irgend etwas wichtiges nicht wissen. Zum Beispiel das da irgendwo noch Typannotationsquatsch ist der für Verwirrung sorgt und beispielsweise `SubCls` zum Alias für `Userdata` macht und deshalb die Typprüfung gar nicht mehr in die tatsächliche `SubCls` schaut, sondern einfach davon ausgeht es ist ein `Userdata`-Objekt, dass diese Methode nicht hat.

“Klassenvariable” ist eine etwas irreführende Bezeichnung für Exemplare.

Kannst Du ein minimales, aber komplettes Beispiel zeigen wo pylance in dieses Problem läuft?
“The best book on programming for the layman is »Alice in Wonderland«; but that's because it's the best book on anything for the layman.” — Alan J. Perlis
Antworten