Klassenattributte umbn(__init__ aufruf...was ruft er da auf)

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.
grandma
User
Beiträge: 26
Registriert: Mittwoch 30. Mai 2007, 15:04

Ich will ein Objekt erzeugen mit

chart = MyChart()

die Init von MyChart enthält nur self als Argument.

In der Init selber werden keine weiteren Objekte (ausser arrays) erzeugt.

Trotzdem kriege ich folgende Fehlermeldung:

"__init__ takes exactly 2 arguments 1 given"



Wenn ich in die init 2 dummy argumente reinmache, so kommt immer noch die selbe Meldung.
=> es ist nicht diese init die einen Fehler wirft...welche dann??

Irgendwelche Ideen?
Zuletzt geändert von grandma am Dienstag 19. Juni 2007, 11:23, insgesamt 1-mal geändert.
Benutzeravatar
birkenfeld
Python-Forum Veteran
Beiträge: 1603
Registriert: Montag 20. März 2006, 15:29
Wohnort: Die aufstrebende Universitätsstadt bei München

Ohne Code wohl kaum...
Dann lieber noch Vim 7 als Windows 7.

http://pythonic.pocoo.org/
grandma
User
Beiträge: 26
Registriert: Mittwoch 30. Mai 2007, 15:04

Code: Alles auswählen

class MyChart(object):
    
    def __init__(self):
        self.rawData = []
        self.calculatedData = []
        self.lowerLimit = []
        self.upperLimit = []
        self.target = []
        self.upperSpec = None
        self.lowerSpec = None
        self.specTarget = None
        self.ooc = []
        #self.db = queue.db
        #self.calcData()
        self.failures = []
aufruf wie gesagt mit chart = MyChart()
mawe
Python-Forum Veteran
Beiträge: 1209
Registriert: Montag 29. September 2003, 17:18
Wohnort: Purkersdorf (bei Wien [Austria])

Also bei mir kommt da keine Fehlermeldung. Ich wüsste auch nicht warum.
grandma
User
Beiträge: 26
Registriert: Mittwoch 30. Mai 2007, 15:04

Code: Alles auswählen

try:
        chart = MyChart()
    except Exception, e:
        f = open("except.txt", "wr")
        f.write(str(e))
        f.close()

Also das ist der genaue Aufruf

Der Aufruf erfolgt auch aus einem externe Methodenobjekt in Zope wenn das eine Rolle spielt. (der Zugriff auf andere Klassen mit daraus funktioniert)
Y0Gi
User
Beiträge: 1454
Registriert: Freitag 22. September 2006, 23:05
Wohnort: ja

grandma hat geschrieben:Wenn ich in die init 2 dummy argumente reinmache, so kommt immer noch die selbe Meldung.
=> es ist nicht diese init die einen Fehler wirft...welche dann??
Das verrät der komplette Traceback.

Möglicherweise ist da eine veraltete Version im Spiel.
grandma
User
Beiträge: 26
Registriert: Mittwoch 30. Mai 2007, 15:04

Ich habe eigentlich gar keinen Traceback, das mit der Exception in ein File schreiben ist auch nur einen Notlösung um überhaupt eine Fehlermeldung zu kriegen.
grandma
User
Beiträge: 26
Registriert: Mittwoch 30. Mai 2007, 15:04

Code: Alles auswählen

Traceback (most recent call last):
  File "/usr/local/Zope-2.9.3/Extensions/web.py", line 81, in go
    chart = MyChart()
TypeError: __init__() takes exactly 2 arguments (1 given)
Benutzeravatar
Sr4l
User
Beiträge: 1091
Registriert: Donnerstag 28. Dezember 2006, 20:02
Wohnort: Kassel
Kontaktdaten:

Code: Alles auswählen

import sys
import traceback
"".join(
    traceback.format_exception( 
        sys.exc_type,sys.exc_value,sys.exc_traceback))
Wenn du den Inhalt dieses Code Mixes in die Datei schreibst bekommst du ein Traceback.
Eine absolute Geek Methode wäre es __init__ so zu verändern das es 2 Variablen entgegennimmt und man lässt sich die zweite einmal ausgeben :-)

*edit*

wie ich sehe hast du gerade die Traceback hin bekommen und wie ich sehe setzt du Zope ein. Kenne ich so nicht, aber bei ModPython ist es so, das man immer in einer Funktion als erstes die Variable `req` entgegen nimmt, so etwas wird es dann bei Zope auch sein.
rolgal_reloaded
User
Beiträge: 312
Registriert: Dienstag 24. Oktober 2006, 19:31

grandma hat geschrieben:

