简体   繁体   English

全局变量与参数是 Python 控制台游戏

[英]Global Variables vs Parameters is Python Console Game

I just looked over some code I wrote a while back and noticed something weird with global variables.我刚刚查看了一段时间前写的一些代码,发现全局变量有些奇怪。 For example in update_board I pass board as a parameter, and update it inside the function, but don't return the updated board, yet it still gets updated.例如,在update_board中,我将board作为参数传递,并在 function 中对其进行更新,但不返回更新后的 board,但它仍然会更新。 So it appears I'm basically using a global value for board .所以看来我基本上是在使用一个全局值board

To be consistent, should I avoid passing the board parameter and use global board instead?为了保持一致,我应该避免传递board参数并改用global board吗? I know globals are discouraged, but it's maybe at least better to be explicit about them.我知道不鼓励全局变量,但至少明确说明它们可能会更好。 Or would it be better to replace instances of update_board(board, row, col) with board = update_board(board, row, col) and return board from update_board instead?或者将update_board(board, row, col)的实例替换为board = update_board(board, row, col)并从update_board返回board会更好吗?

Or have I possibly hit upon a valid approach quite by accident as the code stands?还是我可能偶然发现了一个有效的方法,就像代码一样?

"""
Chomp - a strategy game
"""

import random
import time

NUM_ROWS = 5
NUM_COLS = 6

FILLED_SPOT = "#"
POISON_SPOT = "P"
EMPTY_SPOT = " "


def print_title():
    print(r"""
 ______     __  __     ______     __    __     ______  
/\  ___\   /\ \_\ \   /\  __ \   /\ "-./  \   /\  == \ 
\ \ \____  \ \  __ \  \ \ \/\ \  \ \ \-./\ \  \ \  _-/ 
 \ \_____\  \ \_\ \_\  \ \_____\  \ \_\ \ \_\  \ \_\   
  \/_____/   \/_/\/_/   \/_____/   \/_/  \/_/   \/_/   
""")


def print_instructions():
    print("Welcome to Chomp. Choose a square. All squares to the right")
    print("and downwards will be eaten. The computer will do the same.")
    print("The one to eat the poison square loses. Good luck!")
    print()


def who_goes_first():
    return random.choice(("computer", "human"))


def play_again():
    print("Would you like to play again (yes or no)?")
    return input().lower().startswith("y")


def print_matrix(matrix):
    for row in matrix:
        for elem in row:
            print(elem, end=EMPTY_SPOT)
        print()


def validate_user_input(player_choice, board):
    try:
        row, col = player_choice.split()
    except ValueError:
        print("Bad input: The input should be exactly two numbers separated by a space.")
        return False
    try:
        row = int(row)
        col = int(col)
    except ValueError:
        print("Input must be two numbers, however non-digit characters were received.")
        return False

    if row < 0 or row > NUM_ROWS - 1:
        print(f"The first number must be between 0 and {NUM_ROWS - 1} but {row} was passed.")
        return False
    if col < 0 or col > NUM_COLS - 1:
        print(f"The second number must be between 0 and {NUM_COLS - 1} but {col} was passed.")
        return False
    if board[row][col] == EMPTY_SPOT:
        print("That square has already been eaten!")
        return False
    return True


def update_board(board, row, col):
    for i in range(row, len(board)):
        for j in range(col, len(board[i])):
            board[i][j] = EMPTY_SPOT


def get_human_move(board):
    valid_input = False
    while not valid_input:
        player_choice = input("Enter the row and column number (counting from 0) of your choice,\
        \nseparated by a space: ")
        valid_input = validate_user_input(player_choice, board)
    row, col = player_choice.split()
    return int(row), int(col)


def get_computer_move(board):
    valid_move = False
    while not valid_move:
        row = random.randint(0, NUM_ROWS - 1)
        col = random.randint(0, NUM_COLS - 1)
        if board[row][col] == EMPTY_SPOT:
            continue
        else:
            valid_move = True
    return row, col


