函数返回值和作用域

函数的返回值

  • python函数使用return语句返回“返回值”
  • 所有函数都有返回值,如果没有return语句,隐式调用return none
  • return语句并不一定式函数的语句块最后一条语句
  • 一个函数可以存在多个return语句,但是只有一条被执行,如果没有一条return被执行,则调用return none
  • 如果有必要,可以显示调用return none 可以简写为return
  • 如果函数执行了return语句,函数就会返回,当前被执行的return语句之后的其他语句就不会被执行

 

示例1:

def add(x):
    print(x)
    return x+1
    print(x)

print(add(5))

如果函数执行了return语句,函数就会返回,当前被执行的return语句之后的其他语句就不会被执行,输出为:

5
6

 

示例2:

def guess(x):
    if x > 5:
        return '>5'
    else:
        return '<=5'

print(guess(6))

一个函数可以存在多个return语句,但是只有一条被执行,输出如下:

>5

 

返回多个值

  • 函数不能同时返回多个值
  • return[1,2,3]是返回一个列表,是一个列表对象
  • return 1,2,3看似返回多个值,被python封装成一个元祖

示例3:

def showlist():
    return [1,2,3]

def showlist2():
    return 1,2,3

print(showlist())
x,y,z = showlist()
print(x,y,z)
print(showlist2())
a,b,c = showlist2()
print(a,b,c)

 

可以使用解构提取值,输出为:

[1, 2, 3]
1 2 3
(1, 2, 3)
1 2 3

 

函数嵌套

  • 在一个函数中定义了另一个函数
  • 函数有可见范围,这就是作用域概念
  • 内部函数不能再外部直接用,会抛异常

示例:

def outer():
    def inner():
        print('inner')
    print('outer')
    inner()

outer()

 

作用域

  • 一个标识符的可见返回,这就是标识符的作用域,一般常说变量的作用域
  • 全局作用域,在整个程序环境中都可见
  • 局部作用域,在函数,类等内部可见,局部变量使用范围不能超过其所在的局部作用域

示例:

x = 1

def foo():
    x += 1
    print(x)

foo()

输出报错,因为在函数内x += 1时,变量x赋值即从新定义,但x未在函数内定义,报错

Traceback (most recent call last):
  File "E:/PycharmProjects/untitled/test/a.py", line 13, in <module>
    foo()
  File "E:/PycharmProjects/untitled/test/a.py", line 10, in foo
    x += 1
UnboundLocalError: local variable 'x' referenced before assignment

 

示例:

def outer():
    x = 50
    def inner():
        x = 30
        print('inner{}'.format(x))
    print('outer{}'.format(x))
    inner()

outer()

输出为:

outer50
inner30

外层变量作用域在内层可见,如果内层定义外层同名变量,相当于从新定义了一个,但是内层的不会覆盖外层

 

全局变量global

  • 使用global关键字的变量,将foo内部的x 声明为使用外部的全局作用域中定义x
  • 全局作用域中必须有x的定义
  • 外部作用域变量会内部作用域可见,但也不要在内部的局部作用域使用,因为函数的目的就是为了封装,尽量与外界隔离
  • 如果函数需要使用外部全局变量,请使用函数的形参传参
  • 不要使用global,学习他是为了深入理解变量作用域

示例:

x = 5

def foo():
    global x
    x = 10
    x += 1
    print(x)

foo()

输出为

11

使用global关键字的变量,将foo内的x声明为使用外部的x

但x=10赋值即定义,在内部作用域为一个外部作用域的变量x赋值,不是在内部作用域定义个新变量x,x的作用域为全局

 

闭包

自由变量:未在本地作用域中定义的变量,例如定义在内层函数外的外层函数的作用域中变量

闭包:是一个概念,出现在嵌套函数中,指的是内层函数引用到了外层函数的自由变量,就形成了闭包,很多语言都有这个概念

 

示例:

def counter():
    c = [0]
    def inc():
        c[0] += 1
        return c[0]
    return inc

foo = counter()
print(foo(),foo())
c = 100
print(foo())

输出为:

1 2
3

c已经在counter函数中定义过,inc中使用方式为c元素修改至,不是重新定义,不会报错

inc引用的自由变量c为函数counter变两次,形成闭包

 

nonlocal关键字

使用nonlocal关键字,将变量标记为不在本地作用域定义,而是上级的某一级局部作用域中定义,但不是全局作用域中定义

 

示例:

def counter():
    count = 0
    def inc():
        nonlocal count
        count += 1
        return count
    return inc

foo = counter()
print(foo())
print(foo())

输出:

1
2

count是外层函数的局部变量,被内部函数引用

内部函数使用nonlocal关键字声明count变量在上级作用域而非本地作用域中定义

 

变量名解析原则LEGB

local,本地作用域,局部作用域的local明明空间,函数调用时创建,调用结束消亡

enclosing,python2.2时引入了嵌套函数,实现了闭包,这就是嵌套函数的外部函数的命名空间

global,全局作用域,即一个模块的命名空间,模块被import时创建,解释器退出时消亡

build-in,内置模块的命名空间,声明周期从python解释器启动时创建到解释器退户时消亡,例如print(open),print和open都是内置的函数

 

函数的销毁

全局函数销毁

  • 重新定义同名函数
  • del语句删除函数对象
  • 程序结束时

 

示例:

def foo(xyz=[],u='abc',z=123):
    xyz.append(1)
    return xyz
print(foo(),id(foo),foo.__defaults__)

def foo(xyz=[],u='abc',z=123):
    xyz.append(1)
    return xyz
print(foo(),id(foo),foo.__defaults__)

del foo

print(foo(),id(foo),foo.__defaults__)

输出为:

Traceback (most recent call last):
[1] 1730166338152 ([1], 'abc', 123)
  File "E:/PycharmProjects/untitled/test/a.py", line 19, in <module>
    print(foo(),id(foo),foo.__defaults__)
[1] 1730166338968 ([1], 'abc', 123)
NameError: name 'foo' is not defined

两次定义函数foo的地址不同,del语句删除函数后报错

 

局部函数销毁

  • 重新再上级作用域定义同名函数
  • del语句删除函数名称,函数的引用计数减1
  • 上级作用域销毁时

 

示例:

def foo(xyz=[],u='abc',z=123):
    xyz.append(1)
    def inner(a=10):
        pass
    print(inner)
    def inner(a=100):
        print(xyz)
    print(inner)
    return inner

bar = foo()
print(id(foo),id(bar),foo.__defaults__,bar.__defaults__)
del bar
print(id(foo),id(bar),foo.__defaults__,bar.__defaults__)

输出为:

Traceback (most recent call last):
  File "E:/PycharmProjects/untitled/test/a.py", line 20, in <module>
    print(id(foo),id(bar),foo.__defaults__,bar.__defaults__)
NameError: name 'bar' is not defined
<function foo.<locals>.inner at 0x0000020DED0F3268>
<function foo.<locals>.inner at 0x0000020DED0F3598>
2258835026400 2258835027352 ([1], 'abc', 123) (100,)

 

posted @ 2018-08-29 14:51  rivendare  阅读(1008)  评论(0编辑  收藏  举报