Problem: Methoden-calls & optimierte Dict-Zugrife

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
hector
User
Beiträge: 20
Registriert: Dienstag 3. Oktober 2006, 09:06

Hy,
da ich nicht weiss wie ich das, was ich suche in einen vernuenftigen Suchbegriff wandle, muss ich leider euch fragen.
Man stelle sich vor es gibt eine Methode, die ausgeben soll, wer sie aufruft. Derzeit lasse ich das Objekt, was die Methode aufruft noch sich selbst mit uebergeben. Das ist aber sehr haesslich und kann sehr schnell unterwandert werden (einfach eine andere Objektadresse herausfinden und diese uebergeben z.B.). Ich bin mir sehr sicher, dass es dafuer was gibt, nur weiss ich wie gesagt nicht, was ich da in Google eingeben muss. Unter welchem Schlagwort muesste das laufen? bestimmt irgendwas mit calling..

und damit die Sache gleich noch runder wird:
ich habe eine Liste bestehend aus mehreren Dicts (da sind unter Anderem die Adressen der Objekte gespeichert, die oben genannte Methode erkennen soll)
Momentan mache ich es so, dass ich jedes Element in der Liste rausnehme und schaue ob der Wert zu dem Key gleich der Adresse ist.. ich meine aber, dass das auch schneller gehen muesste..

Code: Alles auswählen

for entity in entitylist:
      if entity["addr"] == addr:
           return entity
Das soll jetzt mal nur die Sache an sich verdeutlichen. Bei mir heissen key und value natuerlich anders. Und da ich weiss, dass py auch fuer Einzeiler bekannt ist, wollte ich euch auch fragen, ob das nicht noch schneller geht. Das waere sozusagen jetzt nicht mehr das Verstehen des Algos, sondern das Erlernen von Kunstgriffen die Python einem gestattet. Kann sein, dass ich da von Datenbanken zu sehr gepraegt bin, aber ich dachte hier dabei an etwas wie

Code: Alles auswählen

return entity in entitylist, where "addr"==addr
Das ist jetzt kein Pzthon sondern eher die ausgeschriebene Idee

Danke fuer die Aufmerksamkeit, ich bin nebenbeigesagt, mittlerweile so weit in Py, dass ich gerne die Kunstgriffe lernen wuerde. Wer dazu was hat, kann es ja hier auch loswerden (was aber nicht heissen soll, dass ich mir das nicht selbst zusammensuche). Ich ebenfalls an dem Pkt, wo bei mir Performanz an oberster Stelle steht. Darum wuerde ich die Benutzung von For-Schleifen gerne reduzieren und mit den schon mehrfach erwaehnten Kunstgriffen ersetzen. Kann mir jemand sagen, wie sich da die Performanz verhaelt? Sind diese Kunstgriffe genausoschnell, langsamer, oder schneller als For-Schleifen? Ich meine gelesen zu haben, dass sie schneller sind, weil sie eben keine For-Schleifen darstellen, sondern andere Algos.. je nach Aufgabe.
DasIch
User
Beiträge: 2718
Registriert: Montag 19. Mai 2008, 04:21
Wohnort: Berlin

Dein Pseudocode könnte man so schreiben:

Code: Alles auswählen

return entity for entity in entitylist if entity.addr == 'addr'
Zu dem Rest solltest du dir das Modul "this" aus der stdlib ansehen. Sollte dir einen guten Eindruck von deinem Vorhaben vermitteln.
Benutzeravatar
str1442
User
Beiträge: 520
Registriert: Samstag 31. Mai 2008, 21:13

@DasIch

Das funktioniert nicht, da du so allerhöchstens mit 2 Klammern einen Generator erzeugen kannst, und dann den Generator zurückgibst, und das ist im großen und ganzen nur eine andere Version als die Version von hector. Direkt so funktioniert das sowieso nicht, und entity an sich wird auch nicht zurückgegeben.

