python foo函数_Python 函数

本文详细介绍了Python中的函数,包括函数的定义、调用、返回值、参数类型(位置参数、关键字参数、默认参数、可变长度参数)、函数对象、嵌套调用、作用域与名称空间、装饰器、闭包和递归。通过实例解析了函数的使用和原理,帮助读者深入理解Python函数的各个方面。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、函数

1、什么是函数:函数就是具备某一功能的工具

函数的使用必须遵循先定义、后调用的原则

事先准备工具的过程即函数的定义

拿来就用即为函数的调用

函数分为两大类:1、内置的函数   2、自定义的函数

2、为什么要用函数:

2.1 程序的组织结构不清晰、可读性差

2.2 日积月累冗余代码过多

2.3 程序的可扩展性极差

3、怎么用函数

3.1定义函数

3.1.1 语法

#def 函数名(参数1,参数2,参数3,...):#"""#文档注释#"""#code1#code2#code3#...#return 返回值

3.1.2 定义函数阶段发生哪些事:只检测语法,不执行代码

def foo(): #foo=函数的内存地址

print('first')print('sencod')print('asdfsadfasdfas')print('third')

foo()

## 定义阶段

deffoo():print('from foo')

bar()defbar():print('from bar')#调用阶段

foo()

3.1.3 定义函数的三种形式

1.无参函数

defbar():print('from bar')

bar()

2.有参函数

deffunc2(x,y):#x=1

#y=3

if x >y:print(x)else:print(y)

func2(1,3)

3.空函数(做占位使用)

deffoo():pass

3.2调用函数

语法:函数名()

调用函数发生了:1、根据函数名找到函数的内存地址  2、函数的内存地址加括号可以触发函数体代码的执行

调用函数的三种方式:

3.2.1 语句

deff1():print('from 1')

f1()

3.2.2表达式

defmax2(x,y):if x >y:returnxelse:returny

res=max(1,2)*10

print(res)

3.2.3当做参数传给其他函数

defmax2(x,y):if x >y:returnxelse:returny

res=max2(max2(1,2),3)print(res)

4、函数的返回值

1、什么是函数的返回值:函数体代码运行的一个成果

return 值:

返回值没有类型限制、返回值没有个数限制

逗号分割多个值:返回一个元组

一个值:返回一个值

没有return:默认返回None

deflogin():whileTrue:

username=input('name>>:').strip()

pwd=input('password>>:').strip()if username not inuser_dic:print('not found')continue

if pwd !=user_dic[username]:print('pwd error')continue

print('login successful')returnusernameprint(login())

return 登录名

#return是函数结束的标志:#函数内可以有多个return,但只要执行一次,整个函数就立即结束,并且将return后的值当作本次调用的结果返回

二、函数的参数

1、函数的参数分为两大类:形参、实参

形参:指的是在定义函数时,括号指定的参数,本质就是变量名

实参:指的是在调用函数时,括号内传入的值,本质就是值

只有在调用函数时才会在函数体内发生实参(值)与形参(变量名)的绑定关系

该绑定关系只在调用函数时临时生效,在调用函数结束后就解除绑定

def foo(x,y): #x=1,y=2

print(x)print(y)#a=1

#b=2

#foo(a,b)

foo(1,2)

2、位置参数

位置形参:在定义函数时,按照从左到右的顺序依次定义的形参称之为位置形参

ps:但凡是按照位置定义的形参,在调用函数时必须为其传值,多一个不行少一个也不行

位置实参:在调用函数时,按照从左到右的顺序依次传入的值

ps:传值是按照顺序与形参一 一对应

deffoo(x,y,z):print(x,y,z)#foo(1,2)

foo(1,2,3,4)#多传一个值 报错#foo(1,2,3)

foo(3,2,1)

3、关键字实参:

在调用函数时,按照key=value的形式定义的实参,称之为关键字实参

注意:

1、在传值时可以完全打乱顺序,但仍然能指定道姓地为指定的参数传值

2、可以在调用函数时,混合使用位置实参与关键字实参

但是位置实参必须跟在关键字实参左边

并且不能为一个形参重复传值

defregister(name,sex,age):print(name)print(sex)print(age)

register(sex='male',name='mogu',age=18)

register('mogu',age=18,sex='male')#混合使用

4、默认参数

