700字范文,内容丰富有趣,生活中的好帮手!
700字范文 > if python 判断函数返回值_Python函数的返回值和作用域

if python 判断函数返回值_Python函数的返回值和作用域

时间:2018-10-18 21:32:56

相关推荐

if python 判断函数返回值_Python函数的返回值和作用域

函数的返回值和作用域

1、返回值

def guess(x): if x > 3: return "> 3" else: return "<= 3"print(guess(10))

1> Python 函数使用 return 语句返回 "返回值”

2> 所有函数都有返回值,如果没有 return 语句,隐式调用 return None

3> return 语句并不一定是函数的语句块的最后一条语句

4> 一个函数可以存在多个 return 语句,但是只有一条可以被执行。如果没有一条 return 语句被执行到,隐式调用 return None

5> 如果有必要,可以显示调用return None,可以简写为return

6> 如果函数执行了 return 语句,函数就会返回,当前被执行的 return 语句之后的其它语句就不会被执行了

7> 返回值的作用:结束函数调用、返回 "返回值”

2、能一次返回多个值嘛?

def showvalues(): return 1, 3, 5print(showvalues()) # 返回 (1, 3, 5)

函数不能同时返回多个值

return 1, 3, 5 看似返回多个值,隐式的被 python 封装成了一个元组

x, y, z = showvalues() 使用解构提取返回值更为方便

3、函数作用域**

3.1 作用域

一个标识符的可见范围,这就是标识符的作用域,一般常说变量的作用域。

x = 20def fn(): x = 100 # x 的作用域:当前函数fn()print(x)# x = 20

注意:每一个函数都会开辟一个作用域。

3.2 作用域分类

全局作用域:

在整个程序运行环境中都可见

全局作用域中的变量称为全局变量

局部作用域:

在函数、类等内部可见

局部作用域中的变量称为局部变量,其使用范围不超过其所在局部作用域

# 局部变量def fn1(): x = 1 # 局部作用域,x 为局部变量,使用范围在 fn1 内def fn2(): print(x) # x 能打印吗?不能print(x)# x 能打印吗?不能

# 全局变量x = 5 # 全局变量,也在函数外定义def foo(): print(x) # 可见吗?可以foo()

一般来讲外部作用域变量在函数内部可见,可以使用

反过来,函数内部的局部变量,不能在函数外部看到

4、函数嵌套

在一个函数中定义另一个函数

def outer(): def inner(): print('inner') print('outer') inner()outer()inner() # 不可以

内部函数 inner 不能在外部直接使用,会抛出 NameError 异常,因为它在函数外部不可见。

其实,inner 不过就是一个标识符,就是一个函数outer内部定义的变量而已。

5、嵌套函数的作用域

def outer(): o = 65 # 局部变量、本地 local 变量、临时变量 def inner(): o = 97 print('inner', o) print('outer 1 ', o) inner() print('outer 2 ', o)outer() # 1:outer 1 65 2:inner 97 3:outer 2 65

外层变量在内部作用域可见。

内层作用域中,如果定义了和外层相同的变量,相当于在当前函数作用域中重新定义了一个新的变量,这个内层变量并不能覆盖掉外部作用域中的变量。

6、一个赋值语句的问题

x = 100def fn(): y = x + 200 print(y)fn()

x = 100def fn(): x += 1 # 报错! 赋值即定义,即 x = x + 1 (局部变量 = 局部变量 + 1)! print(x)fn()

x = 100def fn(): print(x) # 报错!该步执行不了! x += 1 # 只要在该作用域内赋值定义('=')局部变量,在该作用域内的所有该变量都为局部变量! print(x)fn()

能否解决呢?可以,使用 global 语句

x = 100def fn(): global x # 声明全局变量 print(x) # 100 x += 1 print(x) # 101fn()print(x)# 101

注意:全局变量一般情况不推荐修改,一旦在作用域中使用 global 声明全局变量,那么相当于在对全局变量赋值、定义。

global 使用原则:

1> 外部作用域变量会在内部作用域可见,但也不要在这个内部的局部作用域中直接使用,因为函数的目的就是为了封装,尽量与外界隔离。

2> 如果函数需要使用外部全局变量,请尽量使用函数的形参定义,并在调用传实参解决。

3> 一句话:不用 global,学习它就是为了深入理解变量作用域。

