Путаница с деф

Я делаю систему атаки на питоне с помощью def, но получаю сообщение об ошибке, говорящее о том, что на переменную ссылаются до присваивания, хотя я написал ее до def. Кто-нибудь знает, как?

import random
import time

monster = 20

def fight():
  print('Monster Spawned! Attack by 
typing A')
  A = str(input())

  while (A == 'A'):
    damage = range(1, 21)
    damage_done=(random.choice(damage))
    monster = monster - damage_done
    print('Slish Slash!')
    print(monster)
    print(damage_done)

fight()
if (monster < 0):
    print('Good Job')

РЕДАКТИРОВАТЬ 1: Сообщение об ошибке

Traceback (most recent call last):
File "main.py", line 17, in <module>
  fight()
File "main.py", line 12, in fight
  monster = monster - damage_done
UnboundLocalError: local variable 
'monster' referenced before assignment

Ваш цикл while никогда не завершается, если ввод A, и он никогда не запускается, если ввод не A, я не думаю, что ваше условие while должно быть A == 'A', и вам, вероятно, следует изменить имя переменной 'A' на что-то более значимое, например user_input, см. Справка

Liam 09.04.2022 09:14
Анализ настроения постов в Twitter с помощью Python, Tweepy и Flair
Анализ настроения постов в Twitter с помощью Python, Tweepy и Flair
Анализ настроения текстовых сообщений может быть настолько сложным или простым, насколько вы его сделаете. Как и в любом ML-проекте, вы можете выбрать...
7 лайфхаков для начинающих Python-программистов
7 лайфхаков для начинающих Python-программистов
В этой статье мы расскажем о хитростях и советах по Python, которые должны быть известны разработчику Python.
Установка Apache Cassandra на Mac OS
Установка Apache Cassandra на Mac OS
Это краткое руководство по установке Apache Cassandra.
Сертификатная программа "Кванты Python": Бэктестер ансамблевых методов на основе ООП
Сертификатная программа "Кванты Python": Бэктестер ансамблевых методов на основе ООП
В одном из недавних постов я рассказал о том, как я использую навыки количественных исследований, которые я совершенствую в рамках программы TPQ...
Создание персонального файлового хранилища
Создание персонального файлового хранилища
Вы когда-нибудь хотели поделиться с кем-то файлом, но он содержал конфиденциальную информацию? Многие думают, что электронная почта безопасна, но это...
Создание приборной панели для анализа данных на GCP - часть I
Создание приборной панели для анализа данных на GCP - часть I
Недавно я столкнулся с интересной бизнес-задачей - визуализацией сбоев в цепочке поставок лекарств, которую могут просматривать врачи и...
0
1
82
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Добавьте global monster на одну строку перед monster=monster-damage_done Если вы не добавите это, то python распознает monster как локальную переменную, поэтому локальная переменная используется перед назначением.

разве это не зацикливает всю деф

Kuro 09.04.2022 06:59

это не работает? Я не совсем понимаю, что ты сказал

itsme11 09.04.2022 07:02
Ответ принят как подходящий
global monster
monster = monster - damage_done

вы находитесь в функции, и она не может получить доступ к переменной за ее пределами, поэтому скажите функции, что есть глобальная переменная с этим именем снаружи и что это глобальная переменная... если нет, она будет считаться локальная переменная, и она будет искать переменную monster внутри функции

Я думаю, что ваш код нуждается в переписывании:

import random
monster = 20
def fight():
  print('Monster Spawned! Attack by typing A')
  A = str(input())
  global monster
  if A == 'A':
      while monster > 0:
          damage = range(1, 21)
          damage_done=(random.choice(damage))
          monster = monster - damage_done
          print('Slish Slash!')
          print(monster)
          print(damage_done)
      else:
          print('Good Job')
fight()

вы хотите, чтобы какое-то время работало, если только monster < 0 и if monster < 0, тогда вы хотите напечатать good job.

Почему ул (ввод ())? Вы слышали о Рэндинте? Почему монстр должен быть глобальным? Он может быть локальным — просто инициализируйте его перед тестированием пользовательского ввода.

Lancelot du Lac 09.04.2022 08:23

@LancelotduLac ты читал код вопроса? он использовал ул и глобальная переменная. Я знаю, что они неверны, и, по крайней мере, они могут быть лучше, но мы бомбардируем его информацией? В моем коде есть некоторые моменты, которые он должен рассмотреть и проверить, пожалуйста, не добавляйте больше информации и не разочаровывайте его в начале :)

MoRe 09.04.2022 15:38

одна небольшая придирка заключается в том, что вы можете описать, почему глобальная переменная не может быть доступна без явного объявления ее как таковой. это именно потому, что monster присваивается (где угодно) внутри функции, что делает его локальным для функции. Если бы монстр не был назначен внутри функции, а только упоминался, этот код работал бы без ключевого слова global.