Mir persönlich wäre kein anderer Weg als drüber iterieren und explizit testen bekannt. Wie soll man denn auch sonst die Elemente der Liste erfassen? Raten mag Python nicht so. Das sagt auch this aus der StdLib ;)

Aber "besser" könnte man es per Generator / List Comprehension wie von DasIch gezeigt schon schreiben, return mitten in einer Schleife empfinde ich als unschön.

@Funktion-die-ihren-Aufrufer-kennt:

Gibts afaik nicht. Musst du übers Übergeben regeln. Wenn du wirklich meinst, das sei unsicher, könntest du allerhöchstens noch alle erlaubten Objekte in einer Liste speichern und die dann mit dem übergebenen Objekt abgleichen, oder so ähnlich.
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

str1442 hat geschrieben:@Funktion-die-ihren-Aufrufer-kennt:

Gibts afaik nicht. Musst du übers Übergeben regeln.
Doch, das gibts und wurde letztens im Forum diskutiert. Das ist aber eine schlechte Idee(TM). Wäre ja noch besser, wenn Funktionen sich verschieden verhalten, je nach dem wer sie aufruft. Wiederverwendbarkeit Null, aber dafür Spaghetticode hoch zwei.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
DasIch
User
Beiträge: 2718
Registriert: Montag 19. Mai 2008, 04:21
Wohnort: Berlin

@str1442 Es gibt nur die Möglichkeiten, entweder man verwendet einen Generator oder liefert ein Objekt über dass man iterieren kann zurück. Kommt letztendlich aufs selbe raus wobei zweiteres langsamer wäre.

Das einzige was mir noch einfallen würde wäre dass ganze lazy zu machen z.B. mithilfe eines Dekorators, der die Funktion wrappt.

Wird die Funktion aufgerufen werden die übergebenen Argumente in einem dict mit dem Resultat gespeichert und dass Resultat zurückgegeben, sind die Argumente als Key im dict wird das Resultat zurückgegeben.

Macht wiederum nur Sinn wenn die Funktion bewusst aufgerufen wird und ihr Ergebnis aufgrund von Seiteneffekten sich nicht verändert.
Benutzeravatar
str1442
User
Beiträge: 520
Registriert: Samstag 31. Mai 2008, 21:13

Doch, das gibts und wurde letztens im Forum diskutiert. Das ist aber eine schlechte Idee(TM). Wäre ja noch besser, wenn Funktionen sich verschieden verhalten, je nach dem wer sie aufruft. Wiederverwendbarkeit Null, aber dafür Spaghetticode hoch zwei.
Kommt ja auf den Code drauf an. Bei unterschiedlichen Verhalten ist das natürlich schlecht. Aber wenn es nur um die gleiche Sorte von Objekten geht (bzw die alle *garantiert* das gleiche Attribut haben), könnte es sogar ganz nützlich sein. praktisch Funktionen, die wie Methoden eingesetzt werden, ohne welche zu sein. Sowas braucht man aber wirklich nur bei Konstruktionen, bei denen diese Separierung notwendig ist. Beispielsweise ein Plugin System (Plugins, csv - aktuell dreht sich wohl alles im Kreis :D)

Könntest du einen Link zum entsprechenden Thread reinstellen? Interessehalber.

ADD:

@DasIch
Es gibt nur die Möglichkeiten, entweder man verwendet einen Generator oder liefert ein Objekt über dass man iterieren kann zurück. Kommt letztendlich aufs selbe raus wobei zweiteres langsamer wäre.
Klar, aber er wollte ja direkt das Objekt zurückgeben. Und der Generator/Liste wohl immer nur ein Objekt enthalten, da seine Addressenliste ja so angelegt ist. Dein Code war an sich ein SyntaxError, das kam ja dazu, und er hätte vielleicht auf die Idee kommen können, mit deiner Version würde das Objekt direkt zurückgegeben werden.
Zuletzt geändert von str1442 am Sonntag 2. November 2008, 17:15, insgesamt 1-mal geändert.
hector
User
Beiträge: 20
Registriert: Dienstag 3. Oktober 2006, 09:06

Hehe, nein nicht ganz. Die Methode ist schon wiederverwendbar. Nur brauche ich eben die Adresse des Aufrufers, um daraus die Entitaet ableiten zu koennen. Wenn man sich das als Server-Client vorstellt, wird schnell deutlich, dass der Client rumtricksen koennte, wenn er seine Adresse selbst mituebergibt. Die Methode des Servers leitet dann anhand dieser Adresse die ganze Entitaet mit allen Attributen ab usw. Das habt ihr ja vorhin im Codebsp. gesehen. Warum das jetzt SpaghettiCode sein soll, weiss ich ehrlich gesagt nicht. Es ist richtig, dass man das unter der falschen Motivation erhalten wird. Aber diese habe ich ja nicht. Mein Projekt ist eigentlich schoen oop gehalten, nur stoert mich eben die Tatsache, dass ich diese Adresse nicht authentifizieren kann sondern sie "glauben" muss.. -.-

nagut, dann dennoch danke fuer die Hinweise.
BlackJack

Aufbauend auf DasIch:

Code: Alles auswählen

return (e for e in entitylist if e.addr == 'addr').next()
@hector: Ich verstehe nicht welches Problem Du lösen willst und von welchen "Adressen" Du immer redest. Meinst Du Objektidentitäten?

Was übergibst Du denn da, was Du gerne magisch ermittelt hättest? Es gibt Code innerhalb Deines laufenden Programms, dem Du nicht vertraust? Dann hast Du IMHO schon verloren, weil innerhalb des laufenden Interpreters Code voneinander ab zu schotten *ziemlich* schwer ist. Notfalls mogelt sich der Aufrufer irgendwie in die `entitylist` rein.
DasIch
User
Beiträge: 2718
Registriert: Montag 19. Mai 2008, 04:21
Wohnort: Berlin

hector hat geschrieben:Wenn man sich das als Server-Client vorstellt, wird schnell deutlich, dass der Client rumtricksen koennte, wenn er seine Adresse selbst mituebergibt.
Dann lass den Client nur eine UUID übermitteln, die zu manipulieren um gezielt ein anderes Ergebnis zu bekommen dürfte schwer werden.

Dir bleibt letztendlich nichts anderes als dem Client zu vertrauen es sei den du kannst Soft- und Hardware des Clients kontrollieren. Daran kannst du auch nichts ändern wenn du Code schreibst der aussieht als ob es Magie wirklich gibt und zwar nicht metaphorisch gemeint.
hector
User
Beiträge: 20
Registriert: Dienstag 3. Oktober 2006, 09:06

nagut, ich wollts zwar nicht eingehender erklären, aber es macht kein Sinn die gefragten Infos zurückzuhalten. Da ich gerade wieder mein Py-Phase habe, wollte ich mich mal an etwas größerem versuchen. (Ich brauchte sowieso ein Projekt um git auszuprobieren :D)
Jedenfalls programmiere ich gerade ein AntMe-Ableger.. "oh welch Wunder, noch einer der sich daran versucht", werdet ihr jetzt womöglich denken. Naya, ich komme schon hervorragend voran. Und alles schön in Objekten. Der Server von dem ich vorhin sprach, heißt bei mir "Coordinator".. das ist die Instanz die die Schnittstelle von der Welt zu dem Objekt (also Ameise, Apfel, etc.) darstellt. Ein Objekt besitzt ne KI und das ist die Adresse um die es geht. Wenn die KI dem Coordinator sagt "bewege mich nach da hin", ruft das Objekt die Methode moveEntity() des Coordinator auf. Dieser muss nun das gesamte Objekt, zu welchem die KI gehört, ermitteln, damit er anschließend an die Position und die anderen wichtigen Daten des Objekts rankommen kann. Damit wäre es eben sehr fein gewesen die Adresse des rufenden Objekts gleich zu benutzen, ohne das das rufende Objekt die Wahl hat.
Es mag durchaus sein, dass mein Design gravierende Schwächen aufweist. Ich habe mich nun für eine Hierarchie entschieden, die den Coordinator tatsächlich zum Koordinatoren macht und ein Objekt wie die Ameise keine Möglichkeit hat, über ihre Verhältnisse hin die Welt zu verändern. So.. naya, jetzt solltet ihr mein Problem nachvollziehen können.
Und meine Motivation ist, dass ich schon immer mal KI programmieren wollte bzw. Antme. Ich habe auch verschiedene Versuche gestartet, aber irgendwie fehlte mir das Abstraktionsvermögen bis dato. Wenn man es so will, ist die Engine fertig, ich muss mir nur jetzt überlegen wie ich damit weiterverfahre, also wie die Spielregeln sein werden. Hinterher würde das nur in Mehraufwand münden. Naya, und meine Frage war ja eher ästhetischer Natur. Der Code wird auch ohne dies laufen können.

Und bitte keine Kommentare wie "sowas gibts doch schon" und Bla. Ich betreibe das um mich selbst weiterzubilden. Wer will kann den Code natürlich haben, weil es ja mit freien Tools entwickelt wird, aber ich bezweifle, dass das mal passieren wird ;D
Ich muss aber gestehen, dass sowas richtig aufgezogen, durchaus Verwendung finden dürfte.. alleine schon um eine Alternative zum echten AntMe in Py zu haben. Noch ist der Markt nämlich nicht überschwemmt. Und wenn man nun sowas entwickelt, was auch noch sehr gut funktioniert (wie das Vorbild z.b.) dann dürfte das, dieser Sprache einiges an Prestige verschaffen.. aber alleine wage ich mich nicht an so große Ufer. Das müsste ganz anders geplant werden, aber wenn sich die UberC0der hier zusammenschließen würden, könnte das tatsächlich funktionieren.. ich meine, ich habe gerade mal 2 Tage programmiert und bin schon, wie ich finde, ziemlich "weit"
DasIch
User
Beiträge: 2718
Registriert: Montag 19. Mai 2008, 04:21
Wohnort: Berlin

In diesem Fall solltest du einfach den expliziten Weg wählen und Objekt die Adresse an den Coordinator selbst übergeben lassen. Dem Objekt nicht zu vertrauen hiesse von vornerein anzunehmen das Objekt hätte einen Bug, wieso sollte man dass tun?
hector
User
Beiträge: 20
Registriert: Dienstag 3. Oktober 2006, 09:06

Nicht unbedingt Bug, denn die KI soll ja später auch von anderen erstellt werden können. Und damit wäre das jetzt für mich als koordinierende Instanz eben die Möglichkeit gewesen, den Daten auch 99% vertrauen zu können
DasIch
User
Beiträge: 2718
Registriert: Montag 19. Mai 2008, 04:21
Wohnort: Berlin

Dann schreib Tests für die Basis Funktionen der KI, die die KI bestehen muss. Wer auch immer die KI schreibt hat in jedemfall dann einen Bug verursacht den er dann auch bitte schön beheben soll.

In Python gilt da dass gleiche wie bei C, der Programmierer weiß was er tut.
Darii
User
Beiträge: 1177
Registriert: Donnerstag 29. November 2007, 17:02

Dann nimm noch die Koordinaten völlig aus der KI raus. Die KI braucht doch nicht zu wissen wo sie ist. Es reicht doch, wenn sie deinem „Coordinator“ mitteilt wie sie sich in Relativkoordinaten bewegen will.
hector
User
Beiträge: 20
Registriert: Dienstag 3. Oktober 2006, 09:06

Die Koordinaten sind nicht in der KI.. sie sagt dem Koordinator einfach "Ich gehe jetzt nach rechts", den Rest erledigt der Koordinator

Und ya, die Idee mit dem Test kam mir auch bereits. Nur hat das jetzt erstmal keine Priorität ^^ Wenn es ein Attribut gegeben hätte, welches jede Funktion sein eigen nennt, wäre es ja ganz nett gewesen. Aber so wird das zu aufwendig.
BlackJack

