유효 범위

JOOYEUN SEO·2024년 8월 17일

100 Days of Python

목록 보기
12/76
post-thumbnail

❖ 유효 범위(scope)

울타리 의 사과나무에는 울타리 안의 사람들만 접근 가능
울타리 의 사과나무에는 누구나 접근 가능

enemies = 1

def increase_enemies():
  enemies = 2
  print(f"enemies inside function: {enemies}")

increase_enemies()
print(f"enemies outside function: {enemies}")
enemies inside function: 2
enemies outside function: 1

두 변수의 이름은 같지만 실제로는 서로 다른 변수라는 것을 확인할 수 있다

◇ 지역 vs 전역 범위

지역(local) 범위

def drink_potion():
  potion_strength = 2
  print(potion_strength)
  
drink_potion()
print(potion_strength)
NameError: name 'potion_strength' is not defined

drink_potion 함수 안에서 정의된 지역 변수 potion_strength는 해당 함수 안에서만 유효

전역(global) 범위

player_health = 10

def drink_potion():
  potion_strength = 2
  print(player_health)
  
drink_potion()
10

전역 변수 player_health는 함수 외부는 물론 내부에서도 이용 가능

◇ 네임스페이스

  • 이름을 지정한 모든 대상은 네임스페이스(이름공간)을 가짐
  • 네임스페이스는 특정 범위 안에서 유효
  • 함수, 변수 등 원하는 대상에 이름을 지정할 때마다 어디서 해당 대상을 만들었는지 알아야 함
player_health = 10

def game():
  def drink_potion():
    potion_strength = 2
    print(player_health)

  drink_potion()

print(player_health)
10

drink_potion 함수가 game 함수 안으로 들어갔기 때문에, 들여쓰기를 해야 호출 가능하게 됨

❖ 블록 유효 범위

다른 프로그래밍 언어와 달리 파이썬에서는 들여쓰기한 코드의 블록을 울타리로 치지 않음

game_level = 3
enemies = ["Skeleton", "Zombie", "Alien"]

if game_level < 5:
  new_enemy = enemies[0]

print(new_enemy)
Skeleton

if, while, for과 같이 콜론들여쓰기가 있는 모든 코드 블록은 별도의 지역 범위를 만들지 않음

game_level = 3

def create_enemy():
  enemies = ["Skeleton", "Zombie", "Alien"]
  if game_level < 5:
    new_enemy = enemies[0]

print(new_enemy)
NameError: name 'new_enemy' is not defined

함수 내부에는 지역 범위가 있기 때문에 new_enemy를 함수 밖에서 출력 불가능
(create_enemy 함수 안에서 작성해야 출력할 수 있다)

❖ 전역 변수 수정

방법 1 : 전역 변수를 함수 내부에서 직접 변경
(버그와 오류가 잘 발생하고 실수할 가능성이 크기 때문에 전역 변수를 직접 수정하는 것은 비추천)

enemies = 1			# 전역 변수

def increase_enemies():
  global enemies	# 전역 변수를 그대로 가져오기
  enemies +=1
  print(f"enemies inside function: {enemies}")

increase_enemies()
print(f"enemies outside function: {enemies}")
enemies inside function: 2
enemies outside function: 2

방법 2 : return 키워드로 수정하려는 값을 반환하고, 반환값을 전역 변수에 저장
(해당 함수를 코드 어디에서 정의하든 상관 없고, 함수가 전역 변수를 어떻게 변화시키는지만 알면 됨)

enemies = 1  					# 전역 변수

def increase_enemies():
  print(f"enemies inside function: {enemies}")
  return enemies + 1

enemies = increase_enemies()  	# 리턴값을 다시 전역 변수에 저장
print(f"enemies outside function: {enemies}")
enemies inside function: 1
enemies outside function: 2

❖ 상수와 전역적 유효 범위

상수(constants)

  • 사용자가 정의하는 변수이며, 한 번 정의하면 다시는 변경하지 않는 점이 일반 변수와 다른 점
    예) PI = 3.14159...
  • 전역 상수 선언 후, 필요할 때마다 함수 안에서도 사용 가능

