instanzmethode kann nicht auf liste zugreifen

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.
LiLaLaunebär
User
Beiträge: 55
Registriert: Sonntag 11. April 2010, 14:41

Hi,
ich habe folgenden Code:
Der Konstruktor bekommt u.a. eine Liste übergeben, die Gegenstand des Problems ist.
Ich habe 2 print Commandos mit #1 und #2 gekennzeichent. Beide Male wird die Liste ToUnPackAr ausgegeben (ein mal im Konstuktor, ein mal in der Methode unPacking(), welche durch activate(...) aufgerufen wird).
Bei #2 ist die Liste jedoch leer, wie in der Ausgabe zu sehen ist...Warum?

Danke für Tipps.

Code: Alles auswählen

class UnPacker(Process):
    """ A process class unpacking LoadingUnits"""
    def __init__(self, StationObj, ToUnPackAr):
        """ Constructor:
        Parameters:
        @ Station (Station): The Station object where the storage is located
        @ ToUnPack (list [LoadingUnit]): A list containing all LoadingUnits that must be unloaded""" 
        Process.__init__(self, name = "UnPacker")
        self.StationObj = StationObj
        self.ToUnPackAr = ToUnPackAr
        activate(self, self.unPacking())
        print "%s: #1 %s" %(now(),self.ToUnPackAr) 
    def unPacking(self): 
        """ unpacks LoadingUnits"""
        def getToUnPack(Buff):
            for x in Buff:
                if x is Item: 
                    return [x]
        def spaceAvailable():
            pass
        
        if now() > 40:
            print "%s: unpacker active at %s" %(now(), self.StationObj.name)
            print "%s: #2 %s" %(now(), self.ToUnPackAr)
Die Ausgabe ist wie folgt:
45: #1 [<__main__.LoadingUnit object at 0x02780FF0>, <__main__.LoadingUnit object at 0x02787030>, <__main__.LoadingUnit object at 0x02787050>,...
45: unpacker active at CM_MEXICO
45: #2 []
Zuletzt geändert von LiLaLaunebär am Montag 28. Juni 2010, 13:39, insgesamt 1-mal geändert.
CM
User
Beiträge: 2464
Registriert: Sonntag 29. August 2004, 19:47
Kontaktdaten:

Hoi,

wie sollen wir das durch den Code wissen können? Da steht nicht, wie diese Liste initialisiert wurde, was zwischendurch mit Ihr geschieht, wie die Funktion aufgerufen wurde. Magst Du vielleicht ein funktionierendes (den Fehler reproduzierendes) Minimalbeispiel geben?

Und was ist 'Process'? Kommt es aus 'multiprocessing'?

HTH
Christian
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Wir haben hier einen Syntax-Highlighter für Python - sollte man doch mit > 30 Postings wissen, oder? ;-)

Der Code sieht generell ziemlich ungeordnet aus, da müßte man viel umarbeiten für PEP8 -Kompatibilität.

Der Knackpunkt muss doch in der activate-Funktion liegen, die Du uns hier nicht zeigst.
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
Benutzeravatar
pillmuncher
User
Beiträge: 1484
Registriert: Samstag 21. März 2009, 22:59
Wohnort: Pfaffenwinkel

In unPacking fehlt ein return-Statement, und die Funktionen getToUnPack und spaceAvailable werden nie aufgerufen. Außerdem würde ich erstmal testen, ob nicht schon an den Konstruktor eine leere Liste übergeben wird. Und Attribut-Namen sollten kleingeschrieben werden und ggf. mit Unterstrichen gesprenkelt, siehe PEP-8, den Abschnitt "Method Names and Instance Variables".
In specifications, Murphy's Law supersedes Ohm's.
LiLaLaunebär
User
Beiträge: 55
Registriert: Sonntag 11. April 2010, 14:41

