Передача переменных обратно в класс в Python

Я новичок, пожалуйста, потерпите меня. Ниже мой код:

class Player():
    name = "UnknownName"
    stren = 10
    dex = 10
    con = 10
    intel = 10
    wis = 10
    cha = 10

    def randAssign(self):
        global stren, dex, con, intel, wis, cha
        stat_List = [stren, dex, con, intel, wis, cha]

        for stat in stat_List:
             r_1 = random.randint(1,6)
             r_2 = random.randint(1,6)
             r_3 = random.randint(1,6)
             r_4 = random.randint(1,6)

             stat_Val = r_1 + r_2 + r_3 + r_4 - min(r_1, r_2, r_3, r_4)
             stat = stat_Val

randAssign - это метод в Player(). Я пытаюсь установить статистику игрока случайным образом, и мне нужно переписать переменные класса в момент активации randAssign(). По той или иной причине использование global передает следующую ошибку:

NameError: name 'stren' is not defined. 

Использование нелокального кода приводит к этой ошибке:

SyntaxError: no binding for nonlocal 'stren' found

Без глобального или нелокального, он просто не переписывает Player()'s переменные. Я сделал дюжину итераций этого, от совершенно неправильного до "Я думал, что это будет работать, но это не так", и мне нужна помощь.

3 ответа

Подобное определение ваших переменных внутри вашего класса сделает все экземпляры вашего класса общими для этих переменных, что может привести к нестандартным ситуациям (особенно для изменяемых объектов). (обратитесь к документации по Python) Скорее всего, вы захотите использовать это:

class Player:

    def __init__(self):
        self.stren = 10
        self.xcx = 10
        etc.

    def randAssign(self):
        self.stren = randint(1,10)
        ...

Не совсем уверен, если вы знакомы с методами класса против экземпляра, но попробуйте это:

class Player():
    name = "UnknownName"
    stren = 10
    dex = 10
    con = 10
    intel = 10
    wis = 10
    cha = 10

    @classmethod
    def randAssign(cls):
        stat_List = [cls.stren, 
                     cls.dex, 
                     cls.con, 
                     cls.intel, 
                     cls.wis, 
                     cls.cha]

        for stat in stat_List:
             r_1 = random.randint(1,6)
             r_2 = random.randint(1,6)
             r_3 = random.randint(1,6)
             r_4 = random.randint(1,6)

             stat_Val = r_1 + r_2 + r_3 + r_4 - min(r_1, r_2, r_3, r_4)
             stat = stat_Val

Учитывая то, что выглядит, как вы делаете (создание случайной статистики игрока), это было бы более уместно, если бы это делалось для каждого экземпляра игрока под __init__ призывать к инстанции

Прочтите это ТАК для получения дополнительной информации о разнице между этими двумя методами.

Изменить: чтобы проиллюстрировать точку в комментариях...

Это проблема, с которой вы столкнетесь при использовании вашего метода (мой пример, приведенный выше, решает только вашу проблему с областью видимости, а не вашу реализацию)

class Temp:
    stat = 1
    @classmethod
    def test(cls):
        stats = [cls.stat] # container contains copies of primitive types 
        print (stats) # [1]
        for i in range(1):
            stats[i] = (stats[i] + 2) * 3 # 1 + 2 * 3 = 9
        print (stats) # [9]
        print (cls.stat) # 1

Чтобы сделать то, что комментарии появляются, вы хотите:

class Temp:
    stats = {'stat': 1}
    @classmethod
    def test(cls):
        stats = [cls.stats] # container contains reference to another container
        print (stats) # {'stat': 1}
        for stat in stats:
            cls.stats[stat] = (cls.stats[stat] + 2) * 3 # 1 + 2 * 3 = 9
        print (stats) # {'stat': 9}
        print (cls.stats) # {'stat': 9}, look they updated!

Поскольку вы уже проходите self аргумент в определении вашей функции, вы должны ссылаться на эти переменные в соответствующем пространстве имен:

self.stren = ...

вместо

globals stren
stren = ...
Другие вопросы по тегам