Michael Delgado 09.04.2022 18:49

@MichaelDelgado большое спасибо и хороший момент ... Я попытался сказать это «поиском монстра» и простым способом, но я думаю, что ваш комментарий лучше

MoRe 09.04.2022 19:11

Есть несколько проблем с вашей программой:

Проблема 1:

Вы получаете эту ошибку:

UnboundLocalError: local variable 
'monster' referenced before assignment

потому что ваша переменная monster недоступна внутри функции.

Вы объявляете это вне функции fight(), поэтому fight() не знает о переменной. (Как правильно указал @MoRe).


Проблема 2:

Вы не возвращаете переменную monster из своей функции fight(), поэтому, если вы хотите использовать обновленное значение переменной monster, вам нужно будет вернуть обновленное значение из функции fight().


Проблема 3:

Ваш цикл while будет запущен только один раз, если входной сигнал A, и никогда не завершится. Если ввод не A, тогда ваш цикл while никогда не запустится.


Проблема 4:

Как упомянул @Lancelot du Lac, я не думаю, что вам нужно преобразовывать input() в строку, вы можете просто прочитать ввод и проверить, соответствует ли он символу A.

The input() function always converts the user input into a string and then returns it to the calling program.

Справка

Решение 1:

Поскольку ответ @More предполагает, что вы можете объявить переменную monster как глобальную переменную:

global monster
monster = monster - damage_done

Хотя это устраняет вашу ошибку, я не думаю, что это лучшее решение. В общем случае было бы лучше передавать параметры функциям, а не объявлять их как глобальные переменные.

См.: (Python) Должен ли я использовать параметры или сделать их глобальными?


Решение 2

Вам не нужно объявлять monster как global, вы также можете просто передать его как параметр следующим образом:

import random
import time

monster = 20
def fight(monster):
  print('Monster Spawned! Attack by typing A')
  A = input()
  if A == 'A':
      while monster > 0:
          damage = range(1, 21)
          damage_done=(random.choice(damage))
          monster = monster - damage_done
          print('Slish Slash!')
          print(monster)
          print(damage_done)
      else:
          print('Good Job')
fight(monster)

Решение 3

Принимая во внимание все проблемы, вы можете написать свою программу, чтобы обеспечить большую гибкость.

import random
import time

def fight(monster, user_input):
    if user_input == 'A':
        damage = range(1, 21)
        damage_done=(random.choice(damage))
        monster = monster - damage_done
        print('Slish Slash!')
        print(monster)
        print(damage_done)
    else:
        print('You have not typed A')
    return monster

monster = 20
user_input = ''
while True:
    user_input = input('Monster Spawned! Attack by typing A: ')
    monster = fight(monster, user_input)
    if (monster < 0):
        print('Good Job')
        break
  • Программа инициализирует переменную monster значением 20 (согласно вашему примеру), а затем передает эту переменную функции, обновляя ее при возврате каждого вызова функции.

  • Программа неоднократно запрашивает у пользователя ввод данных и отображает сообщение об ошибке, если они не вводят A. Этот подход является более надежным, поскольку он позволит вам позже добавить другие параметры пользовательского ввода, если вы решите это сделать. (Если у вас есть только один вариант, это не будет применяться).

  • Также лучше иметь гибкую функцию, которую можно вызывать несколько раз с разными входными данными (поэтому мы используем параметры для обеспечения такой гибкости). Если вам абсолютно необходимо, чтобы цикл while находился внутри функции fight(), вы можете переместить его внутрь, но я не вижу веской причины, по которой вам нужен цикл while, который никогда не завершается внутри функции fight().

РЕДАКТИРОВАТЬ: Спасибо @MoRe и @Lancelot du Lac за их полезный ответ, комментарии и вклад.

Использование таких строк для управления циклом — не лучшая практика. пока верно с соответствующим расположением перемена является более распространенной парадигмой.

Lancelot du Lac 09.04.2022 09:21

Спасибо, я обновил ответ, извините за ошибку.

Liam 09.04.2022 09:24

и спасибо за ваш исчерпывающий ответ, но я думаю, что время можно убрать, потому что мы его не используем, и вы можете оптимизировать его больше... например, print(...,sep="\n") и random.randint...

MoRe 09.04.2022 19:22

Спасибо за ваш полезный комментарий @MoRe, я думал об удалении time, но я предположил, что ОП импортировал его и просто не включил раздел кода, который его использовал, но я, конечно, мог ошибаться, я сделал предположение и в эфире на стороне осторожности. Конечно, нужно сделать больше оптимизаций, но я не хотел терять OP из-за возможности понять изменения и проблему.

Liam 09.04.2022 21:06

Другие вопросы по теме