Hallo Christian, danke für die Antwort.
Process und activate kommen aus einem Simualtions-Package. Ich glaube ich habe den Fehler gerade auch gefunden, versteh es aber trotzdem nicht...
Die übergebene Liste wird parallel an anderer Stelle gelöscht...ich dachte jedoch, dass das keinen Einfluss hat, weil die Kopie der Liste die Elemente der Liste referenzieren und nicht die Liste selbst?
also was ich nicht verstehe:
ich übergebe die Liste mit

Code: Alles auswählen

UnPacker(Station, DeliveryObj.CargoAr)
scheinbar wird hier eine Referenz auf die Liste übergeben und nicht auf die Elemente. Wie erreiche ich, dass ich quasi eine Liste übergebe, die auf die Elemente und nicht auf die Variable DeliveryObj.CargoAr verweist? also nicht ToUnPackAr -> DeliveryObj.CargoAr -> Elemente sondern ToUnPackAr -> Elemente / DeliveryObj.CargoAr -> Elemente???
LiLaLaunebär
User
Beiträge: 55
Registriert: Sonntag 11. April 2010, 14:41

@pillmuncher, Hyperion:
danke für eure Hilfe, ich habe nur den Anfang vom code gepostet, da der Fehler direkt am Anfang aufgetreten ist und der Rest unwichtig ist.
und das mit dem python highlighter...ist mir noch nie aufgefallen, aber jetzt wo du es sagst... :oops:
Benutzeravatar
pillmuncher
User
Beiträge: 1484
Registriert: Samstag 21. März 2009, 22:59
Wohnort: Pfaffenwinkel

In Python wird nie etwas kopiert, außer du schreibst es selbst hin:

Code: Alles auswählen

blubb = [1,2,3]
bleh = list(blubb)
#oder:
import copy
bleh = copy.copy(blubb)
Auch bei der Argument-Übergabe an eine Funktion wird nicht das Objekt kopiert (Python != C), sondern nur die Referenz auf das Objekt. Variablen in Python enthalten überhaupt immer nur Referenzen, auch hier: Python != C.
In specifications, Murphy's Law supersedes Ohm's.
LiLaLaunebär
User
Beiträge: 55
Registriert: Sonntag 11. April 2010, 14:41

aaahhhh...ok...
danke!
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

pillmuncher hat geschrieben:In unPacking fehlt ein return-Statement,
Wieso? Ich muss in Python doch kein explizites "None" zurückliefern.
pillmuncher hat geschrieben: Außerdem würde ich erstmal testen, ob nicht schon an den Konstruktor eine leere Liste übergeben wird.
Das wird ja offensichtlich nicht, denn die Liste wird ja def. ausgegeben.
LiLaLaunebär hat geschrieben: Die übergebene Liste wird parallel an anderer Stelle gelöscht...ich dachte jedoch, dass das keinen Einfluss hat, weil die Kopie der Liste die Elemente der Liste referenzieren und nicht die Liste selbst?
Natürlich spielt das eine Rolle! (und es dürfte des Rätsels Lösung sein ;-) )

Code: Alles auswählen

In [73]: a = [1, 2, 3]

In [74]: b = a

In [75]: a.pop()
Out[75]: 3

In [76]: a
Out[76]: [1, 2]

In [77]: b
Out[77]: [1, 2]
Wenn Du eine Kopie des wirklichen Objektes erreichen willst:

Code: Alles auswählen

In [78]: a = [1, 2, 3]

In [79]: b = a[:]

In [80]: a.pop()
Out[80]: 3

In [81]: a
Out[81]: [1, 2]

In [82]: b
Out[82]: [1, 2, 3]
Ggf. lohnt auch ein Blick ins copy-Modul.

Und der "wichtige" Teil ist eben wohl im activate zu suchen... ;-)
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
Benutzeravatar
pillmuncher
User
Beiträge: 1484
Registriert: Samstag 21. März 2009, 22:59
Wohnort: Pfaffenwinkel

Hyperion hat geschrieben:
pillmuncher hat geschrieben:In unPacking fehlt ein return-Statement,
Wieso? Ich muss in Python doch kein explizites "None" zurückliefern.
Wg. der Zeile

Code: Alles auswählen

        activate(self, self.unPacking())
