int object is not subscriptable

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
JMHin20xx
User
Beiträge: 2
Registriert: Freitag 1. März 2013, 17:41

Hallo,
ich benutze Python zusammen mit dem 3D Programm Blender. Dort ist Python angewendet und mit eigens definierten Funktionen ausgestattet.
Aber anscheinend habe ich ein reines Python Problem.
Ich hatte früher Php und Java mal angelernt und irgendwie passt der übertrag davon in Python nicht so ganz.
Nach diversen Tests und erfolgloser Suche (bzw. Unverständnis) melde ich mich hilfesuchend an euch :-)
Wenn ich hier falsch bin, bzw. das Blenderzeug euch verwirrt, sagt bescheid.

Erstmal der Code. Das Problem liegt ganz unten, ich habe die Problem-Zeile nochmal mit Kommentar gekennzeichnet.
Meine Ideen und Ziele habe ich ganz nach unten geschrieben, weil erstmal klar sein muss, ob der Code hier überhaupt "akzeptiert" wird.
Danke auf jeden Fall für eure Geduld!

Code: Alles auswählen

import bge


def main():

    cont = bge.logic.getCurrentController()
    own = cont.owner
    #scene <--sucht blender sich
    scene = bge.logic.getCurrentScene()
    print(scene, "is the current scene") 
    #search for property 'player' <---das macht Blender automatisch, die Liste wird korrekt erstellt, Suzanne und Player Collision werden nachfolgend ausgedruckt (siehe auch konsolenzitat)
    playerlist = [s for s in scene.objects if 'player' in s]
    if playerlist :
            print(playerlist, "is the List with the property x")
    i = 0
    pLl = len(playerlist)
    print(pLl , "is the length of the playerlist")
    print(i , "is i")
    print(playerlist[0], "Playerlistentry 0")
    print(playerlist[1], "Playerlistentry 1")
    print(playerlist[i],"is playerlistentry i")
    
    #forloop
    
    for playerlist in range(0,pLl):
        print(i , "value of i in forloop-beginning" )
        #same as before but, next line provides "int object is not subscriptable ERROR!" why? and how is it to solve?
        print(playerlist[i],"is playerlistentry i")
        
       
main()


Das sagt mir die Blender-Console dazu - Suzanne, Spaceship Collision, Enemy Collision sind Objekte aus Blender, die über die internen Funktionen aus der Szene aufgenommen werden.
Blender Game Engine Started
Scene is the current scene
[Suzanne, Spaceship Collision] is the List with the property x
2 is the lenght of the playerlist
0 is i
Suzanne Playerlistentry 0
Spaceship Collision Playerlistentry 1
Suzanne is playerlistentry i
0 value of i in forloop-beginning
Python script error - object 'Enemy Collision' controller 'Python':
Traceback <most recent call last>:
File "errorcheck_int_not_subscriptable1.py", line 31, in <module>
File "errorcheck_int_not_subscriptable1.py", line 28, in main
TypeError: 'int' object is not subscriptable
Blender Game Engine Finished
Der Witz an der Sache ist, vor der forschleife bekomme ich noch die korrekte Ausgabe, in der forschleife ergibt die gleiche Syntax einen Fehler.
Meine Vermutungen:
- ich habe etwas mit lokaler und globaler Variable nicht beachtet.

Mein Unverständnis:
- wenn ich die incrementvariable i als String nutze bekomme ich die Aufforderung einen Integer zu wählen, aber der führt ja zu der entsprechenden Problemphrase.

Mein Ziel:
- durch die Liste durchinkrementieren.
Ich will eine Funktion nutzen, welche die Distanz zwischen 2 Objekten misst (dem Scriptbesitzerobjekt und dem player-objekt), von Blender habe ich nun die Spielerliste bekommen, also die Referenzen. Nun will ich die Funktion auf jedes der in der Liste gespeicherten Objekte anwenden und diese ggf. woanders speichern.
In meinem Anwendungsfall will ich die Distanzfunktion nutzen um zu sehen, welches Objekt ist das nächste. Dazu muss die Referenz und die Distanz des Objekts zusammen auffindbar sein, da ich später anhand der Distanz das nähere Objekt verfolgen möchte. Dazu kann ich Blender ein "Suche/Verfolge" Funktion benutzen, wenn ich das Objekt kenne.