def main():
    game_over = False
    while not game_over:
        board = []
        for i in range(NUM_ROWS):
            row = []
            for j in range(NUM_COLS):
                row.append(FILLED_SPOT)
            board.append(row)

        board[0][0] = POISON_SPOT
        game_is_playing = True
        turn = who_goes_first()

        print_title()
        print_instructions()
        print_matrix(board)
        print()

        while game_is_playing:
            if turn == "human":
                # Human turn
                print("Human turn.")
                row, col = get_human_move(board)
                if board[row][col] == POISON_SPOT:
                    print()
                    print("Too bad, the computer wins!")
                    game_is_playing = False
                else:
                    update_board(board, row, col)
                    print()
                    print_matrix(board)
                    print()
                    turn = "computer"
                    time.sleep(1)
            else:
                # Computer turn
                row, col = get_computer_move(board)
                print(f"Computer turn. The computer chooses ({row}, {col})")
                print()
                if board[row][col] == POISON_SPOT:
                    print()
                    print("Yay, you win!")
                    game_is_playing = False
                else:
                    update_board(board, row, col)
                    print_matrix(board)
                    print()
                    turn = "human"

        if play_again():
            main()
        else:
            print("Goodbye!")
            game_over = True

main()

You dont have a global variable.您没有全局变量。 Instead you have a locally scoped variable which you pass to your function.相反,您有一个本地范围的变量,您可以将其传递给 function。

When you create a variable you are just creating an alias to point to the memory location of an object.当您创建一个变量时,您只是创建一个别名以指向 object 的 memory 位置。 In the below code we are creating a list which is an object and has a string object inside it.在下面的代码中,我们创建了一个列表,它是一个 object,其中有一个字符串 object。 We then create the name mylist and point it to the memory location of the list object.然后我们创建名称 mylist 并将其指向列表 object 的 memory 位置。

mylist = [1]

When you then pass mylist to a function what happens is the function gets a copy of the memory location that mylist points to and the function sets its local variable to point to that memory location. When you then pass mylist to a function what happens is the function gets a copy of the memory location that mylist points to and the function sets its local variable to point to that memory location.

So when you do an action which mutates the object in that memory location then that update will be seen also by the variable name outside the function since both point to the same memory location. So when you do an action which mutates the object in that memory location then that update will be seen also by the variable name outside the function since both point to the same memory location.

If however you were to reassign soemthing to that variable in the function like create a new list then that wouldnt reflect in the variable outside the function.但是,如果您要为 function 中的该变量重新分配某些内容,例如创建一个新列表,那么这不会反映在 function 之外的变量中。 Since what would actually be happening is a new object would be created and the local scope variable would be pointed to it.由于实际发生的是一个新的 object 将被创建,并且本地 scope 变量将指向它。 that wouldnt change the memory address of the variable outside of the function which would still point to the original location.这不会改变 function 之外的变量的 memory 地址,该地址仍将指向原始位置。

def first():
    mylist = [1]
    print("mylist:", mylist)
    print("mylist id:", id(mylist))
    second(mylist)
    third(mylist)
    print("mylist:", mylist)
    print("mylist id:", id(mylist))

def second(second_list):
    #here the local function variable second_list points to the same memory location as mylist
    print("second id:", id(second_list))
    #Here we change the values in this memory location. So second list is still pointing to and change the data that my list points to
    #this is why mylist can see the change even though its not a global variable
    second_list.append(2)
    print("Second_list:", second_list)
    print("second id:", id(second_list))

def third(third_list):
    #here the local function variable third_list points to the same mermoy location as mylist
    print("third list:", third_list)
    print("third id:", id(third_list))
    #here we create a new object which will have a new memory lcaotion then we point the local variable third_list at it.
    #now third_list points to new memory location and not the same memory location as mylist.
    third_list=[3]
    print("third list:", third_list)
    print("third id:", id(third_list))

first()

below is the output where you acn see the memory id of each of the objects you will see how they point to the same object and then in the third function its repointed to a new object in memory. below is the output where you acn see the memory id of each of the objects you will see how they point to the same object and then in the third function its repointed to a new object in memory.

mylist: [1]
mylist id: 2636457271880
second id: 2636457271880
Second_list: [1, 2]
second id: 2636457271880
third list: [1, 2]
third id: 2636457271880
third list: [3]
third id: 2636457271944
mylist: [1, 2]
mylist id: 2636457271880

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM