Objekt hat kein Attribut <hier Namen der Funktion einfügen>

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.
Tobs
User
Beiträge: 65
Registriert: Sonntag 29. September 2013, 11:11

Liebe Pythongemeinde,

ich habe folgendes Problem:

Ich habe eine Klasse definiert, mit mehreren Funktionen.
Wenn ich eine bestimmte Funktion aus dieser Klasse anwende,
behandelt Python sie trotz Klammern dahinter, und einer passenden Anzahl an Attributen,
als Attribut der Klasse und gibt infolge dessen folgenden Fehler aus:

Traceback (most recent call last):
File "E:\Python32\Lösungsentwurf.py", line 15, in <module>
cube.turn(v)
AttributeError: 'Cube' object has no attribute 'turn'

Dabei sollte cube.turn(v) doch als Funktion anerkannt werden, wegen der Klammern dahinter?
Ich habe die Funktion in der Klasse nach weiter oben verschoben, umbenannt und groß-klein-schreibung geändert,
hat alles nicht geholfen. Ich habe noch eine in der Klasse die groß geschrieben ist, könnte das die Ursache sein?
Oder passt es Python einfach nicht, dass die Funktion cube.turn() in sich weiter Funktionen der Klasse aufruft(wie ich es auch gemacht habe)

Ich bekomme diesen Fehler auch bei anderen Programmen häufig, es wäre also gut, wenn ihr mir noch allgemein sagen könntet,
wodurch dieser Fehler ausgelöst wird

Danke im vorraus
BlackJack

@Tobs: Vorweg: Funktionen in Klassen heissen Methoden. Und bei „einer passenden Anzahl an Attributen” meintest Du sicher „Argumente” und nicht „Attribute”.

Methoden werden als Attribute behandelt weil es Attribute sind. Das sind halt Attribute die man aufrufen kann, nach dem man sie vom Objekt abgefragt hat. Nur kommt es bei Dir ja gar nicht bis da hin, denn der Abfruf von `turn` schlägt schon fehl weil das `cube`-Objekt an der Stelle offenbar keine solche Methode hat.

Gross- und Kleinschreibung wird von Python unterschieden, also `turn` ist etwas anderes als `Turn`, oder `tUrN`, …, das sollte also bei der Definition und beim Ab-/Aufruf gleich geschrieben werden. Die Definition innerhalb der Klasse nach oben oder unten zu verschieben sollte keinen Unterschied machen. Das fällt unter die Kategorie, sinnloses, verzweifeltes Rumprobieren. ;-)

Bist Du sicher das hier der richtige `Cube`-Datentyp verwendet wird? Nicht vielleicht eine alte Version davon? Startest Du das Programm neu/frisch, oder vielleicht in einer IDE/Umgebung dir komische Sachen macht?
Tobs
User
Beiträge: 65
Registriert: Sonntag 29. September 2013, 11:11

Erstmal wieder Danke für die Antwort.

Ja ich meine Methoden, und ja ich meine Argumente ;-)

Die Methode turn(anweisung) ist bei mir definitiv in einem anderen Modul vorhanden,
das ich mit from Cube import * importiert habe.

Ich weiß , dass Python Groß- und Kleinschreibung unterscheidet, und habe es
natürlich in beiden Skripten geändert. Ich dachte nur, dass die Groß - und Kleinschreibung vielleicht
eine Ursache für den Fehler gewesen sein könnte, genauso, wie der Name der Methode oder die Tatsache,
dass diese Methode andere Methoden der Klasse in sich aufruft(auf dasselbe Objekt bezogen).

Deshalb stell ich ja die Frage: Ich hab Syntaxgemäß alles richtig gemacht, warum erkennt Python es nicht als Funktion an?

Und wenn ich ein Objekt mit der __init__(self,bla1,bla2,...) initialisiere,
dann besitzt das Objekt doch alle Methoden die ich für dieses Klasse definiert habe?
Tobs
User
Beiträge: 65
Registriert: Sonntag 29. September 2013, 11:11

Hab grade noch herausgefunden, dass auch keine andere Methode dieser Klasse in
meinem 2.Skript funktioniert
BlackJack

@Tobs: Ob Du bei der Definition von der `Cube`-Klasse alles richtig gemacht hast, kann man ohne den Quelltext zu sehen schlecht sagen.

Wenn Du ein `Cube`-Exemplar erstellt hast, dann hat das Objekt alle Methoden die in der Klasse definiert sind.

