python 函数进阶_Python之函数——进阶篇

嵌套函数

---函数内部可以再次定义函数

---函数若想执行,必须被调用

注意,下例中,执行结果为什么?

age = 19

deffunc1():print(age)deffunc2():print(age)

func2()

age= 73func1()

如下:

执行fun2()时,age按从内而外规则寻找,但age = 73还未执行。但又被检测到赋值语句,因此程序不知道应该从哪里寻找,故报错。

*global、nonlocal关键字:

global:声明变量在全局作用域内使用

nonlocal:声明变量在最近一外层函数作用域内使用

deff1():

a= 1

deff2():

nonlocal a

a= 2f2()print('a in f1 :',a)

f1()#nonlocal关键字:#1.外部必须有这个变量,此处外部不包括全局作用域#2.在内部函数声明nonlocal变量之前内部不能再出现同名变量#3.内部修改这个变量在外部有这个变量的第一层函数中生效(即最近以外层作用域)

nonlocal

闭包

关于闭包,即函数定义和函数表达式位于另一个函数的函数体内(嵌套函数)。而且,这些内部函数可以访问它们所在的外部函数中声明的所有局部变量、参数。当其中一个这样的内部函数在包含它们的外部函数之外被调用时,就会形成闭包。也就是说,内部函数会在外部函数返回后被执行。而当这个内部函数执行时,它仍然必需访问其外部函数的局部变量、参数以及其他内部函数。这些局部变量、参数和函数声明(最初时)的值是外部函数返回时的值,但也会受到内部函数的影响。

age = 19

deffunc1():

age= 73

deffunc2():print(age)returnfunc2

val=func1()print(val)

结果如下:

是func2的内存地址!

age = 19

deffunc1():

age= 73

deffunc2():print(age)returnfunc2

val=func1()

val()

结果如下:

验证:代码定义完成后,作用域已经生成,无论何时调用该函数,参数值都回回到定义该函数时的作用域内寻找。

闭包的意义:返回的函数对象,不仅仅是一个函数对象,在该函数外还包裹了一层作用域,这使得,该函数无论在何处调用,优先使用自己外层包裹的作用域。

匿名函数

lambda x,y:x*y #声明一个匿名函数

如何调用匿名函数呢?

func = lambda x,y:x*yprint(func(3,8))

把多行代码简写成一行,匿名函数不能支持复杂的代码(如循环),最多跟三元运算符,lambda一般会跟其他方法配合使用。

现在想将一个列表中所有元素自乘,代码如下:

data = list(range(10))

list1= list(map(lambda x: x*x, data))print(list1)

结果如下:

函数名的本质和高阶函数

函数名本质上就是函数的内存地址

1.可以被引用

deffunc():print('in func')

f=funcprint(f)

被引用

2.可以被当作容器类型的元素

deff1():print('f1')deff2():print('f2')deff3():print('f3')

l=[f1,f2,f3]

d= {'f1':f1,'f2':f2,'f3':f3}#调用

l[0]()

d['f2']()

当做容器类型元素

3.可以当作函数的参数和返回值

高阶函数:变量可以指向函数,函数的参数能接收变量,那么一个函数就可以接收另一个函数作为参数,这种函数就称之为高阶函数。

不明白?那就记住一句话,就当普通变量用

第一类对象(first-classobject)指1.可在运行期创建2.可用作函数参数或返回值3.可存入变量的实体。

第一类对象

递归

defcalc(n,count):print(n, count)if count >0:return calc(n/2, count-1)else:returnn

res= calc(188,5)print('res', res)

特性:

--必须有一个明确的结束条件

--每进入更深一层次时,问题规模相比上次递归都应有所减少

--递归的效率不高,递归层次过多会导致栈溢出

列表生成式

有个需求,列表[0, 1, 2, 3, 4, 5, 6, 7, 8, 9],要求把列表里的每个值加1,你怎么实现?

可以如下实现:

a = map(lambda x:x+1,a)

其实还有一种写法:

b = [i+1 for i in range(10)]

这种写法就叫做列表生成式

又如:

a = [1,2,3,4,5,6,7]

a= [i if i<5 else i*i for i in a]

生成器

生成器的创建方式:

1. 类似列表生成式的方式

a = (i+1 for i in range(10))

next(a)

next(a)

结果如下:

2. 函数

defrange_new(n):

count=0while count

count+= 1xrange= range_new(10)print(next(xrange)) #也可以写成 xrange.__next__

print(next(xrange))print(next(xrange))

结果如下:

yield vs return

return:返回数据并终止function

yield:返回数据并冻结当前的执行过程

next:唤醒冻结的函数执行过程,继续执行,直到遇到下一个yield

函数有了yield后...

1.函数名加()就成了一个生成器

2.return在生成器里,代表生成器的终止,会报错(StopIteration:A,A为return的值)

next vs send

next:唤醒冻结的函数执行过程继续执行,直到遇到下一个yield

send:唤醒冻结的函数执行过程继续执行,并且发送一个信息到生成器内部

defrange_new(n):

count=0while count

sign= yieldcount

count+= 1

if sign == 'Stop':breakxrange= range_new(10)print(next(xrange))

xrange.send('Stop')

迭代器

迭代,即是循环。我们已知的可以直接作用域for循环的数据类型有以下几种:

一是集合数据类型,如list、tuple、dict等;

二是generator,包括生成器和带yield的函数。

可迭代对象:这些可以直接作用域for循环的对象统称为可迭代对象:Iterable。

可以使用isinstance()判断一个对象是否是Iterable对象:

迭代器:可以被next()函数调用并不断返回下一个值的对象称为迭代器:Iterator。

生成器都是Iterator对象,但list、dict、str虽然是Iterable,却不是Iterator。

把list、dict、str等Iterable变成Iterator可以使用iter()函数:

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值