Meine Idee:
- Liste benutzen, Funktion für jedes Item der Liste in der forschleife benutzen, in anderer liste abspeichern, bzw. nur das nähere merken. Aber das geht wohl nicht :-( ...so einfach.

Ihr seid unten angekommen :-)
Danke!
und einen schönen Tag/Abend/Nacht/Morgen noch!
Zuletzt geändert von Anonymous am Freitag 1. März 2013, 18:16, insgesamt 3-mal geändert.
Grund: Quelltext in Python-Tags gesetzt.
BlackJack

@JMHin20xx: Schau doch mal welchen Namen Du in der problematischen Schleife für die Laufvariable verwendest. ;-)

Edit: Datentypen sollte man in Namen übrigens nicht verwenden. Es passiert doch relativ häufig, dass man den Typ im Laufe der Entwicklung mal ändert, und dann muss man entweder überall den Namen anpassen, oder man hat Namen, die verwirrenderweise nicht mehr zum Typ des Wertes passen. Also `playerlist` könnte man `players` nennen.

Ausserdem würde ich Abkürzungen vermeiden. `owner` und `controller` kann man auch Ausschreiben.
BlackJack

@JMHin20xx: Wenn Dein Ziel das iterieren über die Liste ist, dann ist das einfacher als Du das da gerade versuchst, denn dann braucht man den Index überhaupt nicht. Du kannst *direkt* über die Elemente iterieren.

Und was die Entfernungen angeht, da könntest Du Entfernung und Objekt in einem Tupel speichern und diese Tupel in eine Liste stecken. Oder Du sortierst die Liste mit einer entsprechenden `key`-Funktion, oder wenn Du nur das nächstliegende Objekt wissen möchtest, dann verwende einfach die `min()`-Funktion mit einer entsprechenden Funktion als `key`-Argument.

Edit: Ungetestet:

Code: Alles auswählen

def main():
    scene = bge.logic.getCurrentScene()
    print(scene, 'is the current scene')
    
    players = [o for o in scene.objects if 'player' in o]
    if players:
        print(players, 'is the list with the property "player"')
    
    for i, player in enumerate(players):
        print('{0} is list entry {1}'.format(player, i))
    # 
    # `players` sortieren.
    # 
    players.sort(key=distance_func)
    nearest_player = players[0]
    # 
    # Oder den Eintrag mit der kleinsten Entfernung bestimmen.
    # 
    nearest_player = min(players, key=distance_func)
    # 
    # Und das ganze noch mal ohne Liste als Zwischenergebnis.
    # 
    nearest_player = min(
        (o for o in scene.objects if 'player' in o),
        key=distance_func
    )
Für `distance_func` muss man sich etwas passendes definieren. Eine (möglicherweise lokale) Funktion, eine anonyme Funktion (``lambda``), oder etwas mit `functools.partial()` aus einer vorhandenen Funktion oder Methode um den Abstand zu ermitteln.
JMHin20xx
User
Beiträge: 2
Registriert: Freitag 1. März 2013, 17:41

Danke schoneinmal!
Ich spare mir mal meinen verwirrten Post auf die Einzeilenantwort (am Anfang - schon wegeditiert^^)und nehme mir mal etwas Zeit zum verstehen! Die Distance-Funktion liefert mir Blender, zum Glück^^

Ach und, ich soll nicht mehr im Forum das Code Tag sondern das Python Tag nutzen? Ich habe sofort wie gewohnt CODE angeklickt und die andere Funktion übersehen :-)
Braucht man CODE dann noch?

Wie man das Problem mit der Laufvariable löst, habe ich aber nicht verstanden. Meine Tests haben nichts positives bewirkt.
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

JMHin20xx hat geschrieben:Braucht man CODE dann noch?
Es gibt hier auch noch anderen Code ;)
JMHin20xx hat geschrieben:Wie man das Problem mit der Laufvariable löst, habe ich aber nicht verstanden. Meine Tests haben nichts positives bewirkt.
Du ueberschreibst deine Liste - auf die du in der Schleife zugreifen willst - mit der Laufvariablen.

Code: Alles auswählen

for playerlist in range(0,pLl):
sollte (nach deinem restlichen Code)

Code: Alles auswählen

for i in range(0,pLl):
heissen.

Aber noch besser:

Code: Alles auswählen

for i, player in enumerate(playerlist):
    print(i , "value of i in forloop-beginning" )
    print(player ,"is playerlistentry i")
Antworten