Also stellen sich drei Fragen: 1. Hast Du die Methoden richtig definiert? 2. ist der `Cube`-Typ tatsächlich der aus dem richtigen Modul? 3. Tritt das Problem bei einem völlig frischen Programmablauf auf?
Tobs
User
Beiträge: 65
Registriert: Sonntag 29. September 2013, 11:11

1. Ja:

Code: Alles auswählen

class Cube():

    def __init__(self,...,...):

        ...

    def turn(eingabe):

        if eingabe == xy:
            anderefunktionausderklasse()
        elif:
            nocheineanderefunktionausderklasse()
        ...
2. Ja von "Cube.py" müsste man mithilfe von "from Cube import *" , wenn es im selben Ordner ist doch Alles bekommen, oder?
3. Ja, ich hab alles nochmal geöffnet und gespeichert, in der Konsole und in IDLE ausgeführt: Jedes mal dieser Fehler

Das Problem ist auch anderen Programmieren passiert. Manche sagen, dass das vom "Programm zum Python Programmieren falsch verstanden wird"

Ich glaub ich installiere einfach mal Python neu und schau, ob sich was geändert hat...
Zuletzt geändert von Anonymous am Freitag 18. April 2014, 15:04, insgesamt 1-mal geändert.
Grund: Quelltext in Python-Code-Tags gesetzt.
Sirius3
User
Beiträge: 17741
Registriert: Sonntag 21. Oktober 2012, 17:20

@Tobs: wie hast Du eigentlich die Instanz »cube« der Klasse »Cube« erzeugt? Hast Du dazwischen »cube« mit irgendeinem anderen Objekt überschrieben? Wenn Du vor dem Attributzugriff Dir die Variable »cube« mit print ausgeben läßt, was erscheint auf dem Bildschirm?

Und noch was: wie sind die Einrückungen. Kann man ja nicht sehen, weil Du die python-Umgebung im Forum nicht benutzt. Wenn »turn« eine Methode sein soll, fehlt zudem »self« als erstes Argument.
Tobs
User
Beiträge: 65
Registriert: Sonntag 29. September 2013, 11:11

Jetzt hab ich beide Dateien vom Desktop runter und in den Python32 ordner gesteckt,
und jetzt kommt gleich in Zeile 1 bei "from Cube import *" der Fehler, dass ihm eine Datei namens
PyShell.py in den idlelibs nicht passt, obwohl die in einem try-block steht -,-
BlackJack

@Tobs: Es fehlt nicht nur `self` als Argument der Methode, sondern wenn das andere da drin auch Methoden von `Cube` sind, dann musst Du die natürlich über `self` referenzieren.

Ad 2.: Das kommt drauf an ob beides in einem Package definiert ist und wie das Arbeitsverzeichnis des Prozesses lautet, und ob im Suchpfad für Module nicht eventuell noch ein anderes `Cube`-Modul vorher gefunden wird.

In den Python-Ordner sollte man nichts kopieren. Da kann man sich wenn's blöd läuft die Installation mit kaputt machen.
Tobs
User
Beiträge: 65
Registriert: Sonntag 29. September 2013, 11:11

Ok, das mit dem Pythonordner merk ich mir, das mit dem "self" stimmt natürlich,
hab ich auch so gemacht, habs aber vergessen hinzuschreiben. Auf der neuen Python-version(3.4)
läuft mein Skript einwandfrei BIS AUF EINE AUSNAHME :roll: :

Die Methode sucht nach einer Lösung. Wenn sie diese gefunden hat, soll sie diese einer globalen Variable zuweisen. Das passiert nicht.
Die Methode soll die Lösung mit print() in der Konsole ausgeben. Das passiert nicht. Alle anderen print-anweisungen funktionieren.

HÄ?
BlackJack

@Tobs: Ohne den Code zu sehen kann man da nicht viel zu sagen. Wobei globale Variablen keine gute Idee sind.
Tobs
User
Beiträge: 65
Registriert: Sonntag 29. September 2013, 11:11

Der Suchzeit nach zu urteilen findet die Funktion auch die richtige Lösung, aber die Methode druckt halt nichts aus
und irgendwie ändert sie auch an der globalen Variable Loesung nichts...
Tobs
User
Beiträge: 65
Registriert: Sonntag 29. September 2013, 11:11

Der Aufbau der Methode ist so:

Code: Alles auswählen

def Funktion(self,arg1,...):

    global Loesung

    <hier wird arg1 verändert>

    if len(arg1) < len(Loesung):       #Das funktioniert nicht :-(
        Loesung = arg1
        print(arg1)
BlackJack