在定义函数时,就已经为某些参数绑定值,称为默认参数

ps:1、在定义阶段就已经有值,意味在调用阶段可以不用传值

2、默认形参必须放在位置形参的后面

3、默认形参的值只在定义阶段生效一次,在函数定义之后发生的改动无效

4、默认形参的值通常应该是不可变类型

默认形参:大多数情况下值都一样

位置形参:大多数情况值都不同

def foo(x,y,z=3):print(x)print(y)print(z)

foo(1,2)

foo(1,2,4) #传值后改变了默认值

def register(name,age,sex='female'):print(name)print(sex)print(age)

register('mogu',18)

register('xiaohuochai',28)

register('momo',19)

register('张三',33,'male')

默认与位置示例

m=10

def foo(x,y,z=m):print('x:%s' %x)print('y:%s' %y)print('z:%s' %z)

m=111111111 #定义阶段就是10 此更改无效

foo(1,2)

def foo(name,hobby,l=None):if l isNone:

l=[]

l.append(hobby)print('%s 的爱好是 %s' %(name,l))

l1=[]

foo('mogu','read',l1) #l1=['read']

foo('xiaomogu','movie') #l1=['read','music']

foo('nvhai','卖火柴')

foo('张三','吹牛')

foo('关二爷','耍大刀')

默认形参示例2

5、可变长度的参数

可变长度指的是在调用函数时,函数参数的个数可以不固定

然而实参终究是要为形参传值的,针对两种形式实参个数不固定,对应着形参也必须有两种解决方案

那就是 * 和 ** 来分别处理溢出位置实参与溢出关键字实参

5.1 * 会将溢出的位置实参存成元组,然后赋值给紧跟其后的变量名

5.1.1 形参中带 *

def foo(x,y,*z): #z=(3,4,5,6,7,8)

print(x)print(y)print(z)

foo(1,2,3,4,5,6,7,8)

5.1.2  形参中带*   实参中带 * ,窍门:但凡碰到实参中带*  都先将其打散成位置实参,然后考虑传值

def foo(x,y,*z): #z=(3,4,5,6,7,8)

print(x)print(y)print(z)

foo(1,2,[3,4,5,6,7,8]) #z=([3,4,5,6,7,8],)

foo(1,2,*[3,4,5,6,7,8]) #foo(1,2,3,4,5,6,7,8)====>z=(3,4,5,6,7,8)

foo(1,2,*'hello') #foo(1,2,'h','e','l','l','o')

foo(1,*[2,3,4,5,6]) #foo(1,2,3,4,5,6)

5.1.3 实参中带 *  窍门同上

deffoo(x,y,z):print(x,y,z)

l= ['mogu', 'huochai', 'nvhai']

foo(*l) #foo('mogu', 'huochai', 'nvhai')

5.2  ** 会将溢出的关键字实参存成字典,然后赋值给紧跟其后的变量名

5.2.1 形参中带 **

def foo(x,y,m,n,**z): # print(x)print(y)print(m)print(n)print(z)

foo(1,2,n=10,m=20,a=1,b=2,c=3)

View Code

5.2.2 形参中带 **  实参中带 **  窍门:但凡碰到实参中带**  都先将其打散成位置实参,然后考虑传值

def foo(x,y,**z): # print(x,y,z)

foo(1,2,**{'a':1,'b':2,'c':2}) #foo(1,2,c=2,a=1,b=2)

foo(1,**{'a':1,'b':2,'c':2,'y':111}) #foo(1,c=2,a=1,b=2,y=111)

5.2.3 实参中带**

deffoo(x,y,z):print(x,y,z)

foo(1,**{'y':111,'z':222}) #foo(1,y=111,z=222)

foo(**{'z':1,'y':2,'x':3}) #foo(y=2,z=1,x=3)

6、 *args  和 **kwargs

可接收任意长度,任意格式的参数(ps:实参中:位置实参必须在关键字实参的左边)

def foo(*args,**kwargs):print(args,kwargs)#可完美转嫁

foo(任意长度,格式的实参)

#需要将外层函数的参数格式原封不动的转嫁给其内部调用的函数,就需要以下

defindex(name,age,sex):print('name:%s age:%s sex:%s' %(name,age,sex))def foo(*args,**kwargs):

index(*args,**kwargs)#可完美转嫁

foo('mogu',sex='male',age=18)#虽然调用的是foo函数,但是需要遵循

index函数的参数规则

示例

三、函数对象

函数是第一类对象,意味着函数可以当做数据去使用

deffoo():print('from foo')

引用

print(foo)

func=fooprint(func)

func()

当做参数传给另外一个函数

def bar(x): #x=foo的内存地址

print(x)

x()

bar(foo)

当做函数的返回值

defbar():returnfoo

f=bar()#print(f is foo)

f()

当作容器类型的元素

deff1():print('from f1')deff2():print('from f2')

l=[f1,f2] #列表内全为函数体

print(l)

l[1]()

l[0]()

四、函数的嵌套调用

1、嵌套调用

在调用一个函数时,其内部的代码又调用其他的函数

defbar():print('from bar')deffoo():print('from foo')

bar()

foo()

defmax2(x,y):if x >y:returnxelse:returny#defmax4(a,b,c,d):

res1=max2(a,b)

res2=max2(res1,c)

res3=max2(res2,d)returnres3print(max4(1,2,3,4))

数值大小比较

2、嵌套定义

在一个函数的内部又定义了另外一个函数

deff1():

x=1

deff2():print('from f2')print(x)print(f2)

f2()

f1()

五、名称空间和作用域

1、什么是名称空间:名称空间是存放名字与值绑定关系的地方

要取到值必须通过名字才能找,而名字又在名称空间中存放着,所以取值时首先去名称空间中找名字

找到了名字自然拿到值的内存地址。

2、名称空间分为三种:

2.1 内置名称空间:存放的python解释器自带的名字

生命周期:在解释器启动时产生,在解释器关闭时回收

2.2 全局名称空间:除了内置的与局部的之外名字都属于全局名称空间

生命周期:在程序文件执行时就立刻产生,在程序执行完毕后就回收

x=1y=2

deffoo():

x=1y=2foo()if y >x:print(x)

z=3

#其中:x,y,foo,z都是全局名称空间中的名字

2.3局部名称空间:存放的是函数内部定义的名字

生命周期:在调用时临时生效,在函数结束后立刻回收

len=100

#print(len) # 站在全局查找

deffoo():

len=2222

print(len) #先在局部查找

foo()

加载顺序

内置名称空间--->全局名称空间--->局部名称空间

加载名称空间的目的是为了将名字与值的绑定关系存放起来

而存的目的是为了取,也就是当我们查找名字时,必然是在三者之一中找到

查找顺序

局部名称空间--->全局名称空间--->内置名称空间

基于当前所在位置往后查找

x=100y=200

#强调:函数的形参名属于局部名称空间

deffoo(x,y):print(x,y)

foo(1,2) #print结果为1,2

x=2222

deff1():#x=1

deff2():#x=2

print('from f2',x)

f2()

x=111f1()#print结果为 from f2 111

ps:全局查找

x=2222

deff1():#x=1

deff2():

x=2 #先在局部查找

print('from f2',x)

f2()

x=111f1()#结果为 from f2 2

ps:局部查找

3、作用域

域指的是范围,作用域指的是作用范围

3.1.全局作用范围:包含内置名称空间与全局名称空间中的名字

特点:全局有效,全局存活

3.2.局部作用范围:包含局部名称空间中的名字

特点:局部有效,临时存活

x=1

deff1():deff2():deff3():

x=3 #函数此处有值 所有全局的x=1 并不会取

print(x)

f3()

f2()

f1()#函数调用会先在函数内部寻找,所有结果为 3#deffoo():print(x)

foo()#而此处函数内部未定义x 所以会找全局 1

作用范围

#如何打破函数层级带来的访问限制,让我能够在任意位置都可以访问到一个内部函数#基于函数对象的概念将一个内部函数返回(return)到全局使用,从而打破了函数的层级限制

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

即在调用函数时一定要跑到定义函数的位置寻找作用域关系

x=111

defoutter():

x=33333

definner():print('from inner',x)#x=4444 #此处再定义会报错

returninner

x=222f=outter() #f=指向outter.locals.inner

f() #结果为from inner 33333

作用域关系

3.4.  global 和  nonlocal

global :在局部声明名字是来自全局的

x=1

deffunc():global x #声明x为全局