💡 변수와 상수를 구분하는 방법
파이썬에서 상수의 이름을 짓는 규칙은 모든 문자를 대문자로 작성하는 것

🗂️ Day12 프로젝트: 숫자맞추기 게임

숫자를 입력하면 정답보다 높은지 낮은지 알려주는 힌트를 통해 주어진 기회 안에 숫자를 맞추는 게임

🔍 유의 사항

  • 입력하는 숫자는 1 - 100 사이로 가정
  • 레벨에 따라 난이도가 달라짐
    • easy : 10번의 기회
    • hard : 5번의 기회
  • 플레이어에게 보여줘야 할 것
    • 남은 기회 횟수
    • 기회를 다 써버리면 그에 맞는 피드백
    • 맞는 숫자를 입력할 경우 정답 숫자
  • 게임 이름을 아스키 코드 아트로 만들기
    • ASCII Art Generator
    • 로고가 제대로 나오게 하려면 독스트링으로 만들어야 함

📄 art.py

logo = """
   ___                  _____ _          _  _            _             
  / __|_  _ ___ ______ |_   _| |_  ___  | \| |_  _ _ __ | |__  ___ _ _ 
 | (_ | || / -_|_-<_-<   | | | ' \/ -_) | .` | || | '  \| '_ \/ -_) '_|
  \___|\_,_\___/__/__/   |_| |_||_\___| |_|\_|\_,_|_|_|_|_.__/\___|_|  
               
                                                                               
"""

⌨️ 작성한 코드

from art import logo
from random import randint
from replit import clear

# 난이도를 설정하는 함수
def select_difficulty():
    while True:
        difficulty = input("Choose a difficulty. Type 'easy' or 'hard' : ")
        if difficulty == "easy":
            return 10
        elif difficulty == "hard":
            return 5
        else:
            print("Type only 'easy' or 'hard'.")

# 숫자를 맞추는 함수
def number_guessing(real_number, chances):
    for chance in range(chances):
        print(f"\nYou have {chances - chance} attempts remaining to guess the number.")
        guess_number = int(input("Make a guess : "))
        if guess_number == real_number:
            return f"You got it! The answer was {real_number}"
        elif guess_number < real_number:
            print("Too low.")
        elif guess_number > real_number:
            print("too high.")

        if chance != chances - 1:
            print("Guess again.")
        else:
            return "You've run out of guesses, you lose."

# 게임을 진행하는 함수
def game():
    print(logo)
    print("Welcome to the Number Guessing Game!")
    print("I'm thinking of a number between 1 and 100.")
    answer = randint(1, 100)

    should_continue = True
    while should_continue:
        # 난이도에 따라 시도 횟수 결정
        attempts = select_difficulty()
        # 게임 결과
        result = number_guessing(answer, attempts)
        print(result)
        should_continue = False
       
# 게임을 할지 말지 물어보기
while input("\nDo you want to play? Type 'y' or 'n' : ").lower() == 'y':
    clear()
    game()
print("Goodbye.")
[ 출력 결과 ]

