name 'item' is not defined
- Hyperion
- Moderator
- Beiträge: 7478
- Registriert: Freitag 4. August 2006, 14:56
- Wohnort: Hamburg
- Kontaktdaten:
Ach so... das hat doch nichts mit Python an sich zu tun Die IN/OUT[zahl]-Syntax ist einfach nur der Prompt von IPython.Milkymalk hat geschrieben:Das schon, aber ob ich IPython damit nutzen kann, weiß ich nicht - zudem ich dessen In[4] oder auch ohne Zahl bzw. Out[5] nicht dokumentiert finde.
Standard Python-Shell:
Code: Alles auswählen
>>> print("Hallo")
Hallo
Code: Alles auswählen
In [1]: print("Hallo")
Hallo
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
assert encoding_kapiert
Achso
Da ich eh nur einen Spieler und nur einen Shop habe brauche ich es gar nicht so komplex, wie es hier: https://gist.github.com/2710568 gezeigt wurde - aber es war eine gute Anschauungsübung, die mir irgendwann sicher weiterhilft.
Würde das hier so funktionieren?
Zuerst sind alle Items im Shop. Mit 'give_item(name)' gebe ich ein Item dem Spieler, und mit 'use_item(name)' nehme ich es ihm wieder weg und lege es für zukünftige Referenz in der Liste bzw. im Set der benutzten Items ab.
Nein, ich sehe gerade, daß das nicht klappt, weil die Sets ja keine Dictionaries mehr sind, richtig? Wie adressiere ich denn Objekte in Sets?
Oder sollte ich es lieber gleich als Dictionary lassen?
Bei dieser Methode würde ich aber Probleme bekommen, wenn Items mehr Attribute hätten als nur den Preis; kann man das dann überhaupt mit Dictionaries machen?
Da ich eh nur einen Spieler und nur einen Shop habe brauche ich es gar nicht so komplex, wie es hier: https://gist.github.com/2710568 gezeigt wurde - aber es war eine gute Anschauungsübung, die mir irgendwann sicher weiterhilft.
Würde das hier so funktionieren?
Code: Alles auswählen
item_costs = {'Werkzeug': 20, 'Öl': 4, 'Holzbalken': 6, 'Korb': 3, 'Stoff': 8, 'Kreide': 1, 'Seil': 7, 'Holzeimer': 4, 'Harke': 5, 'Axt': 8, 'Lederbeutel': 3}
class Item(object):
def __init__(self, name, cost):
self.name = name
self.cost = cost
def has_item(item):
if item in player_items:
return True
else:
return False
def give_item(name):
player_items.add(shop_items.pop(name))
def use_item(name):
used_items.add(player_items.pop(name))
shop_items = set(Item(name, cost) for name, cost in item_costs.iteritems())
player_items = set()
used_items = set()
Nein, ich sehe gerade, daß das nicht klappt, weil die Sets ja keine Dictionaries mehr sind, richtig? Wie adressiere ich denn Objekte in Sets?
Oder sollte ich es lieber gleich als Dictionary lassen?
Code: Alles auswählen
item_costs = {'Werkzeug': 20, 'Öl': 4, 'Holzbalken': 6, 'Korb': 3, 'Stoff': 8, 'Kreide': 1, 'Seil': 7, 'Holzeimer': 4, 'Harke': 5, 'Axt': 8, 'Lederbeutel': 3}
def has_item(name):
if name in player_items:
return True
else:
return False
def give_item(name):
player_items.add(shop_items.pop(name))
def use_item(name):
used_items.add(player_items.pop(name))
shop_items = item_costs
player_items = {}
used_items = {}
- Hyperion
- Moderator
- Beiträge: 7478
- Registriert: Freitag 4. August 2006, 14:56
- Wohnort: Hamburg
- Kontaktdaten:
Wenn der Name eines `Item`s das Attribut ist, über das Du ein `Item` klassifizierst, dann bietet sich ein Dictionary an:
Du kannst dann für alle Attribute, die Items aufnehmen sollen wieder ein Dict nehmen, also etwa als Attribut von einer Player-Klasse oder eben einer `used`-Kollektion.
Das hier
ist extrem umständlich. `in` liefert bereits einen Wahrheitswert:
Du kannst doch einfach diesen zurückgeben:
Wobei man sich fragt, ob man das überhaupt als Funktion bräuchte oder wieso es keine Methode der Player-Klasse ist.
Code: Alles auswählen
ITEMS = {
'Werkzeug': 20,
'Öl': 4,
'Holzbalken': 6,
'Korb': 3,
'Stoff': 8,
'Kreide': 1,
'Seil': 4,
'Holzeimer':7,
'Harke': 5,
'Axt': 8,
'Lederbeutel': 3
}
class Item:
def __init__(self, name, cost):
self.name = name
self.cost = cost
def __str__(self):
return "{} ({})".format(self.name, self.cost)
# Dict-Comprehension erst ab Python 3.x
# Du musst es in etwa so umsetzen: shop = dict((name, ...) for ...)
shop = {name: Item(name, cost) for name, cost in ITEMS.items()}
print(shop["Axt"])
Das hier
Code: Alles auswählen
def has_item(item):
if item in player_items:
return True
else:
return False
Also z.B.Python Doku hat geschrieben: Comparisons yield boolean values: True or False.
Code: Alles auswählen
In [21]: "Axt" in shop
Out[21]: True
Code: Alles auswählen
def has_item(item):
return item in player_items
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
assert encoding_kapiert
@Milkymalk: Ich weiss nicht so recht in wie weit in einer Ren'py-Umgebung saubere Programmierung eine Rolle spielt, aber normalerweise sollten Funktion nicht auf Daten operieren die nicht als Argument übergeben wurden, ausser es handelt sich dabei um Konstanten.
Dein Code erster Quelltext würde nicht funktionieren, beziehungsweise stimmen die Namen nicht, weil in dem `set()` keine Namen sondern `Item`\s sind. Man muss also bei `give_item()` und `use_item()` ein `Item` übergeben und nicht wie `name` suggeriert eine Zeichenkette mit dem Namen.
Da dort nichts Ren'py-spezifisches enthalten ist, könntest Du solche Sachen auch einfach mit einem normalen Python 2.x ausprobieren. Wenn Du Ren'py auf Code-Ebene erweitern möchtest, solltest Du IMHO sowieso erst einmal die üblichen Python-Grundlagen lernen. Also zum Beispiel das Tutorial aus der Python-Dokumentation durcharbeiten.
Bei Werten kennen Wörterbücher keine Beschränkungen. Das können beliebige Objekte sein. Statt Namen auf Zahlen abzubilden könntest Du auch Namen auf `Item`-Exemplare abbilden.
Dein Code erster Quelltext würde nicht funktionieren, beziehungsweise stimmen die Namen nicht, weil in dem `set()` keine Namen sondern `Item`\s sind. Man muss also bei `give_item()` und `use_item()` ein `Item` übergeben und nicht wie `name` suggeriert eine Zeichenkette mit dem Namen.
Da dort nichts Ren'py-spezifisches enthalten ist, könntest Du solche Sachen auch einfach mit einem normalen Python 2.x ausprobieren. Wenn Du Ren'py auf Code-Ebene erweitern möchtest, solltest Du IMHO sowieso erst einmal die üblichen Python-Grundlagen lernen. Also zum Beispiel das Tutorial aus der Python-Dokumentation durcharbeiten.
Bei Werten kennen Wörterbücher keine Beschränkungen. Das können beliebige Objekte sein. Statt Namen auf Zahlen abzubilden könntest Du auch Namen auf `Item`-Exemplare abbilden.
Ich habe 'has_item' bloß als Funktion geschrieben, weil "if has_item('Seil')" beim Lesen vom Quelltext intuitiv etwas verständlicher ist als "if 'Seil' in player_items". Ich sehe auch die Notwendigkeit von "sauberem" Programmieren, doch wenn ich eine Funktion ohnehin nur als Abkürzung für etwas verwende und sie nicht für verschiedene Zwecke aufgerufen wird, dann erspare ich mir auf Dauer viel Tipparbeit und Parameter, wenn ich keine Argumente übergeben muß.
Eine 'Player'-Klasse anzulegen hat bei nur einer benutzten Instanz keinen Vorteil, da kann ich gleich alle Variablen einzeln ohne Klasse nehmen - das erspart mir, jedesmal 'player.' davorzuschreiben. Gäbe es mehrere Spieler oder Spielfiguren oder auch nur Charaktere, die Items herumtragen können, dann würde ich natürlich eine Klasse anlegen. Tatsächlich haben aber praktisch alle Variablen, die angelegt werden, direkt oder indirekt mit dem Spieler zu tun; andere Entitäten, für die Werte gespeichert werden müssen, kommen nicht vor.
Mir ist klar, daß Klassen eine sehr gute und auch notwendige Möglichkeit sind, Variablen und Funktionen zu sortieren. Aber wozu, wenn es nichts zu sortieren gibt?
Wahrscheinlich klinge ich gerade furchtbar unbelehrbar - tatsächlich ist mir aber daran gelegen, die Variablenaufrufe möglichst einfach zu halten, weil die Zeilen, in denen sie verwendet werden, tendenziell sehr lang und unleserlich werden können.
So wie ich das verstehe ist das gezeigte Beispiel eine Dict-Comprehension. Also muß ich auf die dict()-Funktion ausweichen, weil ich nur eine 2.x-Umgebung habe. Verstanden.
Nochmal vielen Dank für die umfangreiche und geduldige Hilfe
Eine 'Player'-Klasse anzulegen hat bei nur einer benutzten Instanz keinen Vorteil, da kann ich gleich alle Variablen einzeln ohne Klasse nehmen - das erspart mir, jedesmal 'player.' davorzuschreiben. Gäbe es mehrere Spieler oder Spielfiguren oder auch nur Charaktere, die Items herumtragen können, dann würde ich natürlich eine Klasse anlegen. Tatsächlich haben aber praktisch alle Variablen, die angelegt werden, direkt oder indirekt mit dem Spieler zu tun; andere Entitäten, für die Werte gespeichert werden müssen, kommen nicht vor.
Mir ist klar, daß Klassen eine sehr gute und auch notwendige Möglichkeit sind, Variablen und Funktionen zu sortieren. Aber wozu, wenn es nichts zu sortieren gibt?
Wahrscheinlich klinge ich gerade furchtbar unbelehrbar - tatsächlich ist mir aber daran gelegen, die Variablenaufrufe möglichst einfach zu halten, weil die Zeilen, in denen sie verwendet werden, tendenziell sehr lang und unleserlich werden können.
BlackJack hat geschrieben:Bei Werten kennen Wörterbücher keine Beschränkungen. Das können beliebige Objekte sein. Statt Namen auf Zahlen abzubilden könntest Du auch Namen auf `Item`-Exemplare abbilden.
Ah, das ist ja praktisch! Aber das Wörterbuch muß ich dann wie hier anlegen, das kann ich nicht einfach hinschreiben nehme ich mal anHyperion hat geschrieben:Code: Alles auswählen
# Dict-Comprehension erst ab Python 3.x # Du musst es in etwa so umsetzen: shop = dict((name, ...) for ...) shop = {name: Item(name, cost) for name, cost in ITEMS.items()}
So wie ich das verstehe ist das gezeigte Beispiel eine Dict-Comprehension. Also muß ich auf die dict()-Funktion ausweichen, weil ich nur eine 2.x-Umgebung habe. Verstanden.
Nochmal vielen Dank für die umfangreiche und geduldige Hilfe
- pillmuncher
- User
- Beiträge: 1484
- Registriert: Samstag 21. März 2009, 22:59
- Wohnort: Pfaffenwinkel
Verstanden? Fast, aber nicht ganz:Milkymalk hat geschrieben:So wie ich das verstehe ist das gezeigte Beispiel eine Dict-Comprehension. Also muß ich auf die dict()-Funktion ausweichen, weil ich nur eine 2.x-Umgebung habe. Verstanden.
Code: Alles auswählen
Python 2.7.2 (default, Jun 12 2011, 15:08:59) [MSC v.1500 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> {b:a for a, b in enumerate('hallo')}
{'a': 1, 'h': 0, 'l': 3, 'o': 4}
[edit]oops! Falschen Code kopiert. Jetzt stimmt's.
Zuletzt geändert von pillmuncher am Mittwoch 16. Mai 2012, 22:30, insgesamt 1-mal geändert.
In specifications, Murphy's Law supersedes Ohm's.
@Milkymalk: Also ich sehe auch bei einem Spieler einen Sinn eine Klasse anzulegen um darin alle zu ihm gehörenden Daten zu speichern. Bei `has_item()` sagst Du es dient der Lesbarkeit; das gleiche kann man doch auch für ein Player-Objekt sagen, denn ein ``player.has_item('Parrot')`` vermittelt dem Leser die Zusatzinformation worauf sich die Funktion/Methode bezieht. Bei so etwas ist Tipparbeit zu sparen IMHO auch kein gutes Argument, denn es sollte da eher zählen was einem beim Lesen mehr bringt. Quelltext wird deutlich öfter gelesen als geschrieben. Und da heute selbst die einfachen Texteditoren Autovervollständigung anhand des bereits vorhandenen Textes im Dokument bieten, ist es auch nicht so viel Mehraufwand.