x=2 #所以此处即修改了全局的x

func()print(x) #结果为 2

nonlocal :声明变量来自当前层外层(必须在函数内)

x=222

deff1():

x=111

deff2():#nonlocal x

x=3

print('f2---->',x) #f2-----> 3

f2()print('f1---->',x) #f1-------> 111

f1()print('global------>',x) #global------> 222

无nonlocal结果

x=222

deff1():

x=111

deff2():

nonlocal x

x=3

print('f2---->',x) #f2-----> 3

f2()print('f1---->',x) #f1-------> 3

f1()print('global------>',x) #global------> 222

有nonlocal结果

六、装饰器

一、闭包函数(函数体传值的新方式)

1、闭 -------->定义在函数内部的函数

2、包 -------->该内部函数包含对其外层函数作用域名字的引用

闭包函数通常需要结合函数对象的概念,将闭包函数返回到外部使用

#闭包函数基本形式

defoutter():

x=1

definner():print(x)returninner

#将值包给函数

import requests #导入爬虫模块#def outter(url):##url='https://www.jd.com'#def get():#response=requests.get(url)#print(len(response.text))#return get#

#jd=outter('https://www.jd.com')#第一调用传入京东#jd() # 以后调用只需要 jd加括号就能得到结果, 新的传值方式

示例:闭包应用

二、装饰器

装饰指的是为被装饰对象添加新的功能

器指的工具

装饰器本身是任意可以调用的对象,被装饰对象也是任意可以调用的对象

ps:写一个函数用来为另一个函数添加新功能,需要遵循开放封闭原则(对修改是封闭的,对扩展是开放的)

1、不修改被装饰对象的源代码

2、不修改被装饰对象的调用方式

importtimedef index(): #被装饰对象

time.sleep(2)print('welcome to index page')#

#index() #原先功能

def outter(func): #func=最原始index

defwrapper():

start_time=time.time()

func()#上方的index() 原先功能

stop_time=time.time()print('run time is %s' %(stop_time-start_time)) #加入新功能

returnwrapper

index=outter(index) #index=wrapper 加入新功能,并且调用方式没变

index()

装饰器的示例

importtimedef home(name): #有参

time.sleep(1)print('welcome %s to home page' %name)return 'lalala'

def timmer(func): #func=最原始index

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))returnresreturnwrapper

home=timmer(home) #home=warapper

print(home('mogu'))

被装饰对象有参

二、1、装饰器的语法糖

在被装饰对象正上方单独一行写上@装饰器名字

importtimedef timmer(func): #func=最原始index

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))returnresreturnwrapper

@timmer#index=timmer(index)

defindex():

time.sleep(1)print('welcome to index page')return 'lalala'index()

装饰器的语法糖!!

importtime

current_userinfo={'user':None}defoutter(func):def wrapper(*args,**kwargs):if current_userinfo['user']:return func(*args,**kwargs)

user=input('please input you username:').strip()

pwd=input('please input you password:').strip()if user == 'mogu' and pwd == '123':print('login successfull')#保存登录状态

current_userinfo['user']=user

res=func(*args,**kwargs)returnreselse:print('user or password error')returnwrapper

@outter#index=outter(index)

defindex():print('welcome to index page')

time.sleep(3)

@outter#home=outter(home)

defhome(name):print('welecom %s' %name)

time.sleep(2)return 123index()#wrapper()

res=home('mogu') #res=wrapper('mogu')

认证功能装饰器

二、2、添加多个装饰器

importtime

current_userinfo={'user':None}def timmer(func): #func=最原始的index指向的内存地址

def wrapper2(*args,**kwargs):print('wrapper2.....')

start=time.time()

res=func(*args,**kwargs) #func=最原始的index指向的内存地址

stop=time.time()print('run time is %s' %(stop -start))returnresreturnwrapper2def outter(func): #func=wrapper2

def wrapper1(*args,**kwargs):print('wrapper1.....')if current_userinfo['user']:return func(*args,**kwargs)

user=input('please input you username:').strip()

pwd=input('please input you password:').strip()if user == 'mogu' and pwd == '123':print('login successfull')#保存登录状态

current_userinfo['user']=user

res=func(*args,**kwargs) #func=wrapper2

returnreselse:print('user or password err')returnwrapper1#解释语法的时候应该自下而上#执行时则是自上而下#可以连续写多个装饰器,处于最顶层的装饰器先执行

@outter #index=outter(wrapper2) # index=wrapper1

@timmer #timmer(最原始的index指向的内存地址) ==>wrapper2

defindex():print('welcome to index page')

time.sleep(3)

index()#wrapper1()

多个装饰器使用

二、3、有参数的装饰器

importtime

current_userinfo={'user':None}def auth(engine='file'):#参数代表认证模式

def outter(func): #func=最原始的index

def wrapper(*args,**kwargs):if engine == 'file':#if判断认证模式

if current_userinfo['user']:return func(*args,**kwargs)

user=input('please input you username:').strip()

pwd=input('please input you password:').strip()if user == 'mogu' and pwd == '123':print('login successfull')#保存登录状态

current_userinfo['user']=user

res=func(*args,**kwargs)returnreselse:print('user or password err')elif engine == 'mysql':print('mysql 的认证机制')

res= func(*args, **kwargs)returnreselif engine == 'ldap':print('ldap 的认证机制')else:print('不支持该engine')returnwrapperreturnoutter

@auth(engine='mysql') #@outter # index=outter(最原始的index) # index= wrapper

defindex():print('welcome to index page')

time.sleep(3)

@auth(engine='ldap')defhome(name):print('welecom %s' %name)

time.sleep(2)return 123index()#warpper()

home('蘑菇') #wrapper('蘑菇')

View Code

二、4、wraps装饰器

被装饰后的函数其实已经是另外一个函数了(函数名等函数属性会发生改变),为了不影响,Python的functools包中提供了一个叫wraps的decorator来消除这样的副作用。

#wraps作用将被装饰对象属性赋值给 装饰器的wrapper

importtimefrom functools importwrapsdeftimmer(func):

@wraps(func)def wrapper(*args,**kwargs):

start=time.time()

res=func(*args,**kwargs)

stop=time.time()print('run time is %s' %(stop -start))returnres#wrapper.__doc__ = func.__doc__

#wrapper.__name__= func.__name__

returnwrapper

@timmerdefindex():"""这是一个index函数

:return:"""

print('welcome to index page')

time.sleep(1)return 123

print(help(index)) #index.__doc__

#print(index.__name__)

wraps 装饰器

七、表达式,生成式

三元表达式

语法:【条件成立时的返回值】 +  if 条件    +  else【条件不成立时的返回值】

#res=条件成立时的返回值 if 条件 else 条件不成立时的返回值

defmax2(x,y):if x >y:returnxelse:returny

res=max2(1,2)

x=10y=2res=x if x > y elsey

res=True if x > y elseFalseprint(res)

三元表达式

列表生成式

语法: i  +   for循环   可以跟 【条件】

#原先列表生成

l=[]for i in range(10):if i > 3:

l.append(i)print(l)#列表生成式

l1=[i for i in range(10) if i > 3]print(l1)

#原先操作列表

user=input('>>>:').strip()

names=['hello world','hello dream','hello %s'%(user)]

l=[]for name innames:if name.startswith('he'):

l.append(name.upper())

names=lprint(names)#列表生成式操作

user=input('>>>:').strip()

names=['hello world','hello dream','hello %s'%(user)]

names=[name.upper() for name in names ifname.startswith('hello')]print(names)

列表生成式:示例

字典生成式

info=[

['name','mogu'],

('age',18),

['sex','male']]#将列表转成字典:方法一

d={}for item ininfo:

d[item[0]]= item[1]print(d)#字典生成式 :方法二

d={item[0]:item[1] for item ininfo}print(d)

字典生成式

d={'name':'蘑菇','age':18,'sex':'male'}

d={k.upper():v for k,v ind.items()}print(d)

生成式改字典k的大小写

语法:同列表一样   用到 for循环操作时优先考虑生成式操作

八、函数的递归调用

在调用一个函数的过程中又直接或间接的调用了自身。

本质就是一个重复的过程,必须有两个明确的阶段

1、回溯:一层一层地递归调用下去,每进入一层问题的规模都应该有所减少

2、递推:递归必须有一个明确的结束条件,在满足该条件的情况下终止递归,往回一层一层地结束调用

