【问题标题】:Python: local, global variablesPython:局部变量、全局变量
【发布时间】:2019-07-24 18:48:13
【问题描述】:

我正在用 Python (Mastermind) 制作新程序。我对变量的引用有疑问:

def user_turn():
    try_counter = 1
    user_code = []
    guessed_code = random_code()
    print("Twoja kolej na zgadywanie!")
    while try_counter <= max_tries and user_code != guessed_code:
        good_number, good_number_and_position = 0, 0
        appearance_types_guessing_code = [0 for i in range(types)]
        appearance_types_user_code = [0 for i in range(types)]
        user_code = input("Próba nr {}: ".format(try_counter))
        user_code = list(map(int, str(user_code)))
        count_xos()
        print_xos()
        try_counter += 1

    print_result_user_turn()

函数体print_xos():

def print_xos():
    for i in range(good_number_and_position):
        print("x", end='')
    for i in range(good_number):
        print("o", end='')
    print("")

我的问题是函数print_xos() 中的变量good_numbergood_number_and_position 是未知的,尽管事实上我在函数user_turn() 的主体的while 循环中声明了这个变量。我怎么解决这个问题?我不想将引用作为函数的参数发送。在我看来,它并不优雅。是否有可能以其他方式做到这一点?

编辑:

好的,那我稍微改了一下代码:

def user_turn():
    try_counter = 1
    user_code = []
    guessed_code = random_code()
    appearance_types_guessed_code = [0] * types
    how_many_appearance(guessed_code, appearance_types_guessed_code)
    print("Twoja kolej na zgadywanie!")
    while try_counter <= max_tries and user_code != guessed_code:
        good_number, good_number_and_position = 0, 0
        appearance_types_user_code = [0] * types
        user_code = input("Próba nr {}: ".format(try_counter))
        user_code = list(map(int, str(user_code)))
        how_many_appearance(user_code, appearance_types_user_code)
        print(appearance_types_guessed_code, appearance_types_user_code)
        count_xos(guessed_code, appearance_types_guessed_code, user_code, appearance_types_user_code, good_number, good_number_and_position)
        print(good_number_and_position, good_number)
        print_xos(good_number_and_position, good_number)
        try_counter += 1

    print_result_user_turn(guessed_code, user_code)

还有函数体count_xos:

def count_xos(guessed_code, appearance_types_guessed_code, user_code, appearance_types_user_code, good_number, good_number_and_position):
    for i in range(len(appearance_types_guessed_code)):
        good_number += np.min([appearance_types_guessed_code[i], appearance_types_user_code[i]])

    for i in range(code_size):
        if guessed_code[i] == user_code[i]:
            good_number_and_position += 1
            good_number -= 1
    print(good_number_and_position, good_number)

我得到了这个输出:

RUNDA 1
Twoja kolej na zgadywanie!
Próba nr 1: 0011
[0, 2, 0, 1, 0, 0, 0, 1, 0, 0] [2, 2, 0, 0, 0, 0, 0, 0, 0, 0]
1 1
0 0

您可以确定函数 count_xos 计数 good_number,good_number_and_position 计数正确。应该是1 1,但是不知道为什么运行count_xos方法后,变量good_number_and_position、good_number没有变化?

【问题讨论】:

  • 恰恰相反,优雅的解决方案是让您的函数接收这些值作为参数,而不是依赖那些在函数外部设置为全局变量的值。
  • 作为旁注,[0 for i in range(types)] 最好写成[0] * types
  • 阅读Scoping rules - 最好保持范围尽可能小,并为他们需要的功能提供数据。很少需要做某事global

标签: python python-3.x variables global local


【解决方案1】:

您的最后一次尝试没有返回数字,因此提供的数字不会执行到您的调用函数中。

您的代码相当于:

def one(aa,bb):
    aa *= 2
    bb *= 3
    print("In function", aa, bb)
    return aa, bb

a = 5
b = 11
one(a,b)      # does not reassign returned values - similar to not return anything like yours
print(a,b)

输出:

In function 10 33
5 11   

您需要返回并重新分配值:

a,b = one(a,b) # reassign returns
print(a,b)

输出:

In function 10 33
10 33

看看Scoping rules - 最好保持范围尽可能小,并为他们需要的功能提供数据。

如果您修改函数内部的内容并返回其新值并重新分配它们 - 如果您传递一个列表,则不会这样做,它们是可变引用和“自动更新”,因为您通过数据上的 ref 进行操作:

# same function used as above

a = 5
b = [11]
one(a,b)
print(a,b)

输出:

In function 10 [11, 11, 11]
5 [11, 11, 11]

如果您查看变量的 id(),您会发现更改 aa 会将名称 aa 重新指向其他 id - 但外部的 a 仍指向原始名称.更改列表不会更改参考 ID - 它会更改 ref“指向”的数据:

def one_ids(aa,bb):
    print(id(aa),id(bb))
    aa *= 3   # modify an integer
    bb *= 3   # modify the list
    print(id(aa),id(bb))

a = 5
b = [11]
print(id(a),id(b))
one_ids(a,b)
print(id(a),id(b))

输出:

139647789732288   139647790644808   # id of a,b
139647789732288   139647790644808   # id of aa,bb before changing
139647789732**6**08   139647790644808   # id of aa,bb after changing
139647789732288   139647790644808   # id of a,b 

您可以在Function changes list values and not variable values in Python 中进一步阅读 - 看看这些解释是否更适合您。

【讨论】: