函数

函数基础

一、为什么要使用函数

把重复的代码提取出来,节省代码量

二、函数分类

内置函数,如len(),sun()

自定义函数

三、如何定义函数

def 函数名(参数1,参数2,参数3,...):'''注释'''函数体return 返回的值

四、函数使用的原则:先定义,后使用

五、调用函数

1、如何调用函数:函数名加括号

2、函数的返回值

函数的返回值通常都是一个,如果出现 return a,b 这种情况,其实是表示一个元组

六、函数的参数

#1、位置参数:按照从左到右的顺序定义的参数

位置形参:必选参数

位置实参:按照位置给形参传值,顺序必须一一对应

#2、关键字参数:按照key=value的形式定义的实参

无需按照位置为形参传值

注意的问题:

1. 关键字实参必须在位置实参右面

2. 对同一个形参不能重复传值

#3、默认参数:形参在定义时就已经为其赋值

可以传值也可以不传值,经常需要变得参数定义成位置形参,变化较小的参数定义成默认参数(形参)

注意的问题:

1. 只在定义时赋值一次

2. 默认参数的定义应该在位置形参右面

3. 默认参数通常应该定义成不可变类型,举例

def add_end(L=[]):print(id(L))L.append('END')return Lprint(add_end())
print(add_end())

结果:

2822355733768
['END']
2822355733768
['END', 'END']

解释:python函数在定义好时,形参、内部参数等变量就已经有了固定的内存空间(变量始终指向那一块内存,不会更改)。默认参数形参变量如果是可变的,下一次调用该函数时,默认参数就已经发生了变化。

#4、可变长参数: 可变长指的是实参值的个数不固定

而实参有按位置和按关键字两种形式定义,针对这两种形式的可变长,形参对应有两种解决方案来完整地存放它们,分别是*args,**kwargs

===========*args===========

def foo(x,y,*args):   print(x,y)  print(args) foo(1,2,3,4,5) 

def foo(x,y,*args):   print(x,y)   print(args) foo(1,2,*[3,4,5]) 

def foo(x,y,z):   print(x,y,z) foo(*[1,2,3])

当形参为*args,实参可以用 *()或者 *[] 的方式将若干个参数打包发送给形参

===========**kwargs===========

def foo(x,y,**kwargs):   print(x,y)   print(kwargs) foo(1,y=2,a=1,b=2,c=3) 

def foo(x,y,**kwargs):   print(x,y)   print(kwargs) foo(1,y=2,**{'a':1,'b':2,'c':3}) 

def foo(x,y,z):   print(x,y,z) foo(**{'z':1,'x':2,'y':3}) 

当形参为**kwargs时,实参可以通过**{}的方式将若干参数打包发送给形参

===========*args+**kwargs===========

def foo(x,y):   print(x,y) 

def wrapper(*args,**kwargs):   print('====>') foo(*args,**kwargs)

#5、命名关键字参数:*后定义的参数,必须被传值(有默认值的除外),且必须按照关键字实参的形式传递,可以保证,传入的参数中一定包含某些关键字

和关键字参数**kw不同,命名关键字参数需要一个特殊分隔符**后面的参数被视为命名关键字参数(如果参数中已经有了可变参数*args,则不需要 * 来特别标明)

def foo(x,y,*args,a=1,b,**kwargs):print(x,y)print(args)print(a)print(b)print(kwargs)
foo(1,2,3,4,5,b=3,c=4,d=5)
结果: 1 2 (3, 4, 5) 1 3 {'c': 4, 'd': 5}

闭包

一、函数是对象

函数可以当做参数传递,也可以返回一个函数

利用该特性,可以写成一个类似C语言switch case语法的功能,取代多分支if

def foo():print('foo')def bar():print('bar')dic={'foo':foo,'bar':bar,
}
while True:choice=input('>>: ').strip()if choice in dic:dic[choice]()

二、函数嵌套、名称空间、作用域的概念

1、函数嵌套调用

函数嵌套定义

2、名称空间

存放名字的地方,x=1,1存3、放于内存中,那名字x存放在哪里呢?名称空间是存放名字x与1绑定关系的地方,L = [1,2,3],L存放在名称空间里,真正的列表在其他地方。

3、作用域

#1、作用域即范围

-全局范围(内置名称空间与全局名称空间属于该范围):全局存活,全局有效  

-局部范围(局部名称空间属于该范围):临时存活,局部有效

内部的函数可以访问外部的变量,但是外面的函数访问不了内部函数

#2、作用域关系是在函数定义阶段就已经固定的,与函数的调用位置无关

#3、查看作用域:globals(),locals()

python中globals和nonlocals的用法

LEGB 代表名字查找顺序: locals -> enclosing function -> globals -> __builtins__

locals 是函数内的名字空间,包括局部变量和形参

enclosing 外部嵌套函数的名字空间(闭包中常见)

globals 全局变量,函数定义所在模块的名字空间

builtins 内置模块的名字空间

闭包函数

内部函数包含对外部函数而非全局作用域的引用