#询问年龄,第一个人说我比第二个人大2岁,第二个人说我比第三个人大2岁,。。。第六个人说“我18岁”#age(6) = age(5) + 2#age(5) = age(4) + 2#age(4) = age(3) + 2#age(3) = age(2) + 2#age(2) = age(1) + 2#age(1) = 18

#age(n) = age(n-1) + 2 #n > 1#age(n) = 18 #n=1#

defage(n):if n == 1: #结束条件

return 18

return age(n-1) + 2 #基于上一次的结果调用自己

print(age(6))

示例1

#将一个列表中包含的值全部取出

l=[1,[2,[3,[4,[5,[6,[7,[8,[9,]]]]]]]]]deftell(l):for item inl:if type(item) islist:#item 是列表

#再次调用本身的逻辑,传入item

tell(item)else:#item是单独的元素

print(item)

tell(l)

示例2

#数字列表,数字是从小到大排列的

nums=[3,11,13,15,23,27,43,51,72,81,93,101]#算法:就是如何高效地解决某一个具体问题的方法

l1=[3,11,13,15,23,27]

l2=[23,27]

l3=[23]defbinary_search(nums,find_num):print(nums)if len(nums) ==0:print('not exists')returnmid_index=len(nums) // 2

if find_num >nums[mid_index]:#in the right

nums=nums[mid_index+1:]#重复调用本身的逻辑,传入新的nums

binary_search(nums,find_num)elif find_num

nums=nums[:mid_index]#重复调用本身的逻辑,传入新的nums

binary_search(nums,find_num)else:print('find it')

binary_search(nums,94)

函数的递归调用+二分法

九、匿名函数

匿名函数lambda:临时用一次以后不再使用了。

#格式:

defsum2(x,y):return x +yprint(sum2)

sum2=lambda x,y:x + y

wage={'I':3800,'BOSS':9999999,'friends':10000,'web celebrity':1000000}print(max(wage,key=lambda x:wage[x]))#匿名函数使用场景 最大

print(min(wage,key=lambda x:wage[x]))#最小

#按照薪资高低排序人名

print(sorted(wage,key=lambda x:wage[x])) #从小到大

print(sorted(wage,key=lambda x:wage[x],reverse=True))#翻转

十、迭代器,生成器,生成器表达式

1、迭代器

迭代器就是迭代取值的工具

迭代是一个重复的过程,但是每一次重复都是基于上一次的结果而进行。

迭代器的作用:针对没有索引的数据类型,比如(字典、集合、文件)想要迭代取出其中包含的值

python解释器提供了一种不依赖索引取值的工具

#可迭代的对象:在python中但凡内置有__iter__方法的对象都称之为可迭代对象

(字符串、列表、元组、字典、集合、文件)

str1 = 'hello'list1= ['a', 'b', 'c']

t1= ('a', 'b', 'c')

dic= {'x': 1, 'y': 2}

set1= {'m', 'n'}

f= open('a.txt', mode='rt', encoding='utf-8')

可迭代对象

#迭代器对象:#1、内置有__iter__方法,调用迭代器对象的__iter__方法得到仍然是迭代器本身#ps: 文件对象本身就是一个迭代器对象#2、内置有__next__方法

dic = {'x': 1, 'y': 2}

iter_dic= iter(dic) #iter_dic=dic.__iter__()#上面得到迭代器对象 iter_dic

print(iter_dic.__next__())print(iter_dic.__next__())#就可以调__next__方法取值

dic={'x':1,'y':2}

iter_dic=iter(dic) #调__iter__得到迭代器

whileTrue:try: #检测异常

k=next(iter_dic) #执行__next__取值

print(k)except StopIteration: #接try 的检测

break

-----------------------------------------------------------------

#上述即为 for循环的 底层原理

for循环运行机制!!

总结

迭代器的优点:

一、提供了一种能够不依赖索引的、通用的迭代取值方式

补充:for循环可以称之为迭代器循环

list1=['a','b','c']for item inlist1:print(item)

for循环的工作流程

1、调用 in 后面那个对象的__iter__方法,拿到一个迭代器对象

2、调用迭代器对象的__next__方法,拿到一个返回值赋值给变量名item

3、循环往复,直到抛出异常,for循环会自动捕捉异常结束循环

二、节省内存

迭代器的缺点:

1、针对同一个迭代器对象只能取完一次,不如按照索引或者key取值方式灵活