@hector: Es ist nicht nur magisch, sondern schränkt IMHO auch zu sehr ein, weil man den "Koordinator" dann nur von einem KI-Objekt aus aufrufen kann. Das KI-Objekt kann seine Strategien dann nicht in weiteren Objekten kapseln, oder den Aufruf des Koordinators über eine Hilfsfunktion in einem anderen Modul machen.

Was die Sicherheit angeht, müsstest Du die KIs sowieso vom Koordinator über eigene Prozesse trennen und die zum Beispiel über XMLRPC kommunizieren lassen.
farid
User
Beiträge: 95
Registriert: Mittwoch 8. Oktober 2008, 15:37

str1442 hat geschrieben:@Funktion-die-ihren-Aufrufer-kennt:
Eine Moeglichkeit waere einfach im Stack nachschauen:

Code: Alles auswählen

>>> import traceback
>>> def caller():
...     callee()
... 
>>> def callee():
...     print traceback.extract_stack()
... 
>>> caller()
[('<stdin>', 1, '<module>', None), ('<stdin>', 2, 'caller', None), ('<stdin>', 2, 'callee', None)]
Also:

Code: Alles auswählen

import traceback
def caller():
    callee()

def callee():
    thestack = traceback.extract_stack()
    callee_name = thestack[-1][2]
    caller_name = thestack[-2][2]
    print "%s called by %s" % (callee_name, caller_name)
Ausgabe:

Code: Alles auswählen

>>> caller()
callee called by caller

>>> callee()
callee called by <module>
Stackposition entsprechend anpassen wenn man einen Dekorator schreibt. Aber das Prinzip bleibt dasselbe.
Qubit
User
Beiträge: 128
Registriert: Dienstag 7. Oktober 2008, 09:07

hector hat geschrieben:Hy,
da ich nicht weiss wie ich das, was ich suche in einen vernuenftigen Suchbegriff wandle, muss ich leider euch fragen.
Man stelle sich vor es gibt eine Methode, die ausgeben soll, wer sie aufruft. Derzeit lasse ich das Objekt, was die Methode aufruft noch sich selbst mit uebergeben. Das ist aber sehr haesslich und kann sehr schnell unterwandert werden (einfach eine andere Objektadresse herausfinden und diese uebergeben z.B.).
Hm, meinst du vielleicht sowas?

Code: Alles auswählen

class members:
	__id = {}
	def _check_id(self):
		if members.__id.get(self,False):
			return members.__id[self],id(self)
		else: raise Exception
	def _anmelden(self,name):
		members.__id.update({self:name})
		return True
	def _abmelden(self):
		if members.__id.get(self,False):
			del members.__id[self]
			return True
		else:
			return False

class bar_besuch(members):
    def einlass(self):
        try:
            mid = self._check_id()
            print "Komm rein %s: %s" %(mid[0],mid[1])
        except: print "Draussen bleiben: Anonymous"


>>> person1=bar_besuch()
>>> person2=bar_besuch()
>>> person1._anmelden('Qubit')
True
>>> person1.einlass()
Komm rein Qubit: 22725616
>>> person2.einlass()
Draussen bleiben: Anonymous
>>> person1._abmelden()
True
>>> person1.einlass()
Draussen bleiben: Anonymous
>>> 
hector
User
Beiträge: 20
Registriert: Dienstag 3. Oktober 2006, 09:06

@BlackJack:
Ist schon richtig das mit XMLRPC zu trennen, sowas in der Art schwebte mir da auch vor. Aber jetzt mach ichs eben so, um schneller was in der Hand zu haben. Da ich mich noch nicht entschieden habe, wie es im Gesamten einmal ablaufen soll, implementiere ich vorerst nur das was ich brauche.

@farid: interessanter Hinweis, liefert aber nicht das was ich gerne gehabt haette..
<ki_ant.KI_ant instance at 0x2b2649071878> <-- sowas brauche ich

@Qubit:
Deine Loesung muss ich mir in Ruhe ansehen, aber danke dennoch fuer den Vorschlag.
Antworten