Hyperion hat geschrieben:
pillmuncher hat geschrieben: Außerdem würde ich erstmal testen, ob nicht schon an den Konstruktor eine leere Liste übergeben wird.
Das wird ja offensichtlich nicht, denn die Liste wird ja def. ausgegeben.
Stimmt, hatte ich überlesen.

Gruß, Mick.
In specifications, Murphy's Law supersedes Ohm's.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

pillmuncher hat geschrieben:
Hyperion hat geschrieben:
pillmuncher hat geschrieben:In unPacking fehlt ein return-Statement,
Wieso? Ich muss in Python doch kein explizites "None" zurückliefern.
Wg. der Zeile

Code: Alles auswählen

        activate(self, self.unPacking())
Stimmt. Das hatte ich übersehen ;-)
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
LiLaLaunebär
User
Beiträge: 55
Registriert: Sonntag 11. April 2010, 14:41

danke an alle, es lag definitiv am löschen...hab das mit den Referenzen in Python falsch verstanden...
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Vielleicht solltest Du dennoch mal auf die andere Kritik eingehen, oder zumindest selber scharf drüber nachdenken:

- PEP8
- Kein Rückgabewert von unPacking()
- Funktionsdefinitionen in einer Funktion, die nie aufgerufen werden
- externer Funtkionsaufruf aus einem Konstruktor
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
LiLaLaunebär
User
Beiträge: 55
Registriert: Sonntag 11. April 2010, 14:41

@ Hyperion
also das mit pep8 hab ich mir nattürlich angesehen, muss aber sagen, dass ich Teile davon für undurchdacht halte, v.a. Variablen klein schreiben: ich halte es so, dass ich klassiche Datentypen (numerics, boolean usw klein schreibe), Objekte beginnen mit Großbuchstaben und enden mit Obj, listen enden mit Ar für Array (Java-Relikt ;) ...)
Wir halten das mittlerweile im ganzen Team so, weil es sich einfach als besser bewährt hat (und weisen im Modulkopf auch auf diese Konventionen hin). Es ist für andere so einfacher den Code zu überblicken und zu verstehen...sind mittlerweile immerhin über 2000 locs

die folgenden 3 Punkte sind leider nicht vermeidbar (liegt am verwendeten Simulations Package)
- kein return geht in Ordnung, weil das eine ProcessExecutionMethod ist und keine "normale" Methode
- wegen Aufruf einer externen Methode im Konstruktor: der Prozess muss sich selbst aktivieren
- die leere Funktion wird später benötigt und muss da sein, der Code war leider nur ein Snippet
Benutzeravatar
pillmuncher
User
Beiträge: 1484
Registriert: Samstag 21. März 2009, 22:59
Wohnort: Pfaffenwinkel

LiLaLaunebär hat geschrieben:Objekte beginnen mit Großbuchstaben und enden mit Obj, listen enden mit Ar für Array (Java-Relikt ;) ...)
1. Python-Listen sind keine Arrays.

2. Für umgekehrte Ungarische Notation gilt dasselbe, wie für normale Ungarische Notation: "Hungarian Notation is the tactical nuclear weapon of source code obfuscation techniques", aus: How To Write Unmaintainable Code, 'Naming'.

3. Python is not Java ;)
In specifications, Murphy's Law supersedes Ohm's.
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

LiLaLaunebär hat geschrieben:also das mit pep8 hab ich mir nattürlich angesehen, muss aber sagen, dass ich Teile davon für undurchdacht halte, v.a. Variablen klein schreiben: ich halte es so, dass ich klassiche Datentypen (numerics, boolean usw klein schreibe), Objekte beginnen mit Großbuchstaben und enden mit Obj, listen enden mit Ar für Array (Java-Relikt ;) ...)
Das wird dich jetzt vermutlich schocken, aber in Python ist jede "Variable" ein Objekt, also müsstest du "Obj" an alles anhängen was es schon wieder total bedeutungslos macht. Zudem, wie ist das mit euren Listen? Die sind ja auch Objekte, heißen die nun ``MesswerteArObj`` oder ``MesswerteObjAr``.

An PEP8 kann man paar Sachen durchaus aussetzen und ich halte mich da auch nicht 100% daran, aber die Kritikpunkte die du anführst sind keine sinnvollen.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Benutzeravatar
KEBA
User
Beiträge: 16
Registriert: Sonntag 20. April 2008, 16:53

dennda hat auch mal einen sehr netten Artikel geschrieben, der mir geholfen hat, denn Sinn hinter Referenzen zu versthen. Auch wenn du dich mehr auskennst, als ich damals, vielleicht trotzdem lesenswert. Die Links oben empfehle ich übrigens auch :)

Grüße, Keba.
LiLaLaunebär
User
Beiträge: 55
Registriert: Sonntag 11. April 2010, 14:41

Für umgekehrte Ungarische Notation gilt dasselbe, wie für normale Ungarische Notation
Nun, da sehe ich einen gravierenden Unterschied...denn ein Präfix behindert die Lesbarkeit enorm, ein Suffix dagegen nicht.
Der Rest liegt vllt an sprachlicher Unschärfe..Ar vs Iterator bzw Objekt vs eigener Datentyp...vllt noch verbesserungsfähig.
Nichtsdestotrotz hat sich das System bewährt, ich kann mich in die Codestücke meiner Teamkollegen schneller einarbeiten.
Die Problematik mit MesswertArObj kommt übrigens nicht auf, es wird nur mit Ar getagt, das ist dann der Wink mit dem Zaunpfahl, dass es sich hierbei um was iterierbares handelt und dass man ggf genauer hinschauen muss. Ich denke die ungarische Notation kommt nicht von ungefähr. Sie ist vllt nicht optimal, aber die Tatsache, dass sich jmd dieser Thematik angenommen hat zeigt, dass es in der Hinsicht evtl Optimierungspotential gibt.
Benutzeravatar
snafu
User
Beiträge: 6740
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Wenn ich stattdessen `messwerte` lesen würde, wüsste ich auch, dass das wohl eine Liste sein wird...
BlackJack

@LiLaLaunebär: Die ungarische Notation ist ja nicht schlecht, nur dass die im Original von Charles Simonyi, also bei demjenigen der sich der Thematik angenommen hat, der Name nicht den Datentypen beinhalten sollte. Jedenfalls bei der Anwendungsprogrammierung. Bei Systemprogrammierung hat er auch Prefixe für die Datentypen vorgeschlagen.

Die Notation kommt tatsächlich nicht von ungefähr, sie wurde erstmals für BCPL entwickelt, einer Sprache die im Grunde keine Datentypen kennt, ausser das "Maschinenwort". Da hat es halt Sinn gemacht, dass sich der Programmierer die Bedeutung im Variablennamen notiert hat. Mittlerweile kennen Programmiersprachen selbst aber eine Menge Datentypen und man kann auch herausfinden welchen Typ ein Wert hat, ohne auf die Namen zurückgreifen zu müssen.

Microsoft, das die Namenskonvention hauptsächlich eingeführt und verbreitet hat, rät mittlerweile auch davon ab.

Anwendungsorientierte (umgekehrte) ungarische Notation verwende ich auch ab und zu wo es Sinn macht. `Obj` anzuhängen in einer Sprache wo *alles* was man an einen Namen binden kann ein Objekt ist, macht eher wenig Sinn.

`Ar` finde ich ziemlich hässlich. Das ist alles andere als selbsterklärend. `Array` wäre schon verständlicher. Nur dass man in Python wohl in den seltensten Fällen tatsächlich ein Array haben wird, wenn man nicht gerade numerische Berechnungen mit `numpy` durchführt. In Python wäre `_sequence` oder `_seq` eher ein passender Postfix für Werte die Indexzugriff erlauben, oder `_it` oder `_iterator` für Werte die generell iterierbar sind. Ich verwende oft auch einfach nur ein Mehrzahl-`s` um Containerobjekte zu benennen. Das liest sich recht "natürlich". Siehe auch den Kommentar von snafu.
Antworten