TLDR:return 值必须分配到调用站点的某个东西。
test = testing()
Python 中的函数有自己的作用域。它在进入(调用)函数时创建,并在离开时销毁。在作用域内分配给 name 会使该名称成为该作用域的本地名称 - 导致它与作用域一起被销毁。
# start outer scope
test = 0 # create name outer:test
def testing():
# start inner scope
test = 1 # create name outer.testing:test
return test
# end inner scope
# destroy name outer.testing:test
testing() # new temporary inner scope outer.testing
print(test) # use name outer:test
# end outer scope
值得注意的是,内部范围内的名称可能来自外部范围的“shadow”名称。虽然名称test 存在于testing 和外部范围中,但它指的不是同一个东西。这有两个重要的含义:
- 分配给 inner
test 不会影响 outer test。
- 在
testing 的末尾,内部 test 被销毁,只剩下外部 test。
这就是为什么调用testing() 没有达到预期效果的原因:它从不修改传递给print 的外部test。
The return statement defines the value returned by calling a function. 它确实不返回名称,只返回指向的值。
def testing():
test = 1 # test refers to the value 1
return test # return test => value 1
函数返回的值与任何其他值一样 - 无论是来自文字、查找还是其他。最重要的是,除非您将其分配给名称或直接使用,否则该值不会持久存在。
testing() # call test, discard its value
test = testing() # call test, store its value as `test`
print(testing()) # call test, use its value in `print`
因此,为了从函数中返回某些内容以供以后使用,您必须将结果存储到名称中。然后,您可以在以后的语句中使用该名称。您的案例的一个最小示例如下所示:
# we already can define testing here
# it is overwritten later on, then
def testing():
# all names we use inside of testing are gone at the end
# if we just want a value, we can skip temporary names
return 1
# store the return value of testing() for later use
test = testing()
print(test)
附录:函数可以修改其包含范围。但是,必须将名称显式声明为来自外部作用域。
nonlocal 和 global 关键字允许从外部范围修改名称。 nonlocal 是最接近匹配函数范围内的名称。 global 是模块范围内的名称,与中间的任何函数无关。
test = 0
def increment():
global test # declare test as belonging to a specific scope
test += 1
# no need to return something
# we already modified the outer `test`
print(test) # 0
increment()
print(test) # 1
请注意,修改外部名称通常是反模式的标志,globals 比nonlocals 更是如此。除了小脚本之外,很难追踪访问和修改globals 的内容。通常,使用类或生成器来保存状态更合适。
一个函数总是可以从它的包含范围读取名字,只要它从不写入相同的名字。这样的closures 非常容易创建,而且无需修改,更容易追踪。请注意,在函数中修改名称 anywhere 会使其成为本地名称,除非声明为 global 或 nonlocal:
test = 0
def increment():
global test
test += 1
def show_test():
# we never modify `test`, so it is fetched from the outside
print(test)
def show_and_increment1(): # this function is broken!
print(test) # `test` is *not* the outer one, since we modify it in the function
test += 1 # modifying `test` makes it local for the *entire* function
def show_and_increment2(): # this function works!
global test # force `test` to be global
print(test)
test += 1
show_test() # 0
increment()
show_test() # 1
show_and_increment2() # 1
show_and_increment2() # 2
show_and_increment2() # 3
show_test() # 4
show_and_increment1() # UnboundLocalError: local variable 'test' referenced before assignment