Code: Alles auswählen

class MyChart(object):
    
    def __init__(self):
        self.rawData = []
        self.calculatedData = []
        self.lowerLimit = []
        self.upperLimit = []
        self.target = []
        self.upperSpec = None
        self.lowerSpec = None
        self.specTarget = None
        self.ooc = []
        #self.db = queue.db
        #self.calcData()
        self.failures = []
Bei der Instanzierung werden für jede Instanz alle diese Attribute mit dem Boolwert False gesetzt. Wenn das so bleiben soll, würde ich sie als Klassenattribute setzen.

LG

rolgal_reloaded
BlackJack

Dann teilen sich alle Objekte dieses Typs die Attribute. Das ist *sehr* wahrscheinlich nicht das gewünschte Verhalten.
rolgal_reloaded
User
Beiträge: 312
Registriert: Dienstag 24. Oktober 2006, 19:31

BlackJack hat geschrieben:Dann teilen sich alle Objekte dieses Typs die Attribute. Das ist *sehr* wahrscheinlich nicht das gewünschte Verhalten.
Keine Ahnung was gewünscht ist, aber wenn alle Objekte die gleichen Werte bekommen, ohne dass sie beim Aufruf anders gesetzt werden können, macht das doch wenig Sinn sie als Instanzvariablen zu definieren, oder?
grandma
User
Beiträge: 26
Registriert: Mittwoch 30. Mai 2007, 15:04

Naja doch macht schon Sinn, das Objekt wird einer anderen Methode übergeben und da werden dann die Werte verändert.

Hier sollen dann die Werte natürlcih nicht für alle Instanzen verändert werden sondern nur für eine.
(und so 100prozentig fertig ist das ganze noch nicht)

Aber zurück zum Thema...

Das mit den mehreren Variablen übergeben hab ich schon ausprobiert (2 dummy argumente)

Die Fehlermeldung bleibt bei "2 Arguments expected"
Also ist es nicht die eigentlich Init die aufgerufen wird.

Ahja, das Requestobjekt wird zumindestens an die externe Methode über self übergeben, ist also kein extra Argument.


Edit: Wenn ich mir es so recht überlege, da es keinerlei andere Fehlermeldung gab als ich die Argumente geändert habe, glaube ich das es irgendeine alte version ist die er da her nimmt... weiss nur nicht woher gerade.
rolgal_reloaded
User
Beiträge: 312
Registriert: Dienstag 24. Oktober 2006, 19:31

Die Werte können auch nur für eine Instanz geändert werden, wenn es Klassenattribute sind.

Oder überseh ich einen wesentlichen Unterschied:

Code: Alles auswählen

>>> class A:
	    var1 = 5
	    var2 = 10

	
>>> class B:
	    def __init__(self):
                self.var1 = 5
                self.var2 = 10

		
>>> a1 = A()
>>> a2 = A()
>>> b1 = B()
>>> b2 = B()
>>> a1.var1
5
>>> a2.var1
5
>>> a1.var1 = 7
>>> a1.var1
7
>>> a2.var1
5
>>> b1.var1
5
>>> b2.var1
5
>>> b1.var1 = 7
>>> b1.var1
7
>>> b2.var1
5
Benutzeravatar
Michael Schneider
User
Beiträge: 569
Registriert: Samstag 8. April 2006, 12:31
Wohnort: Brandenburg

rolgal_reloaded hat geschrieben:
BlackJack hat geschrieben:Dann teilen sich alle Objekte dieses Typs die Attribute. Das ist *sehr* wahrscheinlich nicht das gewünschte Verhalten.
Keine Ahnung was gewünscht ist, aber wenn alle Objekte die gleichen Werte bekommen, ohne dass sie beim Aufruf anders gesetzt werden können, macht das doch wenig Sinn sie als Instanzvariablen zu definieren, oder?
Hi,

nur weil es Initialisierungswerte sind, heißt das nicht, dass sie im Namensraum der Klasse besser aufgehoben sind. Die Frage ist, ob Änderungen in einer Instanz einen Einfluss auf die anderen Instanzen haben soll.

Michael
Diese Nachricht zersört sich in 5 Sekunden selbst ...
rolgal_reloaded
User
Beiträge: 312
Registriert: Dienstag 24. Oktober 2006, 19:31

@Michael

Ich versteh das schon, nur wie oben gezeigt, lassen sich die Werte der einzelnen Instanzen ohne Einfluss aufeinander ändern.

LG

r_r
grandma
User
Beiträge: 26
Registriert: Mittwoch 30. Mai 2007, 15:04

Ok es ist ein Zopeproblem...

Ich habe das File komplett gelöscht und trotzdem wird noch drauf zugegriffen, ich habe keine Ahnung wo er das noch hernimmt.

Mal im Zopeforum nachfragen...

Danke an alle hilfbereiten hier
Benutzeravatar
Michael Schneider
User
Beiträge: 569
Registriert: Samstag 8. April 2006, 12:31
Wohnort: Brandenburg

Hallo Rolgal!
rolgal_reloaded hat geschrieben:Die Werte können auch nur für eine Instanz geändert werden, wenn es Klassenattribute sind.

Oder überseh ich einen wesentlichen Unterschied:

Code: Alles auswählen

>>> class A:
	    var1 = 5
	    var2 = 10

Ja, es geht darum, ob prinzipiell dasselbe Objekt an die Instanz weitergegeben wird, oder gleich eine Kopie - also ein anderes Objekt.

Wenn Du dem Namen innerhalb der Instanz ein neues Objekt zuweist, dann trennen sich genau da die Wege des Namens und Du greifst fortan von Klasse und Instanz auf unterschiedliche Objekte zu. Bis dahin referenzierten beide Namen (von Klasse und Instanz) dasselbe Objekt:

Code: Alles auswählen

>>> class A:
... 	var = 5
... 	
>>> a1, a2 = A(), A()
>>> a1.var, a2.var
(5, 5)
>>> A.var = 10
>>> a1.var, a2.var
(10, 10)
>>> a1.var = 15
>>> a1.var, a2.var
(15, 10)
Wenn Du dem Namen aber kein neues Objekt zuweist, sondern dasselbe Objekt nur modifizierst (im folgenden Beispiel list.append), dann referenzierst Du weiterhin dasselbe Objekt mit demselben Namen:

Code: Alles auswählen

>>> class B:
... 	var = [5]
... 	
>>> b1, b2 = B(), B()
>>> b1.var, b2.var
([5], [5])
>>> B.var.append(10)
>>> b1.var, b2.var
([5, 10], [5, 10])
>>> b1.var.append(15)
>>> b1.var, b2.var
([5, 10, 15], [5, 10, 15])
Das kann erwünscht sein, aber auch nicht. :-)

Grüße,
Michael
Diese Nachricht zersört sich in 5 Sekunden selbst ...
rolgal_reloaded
User
Beiträge: 312
Registriert: Dienstag 24. Oktober 2006, 19:31

:!: :D

Alles klar, aber wäre es nicht doch besser, die Defaultwerte in __init__ reinzuschreiben. Entspricht das nicht mehr der Idee eines Konstruktors?

Also:

Code: Alles auswählen

class A:
    def __init__(self, var1 = [], var2 = []): #usw.
        self.var1 = var1
        self.var2 = var2

Oder gibt es Fälle wo das wie vom Autor des Threads gezeigt wird besser ist?

LG

rolgal_reloaded
Benutzeravatar
Michael Schneider
User
Beiträge: 569
Registriert: Samstag 8. April 2006, 12:31
Wohnort: Brandenburg

rolgal_reloaded hat geschrieben:@Michael

Ich versteh das schon, nur wie oben gezeigt, lassen sich die Werte der einzelnen Instanzen ohne Einfluss aufeinander ändern.

LG

r_r
Hi rolgal,

leider nicht. Es macht wirklich einen Unterschied, ob bei der Instanzierung einer Klasse eine Referenz auf das Objekt der Klasse übergeben wird, oder eine Kopie. In Deinem Beispiel hatte das Ändern des Integerwertes nur deshalb keinen Einfluss, weil Integerobjekte nicht veränderbar sind und Python nicht dem von der Klasse aus referenzierten Integerobjekt den Wert 5 gegeben hat, sondern statt dessen dem instanzlokalen Namen das (neue) Integerobjekt mit dem Wert 10 zugeordnet hat.
Wie oben gezeigt: bei veränderbaren Objekten geht das nicht - solange Du ihnen kein neues Objekt zuweist. Beachte, dass z.B. "list1 = list1 + [10]" zwar eine neue Liste liefert, diese aber nicht mehr das Objekt list1 ist:
>>> l1 = [5]
>>> l1, id(l1)
([5], 13057200)
>>> l1.append(10)
>>> l1, id(l1)
([5, 10], 13057200)
>>> l1 = l1+[15]
>>> l1, id(l1)
([5, 10, 15], 13024032)
Alle Klarheiten beseitigt? :-)

Grüße,
Michel
Diese Nachricht zersört sich in 5 Sekunden selbst ...
Antworten