@Tobs: Was heisst „funktioniert nicht”? Es wird ganz einfach die Länge von `arg1` nicht kleiner als die Länge von `Lösung` sein. Mehr kann man da so nicht zu sagen. Lass Dir doch beides mal vor dem ``if`` ausgeben, dann siehst Du ja was für Werte das zu dem Zeitpunkt sind.

Und nochmal: ``global`` sollte man vermeiden. Insbesondere in einer Methode ist das IMHO nicht mehr eine Stilfrage sondern schlicht falsch. Denn ``global`` wird man in der Regel durch objektorientierte Programmierung los. Wenn man das also in einer Methode verwendet, dann stimmt etwas mit dem Entwurf nicht.
Tobs
User
Beiträge: 65
Registriert: Sonntag 29. September 2013, 11:11

Okay, danke. Jetzt gibt es nur noch dieses eine Problem, das mich in den Wahnsinn treibt:

Der If-Block wird ausgeführt, die globale Variable ist oben definiert, aber wenn er die globale Variable
am Ende ausdruckt hat sie wieder den selben Wert wie vor der Funktion (Ist das ein Gesetzt in Python?)

Da du mir von globalen Variablen abrätst, (auch wenn die Funktion 14 Ebenen tief geschachtelt sind)
wie würdest du das Problem lokal lösen. Als Python-Neuling hab ich da keinen Durchblick wie soetwas anderweitig zu bewerkstelligen wäre...
BlackJack

@Tobs: Das kann nicht sein.

Code: Alles auswählen

from __future__ import print_function


solution = [1, 2, 3]


def spam():
    global solution
    arg = [42]
    if len(arg) < len(solution):
        solution = arg
        print(arg)


def main():
    print('solution before:', solution)
    spam()
    print('solution after:', solution)


if __name__ == '__main__':
    main()
Ausgabe:

Code: Alles auswählen

solution before: [1, 2, 3]
[42]
solution after: [42]
Das heisst irgendwo musst Du nach dem ausführen des ``if``-Blocks erneut etwas an die globale Variable zuweisen.
Tobs
User
Beiträge: 65
Registriert: Sonntag 29. September 2013, 11:11

Ich kann mir das einfach nicht erklären. Ich hab sogar die If-Anweisung auf Dauer-true gestellt, aber hat nix gebracht
Darii
User
Beiträge: 1177
Registriert: Donnerstag 29. November 2007, 17:02

Poste doch bitte einfach mal ein lauffähiges Minimalbeispiel mit deinem Problem. Also eines wo du nicht die Hälfte weglässt, die vermutlich das Problem verursacht. Dann brauch sich der arme BlackJack nicht seitenlang Spekulationen hingeben und du nicht umständlich beschreiben wie du denkst wie das Programm funktioniert.
Tobs
User
Beiträge: 65
Registriert: Sonntag 29. September 2013, 11:11

from Cube import *

Variable = [mit so viel sinnlosen Elementen, so dass die erste Lösung immer genommen wird]
cube = Cube()

...Zeug zum ändern der Attribute...

cube.Finde_Loesung([],0,tiefe) #Halt die Funktion

print(Variable)

und die Ausgabe ist immer die Liste mit den vielen Elementen :-(
Tobs
User
Beiträge: 65
Registriert: Sonntag 29. September 2013, 11:11

Code: Alles auswählen

def Finde_Loesung(self,Zuege,Anzahl,Tiefe):

        print("ICH LEBE!")
        global Loesung

        Loesung = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15]
    
        Moeg = ["xt","xf","yt","yf","zt","zf"] #Möglichkeiten:
                                         
        for m in Moeg:
    
            #Abbrechen unötiger Durchläufe:
            if Anzahl > 1:
                if m[1] == ("t") and Zuege[len(Zuege)-1][1] == "t": 
                    continue                                              
                if m[0] == Zuege[len(Zuege)-1] and m[1] != Zuege[len(Zuege)-1][1]: 
                    continue                                                      
            if Anzahl > 2:
                if m == Zuege[len(Zuege)-1] and Zuege[len(Zuege)-1] == Zuege[len(Zuege)-2]: 
                    continue                                                                

            self.turn(m) 
            Zuege.append(m) 
            
            if self.is_solved():
                Loesung = Zuege
                print(Zuege)
            else: 
                if Anzahl != Tiefe-1: 
                    self.Finde_Loesung(Zuege,Anzahl+1,Tiefe)
            self.contra_turn(m)
            Zuege.pop()

            
Das hier ist sogar noch die Version, in der er die neue Lösung in jedem Fall übernimmt,
auch wenn die Liste Loesung kürzer als die Liste Zuege ist
Antworten