Python函数与变量作用域

函数与变量作用域

一、函数

1.1 函数定义

def 函数名([参数1][,参数2][,参数3]...):
  [函数语句]#函数语句和return语句不能同时省略
  [return [返回值]]#return后面可以没有返回值

1.2函数调用

在Python中,所有语句都是实时执行的,不存在C/C++的编译过程,def也是一条可执行语句,定义一个函数。所以函数的调用必须在定义之后


>>> def add(a,b):
...   return a+b
...
>>> add
<function add at 0x0000000005DAB730>
>>> add(1,2)
3
>>> x=add
>>> x(1,2)
3
>>> def nullFun(a,b):
...   return
...
>>> nullFun(1,2)
>>> 

1.3 函数参数

调用函数时,参数表中提供的参数成为实际参数,简称实参。在Python中,变量保存的是对象的引用,类似于C/C++中的指针。实参传递给形参就是将对象引用赋值给形参。

函数的多态性

多态是面向对象的一个特点,指同一个行为针对不同对象可能会得到不同的结果。Python中的对象无类型属性,变量可饮用各种不同类型的对象。同一个函数,传递的实际参数类型不同时,可获得不同的结果,体现了多态性。例如:

>>> def add(a,b):
...   return a+b
...
>>> add(1,3)
4
>>> add(1,1.5)
2.5
>>> add('abc', 'def')
'abcdef'
>>> add([1,3],[2,4])
[1, 3, 2, 4]

参数赋值传递

Python允许以形参赋值的方式,指定将实参传递给形参。例如:


>>> def add(a,b):return a+b
...
>>> add(a='ab',b='cd')
'abcd'
>>> add(b='ab',a='cd')
'cdab'

可以看出,采用这种方式时,以形参赋值为准,参数顺序可以忽略。

参数传递与共享引用


>>> def f(x): x=100
...
>>> a=10
>>> f(a)
>>> a
10

可以看出在函数中重新赋值a,并不会影响函数外的a,因为Python中的赋值时建立变量到对象的引用。重新赋值时,意味着形参引用了新的对象,原来的引用已经作废。

小心使用可变参数


>>> def f(a):
...   a[0]='abc'
...
>>> x=[1,2]
>>> f(x)
>>> x
['abc', 2]

当使用可变参数时,如列表、字典等,若在函数中修改形参,因为是共享引用,通过实参也获得修改后的对象。如上。

如果不希望在函数中的修改影响函数外的变量,也可以显示的避免。

例如列表,可以使用列表的拷贝作为实参。如:


>>> def f(a):
...   a[0]='abc'
...
>>> x=[1,2]
>>> f(x[:])
>>> x
[1, 2]

也可以在函数内对列表进行拷贝,实参仍使用变量。例如


>>> def f(a):
...   a=a[:]
...
>>> def f(a):
...   a=a[:]
...   a[0]='abc'
...
>>> x=[1,2]
>>> f(x)
>>> x
[1, 2]

有默认值的参数

如c++

传递任意个数的参数

定义参数时,参数名前使用“*”,表示可以接受任意个参数(包括0个),这些参数保存在一个元组中。

>>> def add(a,*b,c):
...   print(c)
...   s=a
...   for x in  b:
...     s+=x
...   return s
...
>>> add(1,2)
3
>>> add(1,2,3)
6
>>> add(1)
1

如果带“*”参数的后面仍然有参数,则必须通过赋值传递。如上。

函数嵌套定义

内部定义的函数作用域为函数内


>>> def add(a,b):
...   def getsum(x):
...     s=0
...     for n in x:
...       s+=ord(n)
...     return s
...   return getsum(a)+getsum(b)
...
>>> add('12', '34')
202

lambda函数

lambda函数也成为表达式函数,用于定义一个匿名函数,可以将该函数赋值给变量,通过变量调用。lambda函数定义的基本格式如下。

lambda 参数:表达式

如:


>>> add=lambda a,b:a+b
>>> add(1,2)
3
>>> add('ab','cd')
'abcd'

递归函数

如C/C++

函数列表

Python允许将函数作为列表对象,然后列表索引来调用函数。如:

>>> add=lambda a,b:a+b #通过lambda简历
>>> add(1,2)
3
>>> add('ab','cd')
'abcd'
>>>
>>>
>>> d=[lambda a,b:a+b,lambda a,b:a*b]
>>> d[0](1,3)
4
>>> d[1](1,3)
3
>>>
>>>#通过def建立
>>> def add(a,b):
...   return a+b
...
>>> def fac(n):
...   if n==0:
...     return 1
...   else:
...     return n*fac(n-1)
...
>>> d=[add,fac]#建立包含函数列表的列表对象
>>> d[0](1,2)
3
>>> d[1](5)
120
>>> d=(add,fac)#建立包含函数列表的元组对象
>>> d[0](2,3)
5
>>> d[1](5)
120

提示:函数列表的实质就是在元组、列表和字典等序列中简历函数对象的引用,然后通过索引来调用函数。

二、变量作用域

2.1 作用域类型

变量作用域就是变量的可访问范围,也可称为命名空间。在第一次给变量赋值时,Python创建变量,第一次给变量赋值的位置决定了变量的作用域。

作用域由大到小分为:内置作用域>文件作用域>函数嵌套作用域>本地作用域

本地作用域:不包含其他函数定义的函数的内部成为本地作用于。函数内通过赋值创建的变量,函数参数都属于本地作用域

函数嵌套作用域:包含了其他函数定义的函数的内部成为函数嵌套作用域

文件作用域:程序文件(也称模块文件)的内部为文件作用域

内置作用域:最顶层,包含了python各种预定义变量和函数的作用域成为内置作用域。

内置作用域和文件作用域有时都被成为全局作用域(变量称为全局变量),函数嵌套作用域优势也成为本地作用域(变量成为本地变量)。

作用域外的变量与作用域内的变量名称相同时,遵循“本地”优先原则,此时外部的作用域被屏蔽--成为作用隔离原则。与C/C++类似。但与C/C++不同的是,在更小作用域整体里,定义该重复变量之前的范围,程序是检测不到那个大作用域的变量的。


>>> a=10
>>> def show():
...   print('a=',a)
...   a=100
...   print('a=',a)
...
>>> show()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 2, in show
UnboundLocalError: local variable 'a' referenced before assignment

2.2 global语句

使用global语句可以在函数内部声明全局变量。全局变量增大了代码维护调试难度,不建议用。

>>> a=10
>>> def show():
...   global a#有用吗?前面不是定义了个全局的a吗?
...   a+=1
...   print('a=',a)
...
>>> show()
a= 11
>>> show()
a= 12
>>> show()
a= 13

2.3 nonlocal语句

作用域隔离原则同样适用于函数内部的嵌套函数。在嵌套函数内使用与上层函数本地变量同名的变量时,若该变量没有被赋值,则该变量就是上层函数的本地变量。如:


>>> def test():
...   a=10
...   def show():
...     print('in show(),a=',a)
...   show()
...   print('in test(),a=',a)
...
>>> test()
in show(),a= 10
in test(),a= 10

稍微修改

>>> def test():
...   a=10
...   def show():
...     a=100
...     print('in show(),a=',a)
...   show()
...   print('in test(),a=',a)
...
>>> test()
in show(),a= 100
in test(),a= 100

若想这个a与上一层a为同一个,则需要加一句nonlocal a,来声明变量是外部的本地变量。

>>> def test():
...   a=10
...   def show():
...     nonlocal a
...     a=100
...     print('in show(),a=',a)
...   show()
...   print('in test(),a=',a)
...
>>> test()
in show(),a= 100
in test(),a= 100

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值