»Non subscriptable«... BUT IT IS! @`~´@

I command:


[...]
plr=cnt.sensors["Collision"].hitObject
if plr["feelgood"] < 100:
[...]

And the Console says:

Type Error: ‘NoneType’ object is not subscriptable

But the Code Works, and the hitObject, which is in all Cases the Player, obviously ~is~ subscriptable – so why does the Console mention such an Error when ingame there is absolutely no Problem with it? (That occurs in several Script running within that .blend!)

Blender 259.3

The problem here is that there is no collision going on. When there is no collision, hitObject returns None. In the line after that, you try to access a property on that object, but there isnt anything on a NoneType object. I would suggest changing it to:


[...]
plr=cnt.sensors["Collision"].hitObject
if plr != None and "feelgood" in plr and plr["feelgood"] < 100:
[...]

Thank you very much, mokazon! :}
Framerate also gets better without Masses of such Error Messages! :RocknRoll:

You can also use “try” and “except” commands too. These will try to do the action, and if not, they don’t send an error message unless you want them too. The except message is very useful, as it allows you to “print” some more info to find out exactly what went wrong (like what object is running the script and other things.

or

you can check the sensor to be positive


collisionSensor = 
cnt.sensors["Collision"]
if not collisionSensor.positive:
  return

or

you check the hitObject not to be None


if collisionSensor.hitObject is None:
  return

btw, what is a “plr”?

Thank you two for the Information, I will dig into it! : )

@ Monster:
A »plr« is a »Player« reduced to three Letters. :wink:
I like limiting my self-defined Names to three Letters, just like I write »cnt« where »cont« is common.
I think: The less Sign have to be read the easier the Script can be handled. (Some people even would reduce their »own« or »obj« to just one »o«, but single Letters would allow quite little Space for me to recognize several Names…)

Smoking_mirror: try and accept is usually not a good habit to get into :wink: I wouldnt reccomend using it often

Ah thanks, that is not obvious

No this reduces the readablity of the code. It is not obvious what it means. And a reader has to guess. And he might guess wrong ;).

This is pure lazyness. It can produce a lot of avoidable work later (when trying to remember what it means :D).
Using one letter names is accepable … but in very very narrow context.
See PEP#008 - Style Guide for Python Code see naming conventions

Do you know details of that?
I know that bare except statements should be avoided ( see PEP#008 ) but not the general use.

And I agree it can look very uggly especially if try…except is used nested.

@Monster:
I meant the use of:


try:
        <code here>
except:
         pass #or continue

it really defeats the purpose of try accept. It is usually used for error detection, but for C.A.'s case it is unneeded.

Actually, try and except can be used not necessarily for error detection. For example, you can do it to check to see if variables have been initialized yet, rather than checking it. That can save some frames on many objects (once the BGE can handle Python running through thousands of objects at a time).

The blender error reporting in console is usually quite detailed, but sometimes you need extra information (for example the name of the object, and several of it’s properties) so in that case Try and Except can be very useful.

I’m not suggesting using them regularly instead of trying to handle errors. :slight_smile:
It’s better to know why it failed (object == None or object.invalid() or some other reason) then you can try to make it not fail.

Mokazon, you are right this is a bare exception without any exception handling. This simply supresses any error message and is in genreal very dangerous ;).

the better code would be:


try:
   value = obj["propertyName"]
except KeyError:
           obj["propertyName"] = defaultValue

any other error would still be seen via default exception handling.

The error is self-explanatory. You are trying to subscript an object which you think is a list or dict, but actually is None. This means that you tried to do:

None[something]

This error means that you attempted to index an object that doesn’t have that functionality. You might have noticed that the method sort() that only modify the list have no return value printed – they return the default None. ‘NoneType’ object is not subscriptable is the one thrown by python when you use the square bracket notation object[key] where an object doesn’t define the getitem method . This is a design principle for all mutable data structures in Python.

You could say that about any error, except it doesn’t actually help them understand why it’s happening. Plus it’s infuriating when someone says answer is obvious when they clearly haven’t understood it.

The problem isn’t that the hit object isn’t subscriptable, it’s that they haven’t got a hit object. All of this was explained to OP 10 years ago(!!!) and it sounds like they understood it at the time.

So to give the right answer, because solutions in this topic are just outdated, and try:/except should not be used like that, you still can but not recommended.

So in a situation as the OP had 10 years ago…:

plr=cnt.sensors["Collision"].hitObject
if plr["feelgood"] < 100:

Becomes:

plr = cnt.sensors["Collision"].hitObject

#if you are sure the property exists
if plr and plr["feelgood"] < 100:
    #do stuff

Or you can do 1 more check

plr = cnt.sensors["Collision"].hitObject

if plr:
    #water proof check to make sure property exists
    if "feelgood" in plr and plr["feelgood"] < 100:
        #do stuff

Both methods do the exact same thing only written differently, usually to print errors in multiple stages of the process.

I don’t see how that’s fundamentally any different to what Monster/mokazon said in their first posts.

For the record, I agree that try/except isn’t a good way to handle that, but I thought the thread covered that already.

Oops skimmed to fast over it didn’t even see monsters first post, that is indeed correct.