Page 1 of 1

Values returning 'None' for variables

Posted: Thu Apr 17, 2014 4:46 am
by arawra
In my subclass for dict, the userid is being passed properly, but it is not properly setting self[userid] as its value is 'None' as well as the variable value. The variable spawnee is also returning 'None' for its value.

Code: Select all

def debug(msg=[]):
    print('\n[D&D Debug] %s\n'%msg)

@Event
def player_spawn(game_event):
    spawnee_userid = game_event.get_int('userid')
    spawnee = dndPlayerDictionary[spawnee_userid]
    debug(spawnee)
   
class _dndPlayerDictionary(dict):
    def __missing__(self, userid):
        value = self[userid] = dndPlayer(userid)
        debug("%s %s %s"%(userid, self[userid], value))
        return value
       
    def __delitem__(self, userid):
        if userid in self:
            super(_dndPlayerDictionary, self).__delitem__(userid)
           
dndPlayerDictionary = _dndPlayerDictionary()
   
class dndPlayer(PlayerEntity):

    def __new__(self, userid):

        debug('New dndPlayer object')
        # Since PlayerEntity requires an index for instantiation, we need to get the index
        index = index_from_userid(userid)
        self = super(dndPlayer, self).__init__(index)
        # Call the "super" class (which is PlayerEntity in this instance) __init__ method with the index
        return self
       
    def __init__(self, userid):
        PlayerDataDictionary[self.steamid].name = self.name
        self.playerinfo = self.info

Posted: Thu Apr 17, 2014 5:10 am
by L'In20Cible
Well, replace the following line:

Code: Select all

self = super(dndPlayer, self).__init__(index)
To the following one:

Code: Select all

self = PlayerEntity.__new__(dndPlayer, index)
Please, always post your complete code so we don't have to guess your imports and/or custom global variables (such as PlayerDataDictionary) when trying to debug your code!

Posted: Thu Apr 17, 2014 3:34 pm
by satoon101
Actually, you just need to change __init__ to __new__ with the super line. Also, "self" is misleading as the first argument in your __new__ method, since the object it represents is the class itself, not the instance, as __new__ is a "class" method.

Posted: Thu Apr 17, 2014 8:33 pm
by Doldol
Yes, to clarify: __new__ returns a new instance of the class, while __init__ gets called on the initialisation of said instance.

Posted: Thu Apr 17, 2014 8:56 pm
by L'In20Cible
satoon101 wrote:Actually, you just need to change __init__ to __new__ with the super line.
He will also need to add "self" as first argument since __new__ is a static method.

Posted: Fri Apr 18, 2014 4:04 am
by satoon101
Yes, sorry about that. Though, again, "self" is very misleading. It is very typical to use "cls" to represent the class object in class methods:

Code: Select all

class dndPlayer(PlayerEntity):
    def __new__(cls, userid):
        index = index_from_userid(userid)
        self = super(dndPlayer, cls).__new__(cls, index)
        return self


Also, I am not sure why you bother with this:

Code: Select all

        self.playerinfo = self.info

I am contemplating changing that property to be named playerinfo anyway, as it better describes what value is held by that property. However, setting one attribute to just equal another seems a bit silly.

Posted: Fri Apr 18, 2014 11:49 am
by arawra
Only reason I am using "self.playerinfo = self.info" is because I was using self.playerinfo in many of dndPlayer's methods. I'd rather have one line to change when the update happens than many.