Изменения переменной класса Python не сохраняются

Я пытаюсь работать над текстовым приключением, чтобы сохранить мой интерес, пытаясь изучить концепции и нюансы Python. Первоначально я следил за учебником YouTube (серия из 6 частей, ссылка на часть 1 предоставлена: https://www.youtube.com/watch?v=MFW8DJ6qsak).

Я создал класс игрока, как показано ниже:

class Player:
    def __init__(self):
        self.name = ''
        self.jobclass = ''
        self.currenthp = 0
        self.totalhp = 0
        self.currentmp = 0
        self.totalmp = 0
        self.physical_damage = 0
        self.physical_defense = 0
        self.magic_attack = 0
        self.magic_defense = 0
        self.speed = 0
        self.luck = 0
        self.status_effect = []
        self.location ='b2'
        self.game_over = False

myPlayer = Player()

Моя текущая проблема заключается в попытке назначить игроку определенные характеристики на основе выбранной им работы персонажа, то есть:

def setup_game():
    ...
    player_jobclass = input("> ")
    myPlayer.jobclass = player_jobclass
    valid_jobs = ['warrior', 'mage', 'thief', 'cleric']
    while player_jobclass.lower() not in valid_jobs:
        print("Please choose a valid class")
        player_jobclass = input("> ")
    if player_jobclass.lower() in valid_jobs:
            myPlayer.jobclass = player_jobclass
            print("Ah, the " +player_jobclass.lower()+ ". Fine choice!\n")

    #Class Starting Stats
    if myPlayer.jobclass is 'warrior':
        self.currenthp = 20
        self.totalhp = 20
        self.currentmp = 10
        self.totalmp = 10
        self.physical_damage = 10
        self.physical_defense = 10
        self.magic_attack = 2
        self.magic_defense = 3
        self.speed = 4
        self.luck = 4
        self.location = 'd1'
    elif myPlayer.jobclass is 'mage':
        self.currenthp = 10
        self.totalhp = 10
        self.currentmp = 20
        self.totalmp = 20
        self.physical_damage = 2
        self.physical_defense = 3
        self.magic_attack = 10
        self.magic_defense = 7
        self.speed = 7
        self.luck = 3
        self.location = 'a1'
    ...
    main_game_loop()

Потому что после того, как все это запускается, я нормально захожу в игру, и все мои движения и небольшие действия работают нормально, однако, если я попытаюсь распечатать «статистику» игрока с помощью чего-то вроде:

def show_stats():
hpmpadarmPrint = ("" + str(myPlayer.currenthp) + "/" + str(myPlayer.totalhp) + " hp " + str(myPlayer.currentmp) + "/" + str(myPlayer.totalmp) + " mp " + str(myPlayer.physical_damage) + " ATK " + str(myPlayer.physical_defense) + " ARM \n")
mgclckspdPrint = ("" + str(myPlayer.magic_attack) + " AP " + str(myPlayer.magic_defense) + " MR " + str(myPlayer.speed) + " SPD " + str(myPlayer.luck) + " LCK \n")

Напечатает только:
0/0 hp 0/0 mp 0 ATK 0 ARM 0 AP 0 MR 0 SPD 0 LCK

Я могу сказать, что есть какая-то более крупная концепция, которая ускользает от меня в том, что касается присвоения значений, поскольку даже self.location = 'b2' ДОЛЖЕН быть там, иначе игра не запустится, поскольку myPlayer на самом деле не присваиваются значения, которые, как я считаю, должны. Это также мешает моей функции change_text_speed() работать, а также ... вы поняли.

Угадайте, что главный вопрос будет заключаться в следующем: как сохранить новые значения после присвоения?


person Chris    schedule 29.07.2018    source источник
comment
Почитайте о наследовании. Кроме того, я думаю, что статистику следует задавать в методе __init__.   -  person Brian    schedule 29.07.2018
comment
Не сравнивайте строки с is. Используйте ==.   -  person Aran-Fey    schedule 29.07.2018
comment
Очень сложно понять, что происходит с вашей функцией setup_game. Откуда self? В любом случае ваша непосредственная проблема, вероятно, связана со сравнением строк с is вместо ==. Не делай этого. is для идентичности, == для равенства. Вы не можете гарантировать, что равные строки будут идентичными строками, т. е. одним и тем же строковым объектом.   -  person juanpa.arrivillaga    schedule 29.07.2018
comment
Кроме того, здесь возможен вариант наследования. Но не думайте, что это единственный вариант.   -  person juanpa.arrivillaga    schedule 29.07.2018
comment
Спасибо за разъяснения по поводу is и ==. self - это то, как (теперь я думаю, не так хорошо, как я когда-то думал) руководство было основано на первоначальном __init__(self)   -  person Chris    schedule 29.07.2018
comment
self — это (условное) имя экземпляра класса, который используется внутри методов класса. Но это не имеет никакого значения вне определения класса. Поэтому, когда код вне определения Player хочет получить доступ к атрибутам (включая методы) экземпляра класса myPlayer, ему нужно использовать myPlayer, а не self.   -  person PM 2Ring    schedule 29.07.2018
comment
Руководство по стилю (также известное как форматирование): python.org/dev/peps/pep-0008< /а>   -  person Patrick Artner    schedule 29.07.2018
comment
@Chris, верно... self обычно является первым параметром метода, но в сигнатуре вашей функции он не определяет никаких параметров, поэтому self будет неопределенным. Обратите внимание, что никаких ошибок не выдается, потому что этот код никогда не достигается из-за проблем с is/==.   -  person juanpa.arrivillaga    schedule 29.07.2018


Ответы (2)


self и myPlayer — это два разных объекта. Есть два исправления, которые вы можете сделать. Во-первых, замените себя на myPlayer при настройке статистики.

if myPlayer.jobclass is 'warrior':
    myPlayer.currenthp = 20
    myPlayer.totalhp = 20
    myPlayer.currentmp = 10
    ...

Второй и, на мой взгляд, лучший подход — установить статистику в __init__. Это будет выглядеть примерно так.

if self.jobclass is 'warrior':
    self.currenthp = 20
    self.totalhp = 20
    self.currentmp = 10
    ...

Чтобы сделать код еще лучше, прочитайте о наследовании и создайте класс для каждого класса заданий. В конце концов, вы назвали это работой класс.

person Brian    schedule 29.07.2018
comment
Ооо, а потом просто присвоить myPlayer одному из классов? Если это так, то это решение действительно имеет ТОННУ смысла! Спасибо. - person Chris; 29.07.2018
comment
Да, вы поняли. @Крис - person Brian; 29.07.2018

is проверяет, указывают ли две переменные на один и тот же объект. В таких случаях, как ваш, при вводе пользовательских строк у вас, скорее всего, будет два разных строковых объекта с одинаковым значением. Например.:

>>> x = input("")
ab
>>> x
'ab'
>>> x == "ab"
True
>>> x is "ab"
False

Короче говоря, используйте ==, а не is, когда вы проверяете игроков jobClass.

person Mureinik    schedule 29.07.2018