[파이썬] 12강 지역범위(Local Scope), 전역 범위(Global Scope) +랜덤숫자 추출하여 예측하는 게임 만들기
유데미 안젤라유 파이썬 12강 요약
12강에서는 스코프(scope)라는 개념에 대해서 배웠는데, 함수를 만든 후 해당 함수의 바깥에서, 해당함수 내부의 변수를 호출해야 하는 경우 꼭 알아야 하는 부분이다. 사실 이 글을 적는 지금도 스코프를 정확하게 이해하진 못했지만, 일단 이해한 부분까지만이라도 정리해보려고 한다. 이 스코프의 개념을 이해했다면, 랜덤으로 숫자를 추출해놓고 이를 예측하는 게임에서 적절하게 응용해볼 수 있다.
Scope
스코프는 파이썬에서 '유효 범위'라고 불린다. 조금 더 풀어 설명하자면 '특정 변수가 유효할 수 있는 범위'다. 예를 들면 어떤 함수안에 변수를 지정해놓고, 해당 변수를 호출 했을때 원하는 값이 정상적으로 출력되는가? 라고 했을때 정상적으로 출력된다면 해당 변수는 유효범위 안에 들어와있다고 볼 수 있다. 예시문을 살펴보자.
#enemies라는 변수를 1로 지정
enemies = 1
def increase_enemies():
# 함수 안에서 enemies를 2로 지정
enemies = 2
print(f"enemies inside function: {enemies}")
# 해당 함수를 호출했을때 1이 출력될까? 아님 2가 출력될까?
increase_enemies()
print(f"enemies outside function: {enemies}")
결과는 아래와 같이 출력된다.
enemies inside function: 2
enemies outside function: 1
스코프는 지역스코프(local scope)와 전역스코프(global scope)로 분류된다.
지역 스코프 부터 살펴보자.
Local Scope 지역 스코프, 지역 범위
def drink_potion():
potion_strength = 2 #potion_strength는 지역 변수
print(potion_strength) #함수 drink_potion의 지역변수 출력
drink_potion()
print(potion_strength) #지역변수를 함수 바깥에서 출력 (에러발생 지점)
위와 같이 drink_potion()이라는 함수를 호출하고,
potion_strength라는 함수 내의 변수를 단독으로 출력하는 경우 어떤 결과가 나타날까 ?
아래 콘솔을 보듯이 print(potion_strength)로 인해 에러가 발생하였다.
에러가 발생한 이유를 이해하기 위해선, Local Scope의 개념에 대해 알아야 한다.
Local Scope 즉, 지역 범위는 함수 내에 존재하는 유효범위를 의미한다.
이것은 함수 내에 있는 변수는 함수 내부에 있을때만 사용할수 있다는 의미이며, 해당 변수는 지역범위를 가진 것이므로 오직 drink_potion이라는 함수 내에서만 접근가능하다. 위 콘솔에서 에러가 났듯이 함수 외부에서는 접근이 불가하므로, 다른 함수 내부에 새 변수나 새 함수를 만드는 경우에만 접근이 가능하다.
특정 변수를 함수 밖에서도 사용하려면 Global Scope, 즉 전역 범위의 개념을 알아야 한다.
Global Scope 전역 스코프, 전역 범위
함수의 외부에서 변수를 선언할때, 해당 변수는 '전역 변수'라고 칭하며
해당 전역변수가 유효하게 동작할수 있는 영역을 '전역 범위'라고 한다.
player_health = 10 #전역변수
def drink_potion():
potion_strength = 2 #지역변수
print(player_health) #전역변수 출력
drink_potion()
이러한 전역범위 및 지역범위의 개념은 변수에만 한정하여 적용되지는 않는다.
함수와 기타 개념에도 적용이 가능한데, 이때 이 개념을 '네임스페이스'(Namespace)라고 한다.
(네임스페이스에 대한 개념은 다음에 다뤄보기로..)
프로젝트: 랜덤으로 추출된 숫자를 예측하는 게임 만들기
게임의 골자는 이러하다.
1) 사용자는 게임의 난이도를 선택하여 정해진 횟수만큼 숫자를 예측할 수 있다.
2) 예측에 실패하면 횟수가 차감된다.
(7강에서 다룬 행맨게임의 흐름과 유사하다(포스팅 참고))
import random
from art import logo
HARD_LEVEL_TURNS = 5 #전역 변수가 사용된 부분
EASY_LEVEL_TURNS = 10
def guess_number(random_pick, guess, turns):
if random_pick > guess:
print("Too low")
return turns -1
elif random_pick < guess:
print("Too high")
return turns -1
else:
print(f"The number is {random_pick}. You got it!")
#Make function to set difficulty.
def game_level():
level_choice = input("What difficulty level would you like to start with? Type 'hard' or 'easy': ")
if level_choice == "hard":
return HARD_LEVEL_TURNS
else:
return EASY_LEVEL_TURNS
def game_start():
print(logo)
print("Welcome to the Number Guessing Game!")
random_pick = random.randint(1,100)
print(random_pick)
turns = game_level()
guess = 0
while guess != random_pick:
print(f"you have {turns} turns remaining to guess the number.")
guess = int(input("Make a guess: "))
turns = guess_number(random_pick, guess, turns)
if turns == 0:
print("You lose.")
return
elif guess != random_pick:
print("Guess again.")
game_start()
내가 직접 작성한 코드도 있고, 도저히 하다가 안돼서 안젤라쌤의 정답코드를 참고한 부분도 있다.
중요한 포인트는 게임을 만들때 꼭 필요한 기능들을 함수로 미리 정의 및 필요한 값을 Return해두고,
실제 게임이 시작되는 "def game_start()" 함수에서 시의적절하게 호출하여 활용할 수 있어야 한다는 점이다.
현재로서 제일 어려운 부분은, 다음 강의에서 솔루션이 제공되니까 그 솔루션 안에서만 고민하려고 한다는 건데
막상 결과를 놓고 보면 굉장히 단순하게 풀수 있는 부분인데도 그 전까지는 머리를 싸매고 고민할 수 밖에 없다는 것 ㅠㅠ
꼭 필요한 과정이므로 너무 결과에 얽매이지 않고 충분히 고민하고 내 주관에 맞게 코드를 짜보는 것이 중요할 것 같다.