def counter():n = 0def incr():nonlocal nx = nn += 1return xreturn incrc = counter()
print(c())
print(c())
print(c())
print(c.__closure__[0].cell_contents)  # 查看闭包的元素

结果:

0
1
2
3

闭包函数的意义:

返回的函数对象,不仅仅是一个函数,在该函数外还包裹了一个外层作用域(一般含是变量),这使得,该函数无论在何处调用,都优先使用自己外层包裹的作用域,相对于更外层的比如全局作用域。

实现延迟计算的功能:

普通函数调用后立即函数执行,闭包则是给函数包裹上了一层外层作用域,传了参数的功能。

装饰器

1、装饰器是闭包函数的一种应用

2、装饰器可以在不修改原函数功能的前提下,添加额外功能。开放封闭原则

#不带参数的装饰器

import time
def timmer(func):def wrapper(*args,**kwargs):start_time=time.time()res=func(*args,**kwargs)stop_time=time.time()print('run time is %s' %(stop_time-start_time))return resreturn wrapper@timmer   #相当于foo = timmer(foo)
def foo():time.sleep(3)print('from foo')
foo()

#利用闭包的特点:1、具有延迟计算的功能,函数不是立即执行;2、闭包相当于包裹了一个外层作用域的函数。当timmer函数执行后,形参 func,原函数作为一个对象传到了形参,传给了内层函数 wrapper,即使timmer执行完毕了,形参会一直存在着。

#带参数的装饰器

def auth(driver='file'):def auth2(func):def wrapper(*args,**kwargs):name=input("user: ")pwd=input("pwd: ")if driver == 'file':if name == 'egon' and pwd == '123':print('login successful')res=func(*args,**kwargs)  #原函数其实就一个调用,其他都是额外功能,装饰作用return reselif driver == 'ldap':print('ldap')return wrapperreturn auth2@auth(driver='file')
def foo(name):print(name)foo('egon')

迭代器

1、为什么要有迭代器:

有序序列,如列表,字符串可以通过索引的方式取出其中的元素,而对于字典,文件,集合等类型,是没用索引的,所以需要通过不依靠索引的迭代方式,就是迭代器。

2、什么是可迭代对象:

可迭代对象指的是实现了__iter__方法的对象

3、什么是迭代器(对象):

可迭代对象执行obj.__iter__()得到的结果就是迭代器对象,同时,迭代器内部还有__next__方法

文件类型是可迭代器对象
open('a.txt').__iter__()
open('a.txt').__next__()

注意:

迭代器对象一定是可迭代对象,而可迭代对象不一定是迭代器对象

迭代器对象的使用

dic = {'a':1, 'b':2, 'c':3}

iter_dic = dic.__iter__()   #得到一个迭代器

注意:迭代器.__iter__() 得到仍然是迭代器本身

print(iter_dic.__next__()) #等同于next(iter_dic)

print(iter_dic.__next__()) #等同于next(iter_dic)

print(iter_dic.__next__()) #等同于next(iter_dic)

print(iter_dic.__next__()) #抛出异常StopIteration,或者说结束标志

iter_dic=dic.__iter__()
while 1:try:k=next(iter_dic)print(dic[k])except StopIteration:break
通过next方法从迭代器取数据,需要手动捕获异常

for循环执行next方法,并且自动捕获异常

dic={'a':1,'b':2,'c':3}
for k in dic:print(dic[k])for循环的工作原理
1:执行in后对象的dic.__iter__()方法,得到一个迭代器对象iter_dic
2: 执行next(iter_dic),将得到的值赋值给k,然后执行循环体代码
3: 重复过程2,直到捕捉到异常StopIteration,结束循环

生成器

概念:

只要函数内部包含有yield关键字,那么函数名()的到的结果就是生成器,加括号不会执行函数内部的代码

注意:生成器是一种特殊的迭代器,生成器内置__next__,__iter__方法

send方法的使用:

def range2(n):count =0while count < n:print('count',count)count += 1sign = yield countprint('-------sign',sign)return 333new_range = range2(3)
n1 = next(new_range)print('do sth else')
new_range.send('stop!')

send与next的区别:

  两者都可以唤醒生成器,来继续执行

  send的作用:外界可以发送一个信号给生成器内部,表达式 sign = yield count, 而next是默认发送为None的

  

只使用send的情况:

#yield关键字的另外一种使用形式:表达式形式的yield
def eater(name):print('%s 准备开始吃饭啦' %name)food_list=[]while True:food=yield food_listprint('%s 吃了 %s' % (name,food))food_list.append(food)g=eater('egon')
g.send(None) #对于表达式形式的yield,在使用时,第一次必须传None,g.send(None)等同于next(g)
g.send('蒸羊羔')
g.send('蒸鹿茸')
g.send('蒸熊掌')
g.send('烧素鸭')
g.close()
g.send('烧素鹅')
g.send('烧鹿尾')

转载于:https://www.cnblogs.com/liyuexi/p/10702873.html

函数、迭代器、生成器、装饰器相关推荐

  1. 迭代器 生成器 装饰器 匿名函数

    迭代器 生成器 装饰器 匿名函数 #可迭代对象:列表.字典.集合.字符串:能够被for 循环遍历的对象# 数字类型不可迭代:# name="wangyifei"# for i in ...

  2. 迭代器/生成器/装饰器 /Json pickle 数据序列化

    本节内容 迭代器&生成器 装饰器 Json & pickle 数据序列化 软件目录结构规范 作业:ATM项目开发 1.列表生成式,迭代器&生成器 列表生成式 孩子,我现在有个需 ...

  3. Python基础 day4 迭代器生成器 装饰器 Json pickle 数据序列化 软件目录结构规范 作业:ATM项目开发...

    本节内容 迭代器&生成器 装饰器 Json & pickle 数据序列化 软件目录结构规范 作业:ATM项目开发 列表生成器 1.列表生成式,迭代器&生成器 列表生成式 孩子, ...

  4. python迭代器生成器装饰器

    基本概念 学习python中有什么不懂的地方,小编这里推荐加小编的python学习群:895 817 687有任何不懂的都可以在里面交流,还有很好的视频教程pdf学习资料,大家一起学习交流! 1.容器 ...

  5. python 生成器装饰器_4.python迭代器生成器装饰器

    基本概念 1.容器(container) 容器是一种把多个元素组织在一起的数据结构,容器中的元素可以逐个地迭代获取,可以用in, not in关键字判断元素是否包含在容器中.通常这类数据结构把所有的元 ...

  6. python 生成器装饰器_七.python迭代器生成器装饰器

    1.迭代器 1.1 什么是可迭代对象(Iterable)? 定义:可以直接作用于for循环的对象统称为可迭代对象,即Iterable. 可迭代对象包括: 1.集合数据类型:如list.tuple.di ...

  7. Python 3 学习——函数扩展and迭代器生成器装饰器

    Python 学习的第九小节 写此博客 是为了激励自己,并且将自己的心得以及遇到的问题与人分享 一.学习笔记 1. 高阶函数 函数名可以作为函数参数输入 .可以进行赋值.还可以作为返回值. 2.作用域 ...

  8. python学习day-8 迭代器 生成器 装饰器

    http://www.cnblogs.com/linhaifeng/articles/7580428.html 迭代器#迭代器即迭代的工具,那什么是迭代呢?#迭代是一个重复的过程,每次重复即一次迭代, ...

  9. day04 迭代器生成器装饰器

    目录   1.迭代器 2.生成器 3.推导式 4.匿名函数 5.内置函数 6.递归 7.闭包 8.装饰器 一.迭代器 特点: 1. 省内存 2. 只能向前. 不能反复 3. 惰性机制 让不同的数据类型 ...

  10. python基础(迭代器,生成器,装饰器)

    python: 生成器: 因为当列表元素达到一定上限,列表会占很大内存空间来存储,所以列表是受到内存限制的来适当使用. 生成器可以按照一个算法,循环推导出元素,就不用一次生成整个列表,而通过生成器(g ...

最新文章

  1. 其他算法-浅谈小波变换
  2. Intel Realsense D435 多摄像头多线程目标识别架构
  3. 【CentOS Linux 7】实验1【VMware安装、新建虚拟机;63个基础命令运行结果图】
  4. rename、remove
  5. mysql内存机制_MySQL内存管理机制
  6. ARP,这个隐匿在计网背后的男人
  7. go语言linux下开发工具,LiteIDE 开发工具指南 (Go语言开发工具)
  8. Linux系统下网卡网络配置基础
  9. centos7 常用命令参考
  10. Django模块学习- django-pagination
  11. 数据结构时间复杂度_数据结构之时间复杂度分析
  12. Java基础 IO流——第三部分
  13. 【iOS沉思录】:iOS多媒体音频(下)-录音及其播放
  14. WinCE开发流媒体播放器--MPEG4
  15. 北斗导航 | dBW/dBm/W快速换算方法
  16. C语言 找数字,用(折半查找法或二分查找法)
  17. 傅立叶变换系列(二)傅立叶级数
  18. ViewPagerIndicator
  19. 桌面只计算机图标发白,win7系统桌面图标变白怎么回事_电脑桌面图标有小白块...
  20. Docker - 应用镜像

热门文章

  1. NOI入门级:算法之动态规划
  2. python编程与数学书籍
  3. 2.1基本算法之枚举_1749数字方格
  4. awk 匹配_linux的awk命令详解,通俗易懂
  5. STM32H743+CubeMX-QSPI+DMA读取外部FLASH(W25Q128JVSQ)
  6. 【四】Java流程控制
  7. c# imager让图片有圆角unity_Unity纹理-引题和单张纹理
  8. Android逆向笔记-使用Android Studio调试Smali代码(方式二)
  9. MySQL笔记-Slave_IO_Running:No【Could ... ... in binary log index file (server_errno=1236)】
  10. OllyDbg笔记-寄存器以及各种关键指令解析(含简单程序破解)