2、无法预测迭代器对象所包含值的个数

2、生成器

在函数内但凡出现yield 关键字,在调用函数就不会触发函数体代码的执行了,

会得到一个返回值,返回值就是一个生成器对象

而生成器对象本质就是迭代器(ps:生成器是自定义的迭代器)

deffoo():print('first')yield 1

print('second')yield 2

print('third')yield 3

print('fourth')

g=foo() #g是生成器=》就是迭代器

g.__next__()

g.__next__()

g.__next__()

上述会触发g对应的函数体代码的执行,直到碰到一个yield就暂停住,该yield后的值当做本次__next__的返回值返回

print(g.__next__())print(g.__next__())print(g.__next__())

总结yield的功能:

1、提供了一种自定义迭代器的方式

2、可以用于返回值

yield和return的区别:

相同点:都可以用于返回值,个数以及类型都没有限制

不同点:yield可以返回多次值,return只能返回一次值整个函数就结束了

3、函数暂停以及继续执行的状态是由yield保存的

def my_range(start,stop,step=1):while start < stop: #4 < 4

yield start #start = 3

start+=step #star=4#----------------------------------------------------------#range()的原理

for i in my_range(1,5): #1 3

print(i)

了解:yield关键字表达式形式的应用

defcat(name):print('橘猫[%s]准备开吃' %name)

food_list=[]whileTrue:

food=yield food_list#food=yield='鱼干'

print('橘猫[%s]吃了: %s' %(name,food))

food_list.append(food)#ct=cat('蘑菇')#强调:针对表达式形式的yield,在使用生成器时必先send(None),相当于先完成一个初始化操作

res0=next(ct) #ct.send(None)#print(res0)

#send有两个功能:#1、为当前暂停位置的yield赋值#2、与next的效果一样

ct.send('鱼干')#next(ct)#ct.send(None)

ct.send('三鹿')

res1=ct.send('鱼干')#print(res1)

res2=ct.send('牛奶')print(res2)

yield关键字表达式

3、生成器表达式

同上述列表、字典生成式一样的形式,只是两边换成了()

l=[i**2 for i in range(1,11)]print(l)###列表生成式#[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]#==================================

l1=(i**2 for i in range(1,11))print(l1)# at 0x0000000001EC05C8>#()括号生成了一个迭代器对象,只要不调用l1,其内部就没有值,调一次next方法就取出一个值

print(next(l1))

优点是:

更加节省内存

自定义迭代器的方式

十一、面向过程编程

#=============复杂的问题变得简单#注册功能:#阶段1: 接收用户输入账号与密码,完成合法性校验

deftalk():whileTrue:

username=input('请输入你的用户名:').strip()ifusername.isalpha():break

else:print('用户必须为字母')whileTrue:

password1=input('请输入你的密码:').strip()

password2=input('请再次输入你的密码:').strip()if password1 ==password2:break

else:print('两次输入的密码不一致')returnusername,password1#阶段2: 将账号密码拼成固定的格式

defregister_interface(username,password):

format_str='%s:%s\n' %(username,password)returnformat_str#阶段3: 将拼好的格式写入文件

defhandle_file(format_str,filepath):

with open(r'%s' %filepath,'at',encoding='utf-8') as f:

f.write(format_str)defregister():

user,pwd=talk()

format_str=register_interface(user,pwd)

handle_file(format_str,'user.txt')

register()

面向过程编程

#1、首先强调:面向过程编程绝对不是用函数编程这么简单,

面向过程是一种编程思路、思想,而编程思路是不依赖于具体的语言或语法的。

言外之意是即使我们不依赖于函数,也可以基于面向过程的思想编写程序

#2、定义

面向过程的核心是过程二字,过程指的是解决问题的步骤,即先干什么再干什么

基于面向过程设计程序就好比在设计一条流水线,是一种机械式的思维方式#3、优点:复杂的问题流程化,进而简单化

#4、缺点:可扩展性差,修改流水线的任意一个阶段,都会牵一发而动全身

#5、应用:扩展性要求不高的场景,典型案例如linux内核,git,httpd

#6、举例

流水线1:

用户输入用户名、密码--->用户验证--->欢迎界面

流水线2:

用户输入sql--->sql解析--->执行功能

十二、补充内置函数

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值