Do you want to play? Type 'y' or 'n' : ❚y

   ___                  _____ _          _  _            _             
  / __|_  _ ___ ______ |_   _| |_  ___  | \| |_  _ _ __ | |__  ___ _ _ 
 | (_ | || / -_|_-<_-<   | | | ' \/ -_) | .` | || | '  \| '_ \/ -_) '_|
  \___|\_,_\___/__/__/   |_| |_||_\___| |_|\_|\_,_|_|_|_|_.__/\___|_|  
               
                            

Welcome to the Number Guessing Game!
I'm thinking of a number between 1 and 100.
Choose a difficulty. Type 'easy' or 'hard' : ❚hard

You have 5 attempts remaining to guess the number.
Make a guess : ❚50
Too low.
Guess again.

You have 4 attempts remaining to guess the number.
Make a guess : ❚60
Too low.
Guess again.

You have 3 attempts remaining to guess the number.
Make a guess : ❚70
Too low.
Guess again.

You have 2 attempts remaining to guess the number.
Make a guess : ❚80
Too low.
Guess again.

You have 1 attempts remaining to guess the number.
Make a guess : ❚90
too high.
You've run out of guesses, you lose.

Do you want to play? Type 'y' or 'n' : ❚y


   ___                  _____ _          _  _            _             
  / __|_  _ ___ ______ |_   _| |_  ___  | \| |_  _ _ __ | |__  ___ _ _ 
 | (_ | || / -_|_-<_-<   | | | ' \/ -_) | .` | || | '  \| '_ \/ -_) '_|
  \___|\_,_\___/__/__/   |_| |_||_\___| |_|\_|\_,_|_|_|_|_.__/\___|_|  
               
                                           

Welcome to the Number Guessing Game!
I'm thinking of a number between 1 and 100.
Choose a difficulty. Type 'easy' or 'hard' : ❚easy

You have 10 attempts remaining to guess the number.
Make a guess : ❚50
Too low.
Guess again.

You have 9 attempts remaining to guess the number.
Make a guess : ❚60
Too low.
Guess again.

You have 8 attempts remaining to guess the number.
Make a guess : ❚70
too high.
Guess again.

You have 7 attempts remaining to guess the number.
Make a guess : ❚65
Too low.
Guess again.

You have 6 attempts remaining to guess the number.
Make a guess : ❚66
You got it! The answer was 66

Do you want to play? Type 'y' or 'n' : ❚n
Goodbye.

🖍️ 답안

from random import randint
from art import logo

EASY_LEVEL_TURNS = 10
HARD_LEVEL_TURNS = 5

# 3. Function to check user's guess against actual answer.
def check_answer(guess, answer, turns):
  """checks answer against guess. Returns the number of turns remaining."""
  if guess > answer:
    print("Too high.")
    return turns - 1
  elif guess < answer:
    print("Too low.")
    return turns - 1
  else:
    print(f"You got it! The answer was {answer}.")

# 4. Make function to set difficulty.
def set_difficulty():
  level = input("Choose a difficulty. Type 'easy' or 'hard': ")
  if level == "easy":
    return EASY_LEVEL_TURNS
  else:
    return HARD_LEVEL_TURNS

# 7. 게임 기능을 함수 안에 넣기
def game():
  print(logo)
  # 1. Choosing a random number between 1 and 100.
  print("Welcome to the Number Guessing Game!")
  print("I'm thinking of a number between 1 and 100.")
  answer = randint(1, 100)
  print(f"Pssst, the correct answer is {answer}") 
  
  # 5. 난이도에 따른 시도 횟수를 turns에 저장
  turns = set_difficulty()							# 지역 변수 turns
  # 6. Repeat the guessing functionality if they get it wrong.
  guess = 0		# while 반복문을 위해 guess를 먼저 선언
  while guess != answer:
    print(f"You have {turns} attempts remaining to guess the number.")

    # 2. Let the user guess a number.
    guess = int(input("Make a guess: "))

    # 9. Track the number of turns and reduce by 1 if they get it wrong.
    turns = check_answer(guess, answer, turns)		# 지역 변수 turns 업데이트
    if turns == 0:
      print("You've run out of guesses, you lose.")
      return	# 함수 종료
    elif guess != answer:
      print("Guess again.")

# 8. game 함수 호출
game()
  • 각 난이도에 해당하는 시도 횟수를 전역 변수로 설정
    • 함수 선언들보다 상단에 있기 때문에 어디서든 사용 가능
    • 값을 수정해야 할 경우 맨 위로 올라가서 전역 변수를 수정해주면 아래 코드에 모두 반영되므로 편리
  • 지역 변수 turns를 업데이트 하는 방법에 주목
  • game 함수 종료 조건
    • while guess != answer 이므로 기회 소진 전에 사용자가 정답을 맞추면 함수 종료
    • 정답을 맞추지 못하고 기회를 모두 소진하면 if turns == 0에 의해서 함수 종료
      (이미 함수 안이므로 return 키워드로 원할 때 종료할 수 있음)




▷ Angela Yu, [Python 부트캠프 : 100개의 프로젝트로 Python 개발 완전 정복], Udemy, https://www.udemy.com/course/best-100-days-python/?couponCode=ST3MT72524

0개의 댓글