# 不建议直接传入全局变量!y = []def foo(): # x 就是标识符,就是变量,就是本地变量 y.append(1)foo()foo()print(y)

# 建议使用传参的方式,在函数内使用全局变量y = []def foo(x): # x 就是标识符,就是变量,就是本地变量 x.append(1)foo(y)foo(y)print(y)

7、闭包**

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

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

# python 2 实现闭包def counter(): c = [0] def inc(): c[0] += 1 # 是赋值即定义嘛?不是!是修改值 return c[0] return inc# 返回标识符,即函数对象m = counter()m()# 调用函数 inc(),但是 c 消亡了嘛?没有,内层函数没有消亡,c 不消亡(闭包)m()m()print(m())

# 不推荐使用 global !def counter(): global c c = 0 def inc(): global c c += 1 # 不是闭包! return c return incm = counter()m()m()m()print(m())

# 推荐使用 nonlocal,python 3 实现闭包def counter(): c = 0 def inc(): nonlocal c # 非当前函数的本地变量,当前函数之外的任意层函数的变量,绝非 global c += 1 # 是闭包吗?是! return c return incm = counter()m()m()m()print(m())

nonlocal 语句:将变量标记为不在本地作用域定义,而是在上级的某一级局部作用域中定义,但不能是全局作用域中

8、默认值的作用域

def foo(x=1): x += 1 print(x)foo() # 2foo() # 2def bar(x=[]): # x = [],引用类型 x.append(1) # [1] print(x)bar() # [1]bar() # [1, 1]

为什么上列 bar 函数第二次调用打印的是 [1, 1]?

因为函数也是对象,每个函数定义被执行后,就生成了一个函数对象和函数名这个标识符关联。

python 把函数的默认值放在了函数对象的属性中,这个属性就伴随着这个函数对象的整个生命周期。

# 查看 foo.__defaults__ 属性,它是个元组def bar(x=[]): x.append(1) print(x)print(bar.__defaults__)bar() # [1]print(bar.__defaults__)bar() # [1, 1]print(bar.__defaults__)# 执行结果:([],)[1]([1],)[1, 1]([1, 1],) # 元组不变,记录的是地址,引用类型变化

def foo(x, m=123, n='abc'): m=456 n='def' print(x)print(foo.__defaults__) # (123, 'abc')foo('yang')print(foo.__defaults__) # (123, 'abc')

def foo(x, m=123, *, n='abc', t=[1,2]): m=456 n='def' t.append(12) #t[:].append(12) # t[:],全新复制一个列表,避免引用计数 print(x, m, n, t)print(foo.__defaults__, foo.__kwdefaults__) #(123,) {'n': 'abc', 't': [1, 2]}foo('yang')print(foo.__defaults__, foo.__kwdefaults__) #(123,) {'n': 'abc', 't': [1, 2, 12]}

def x(a=[]): a = a + [5] # 加法的本质:返回新列表、新地址;赋值即定义print(x.__defaults__) # ([],)x()x()print(x.__defaults__) # ([],)def y(a=[]): a += [5] # += 即 extend => a.extend([5])print(y.__defaults__) # ([],)y()y()print(y.__defaults__) # ([5, 5],)# 列表的 + 和 += 的区别:# + 表示两个列表合并并返回一个全新的列表。# += 表示,就地修改前一个列表,在其后追加后一个列表,就是 extend 方法。# 例:l1 = [1, 2]l2 = [3, 4]l3 = l1 + l2print(id(l1), id(l2), id(l3))l3 += l2 # 就地修改print(id(l3))执行结果:2279905055304 2279905055816 22799063342162279906334216

9、变量名解析原则 LEGB**

Local,本地作用域、局部作用域的 local 命名空间,函数调用时创建,调用结束消亡。

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

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

Build-in,内置模块的命名空间,生命周期从 python 解释器启动时创建到解释器退出时消亡。例如 print(open),print 和 open 都是内置的变量。

所以一个名词的查找顺序就是 LEGB

10、函数的销毁

定义一个函数就是生成一个函数对象,函数名指向的就是函数对象。可以使用del语句删除函数,使其引用计数减 1。可以使用同名标识符覆盖原有定义,本质上也是使其引用计数减 1。Python程序结束时,所有对象销毁。函数也是对象,也不例外,是否销毁,还是看引用计数是否减为 0。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。