一函数基础
1.1 函数分类
a.内置函数:为了方便我们的开发,针对一些简单的功能,python解释器已经为我们定义好了的函数即内置函数。对于内置函数,我们可以拿来就用而无需事先定义,如len(),sum(),max()
b.自定义函数:很明显内置函数所能提供的功能是有限的,这就需要我们自己根据需求,事先定制好我们自己的函数来实现某种功能,以后,在遇到应用场景时,调用自定义的函数即可。
1.2 定义函数
#语法
def 函数名(参数1,参数2,参数3,...):
'''注释'''
函数体
return 返回的值
#1、无参:应用场景仅仅只是执行一些操作,比如与用户交互,打印
#2、有参:需要根据外部传进来的参数,才能执行相应的逻辑,比如统计长度,求最大值最小值
#3、空函数:设计代码结构
1.3 调用函数
1 语句形式:foo()
2 表达式形式:3*len('hello')
3 当中另外一个函数的参数:range(len('hello'))
函数练习:
'''
1、写函数,,用户传入修改的文件名,与要修改的内容,执行函数,完成批了修改操作
'''
import os
def foo(x,y,z):
'''
:param x: 文件名
:param y: 修改的内容
:return:
'''
with open(x,'r')as f_read,open('tmp.txt','w')as f_write:
for line in f_read:
data=line.replace(y,z)
f_write.write(data)
os.remove(x)
os.rename('tmp.txt',x)
foo('a.txt','ha','yi')
'''
2、写函数,计算传入字符串中【数字】、【字母】、【空格] 以及 【其他】的个数
'''
def foo(a):
n_num=0
n_word=0
n_space=0
n_other=0
for word in a:
if word.isdigit():n_num+=1
elif word.isalpha():n_word+=1
elif word==' ':n_space+=1
else:n_other+=1
print(word)
print(n_num,n_word,n_space,n_other)
foo('123 wef wd23!2')
'''
3、写函数,判断用户传入的对象(字符串、列表、元组)长度是否大于5。
'''
def func(a):
if len(a)>5:return True
else:return False
print(func('23rsdsd2'))
'''
4、写函数,检查传入列表的长度,如果大于2,那么仅保留前两个长度的内容,并将新内容返回给调用者。
'''
def func(a):
while True:
if type(a)!=list:
print('list please!')
else:break
if len(a)>=2:
data=a[0:2]
else:data=a
print(data)
func([12,])
'''
5、写函数,检查获取传入列表或元组对象的所有奇数位索引对应的元素,并将其作为新列表返回给调用者。
'''
def func(a):
l=[]
for x in a:
if a.index(x)%2!=0:
l.append(x)
return l
print(func(['qef','123','asdf','dcsc','csdcd']))
'''
6、写函数,检查字典的每一个value的长度,如果大于2,那么仅保留前两个长度的内容,并将新内容返回给调用者。
dic = {"k1": "v1v1", "k2": [11,22,33,44]}
PS:字典中的value只能是字符串或列表
'''
def func(dic):
for key in dic:
if len(dic[key])>=2:
new_value=dic[key][0:2]
dic.pop(key)
dic[key]=new_value
return dic
print(func( {"k1": "v1v1", "k2": [11,22,33,44]}))
1.4 函数对象
#1 可以被引用 #2 可以当作参数传递 #3 返回值可以是函数 #3 可以当作容器类型的元素
#取代多分支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.5 函数嵌套
def max1(x,y):
return x if x>y else y
def max4(a,b,c,d):
res1=max1(a,b)
res2=max1(c,d)
res=max1(res1,res2)
return res
print(max4(1,2,3,4))
# 函数的嵌套定义
def f1():
def f2():
def f3():
print('from f3')
f3()
f2()
f1()
1.6 名称空间和作用域
名称空间:存放名字的地方。局部名称空间,全局名称空间,内置名称空间
名字的查找顺序:局部名称空间--->全局名称空间-->内置名称空间
名称空间的加载顺序:
python test.py #1、python解释器先启动,因而首先加载的是:内置名称空间 #2、执行test.py文件,然后以文件为基础,加载全局名称空间 #3、在执行文件的过程中如果调用函数,则临时产生局部名称空间
作用域即范围
- 全局范围(内置名称空间与全局名称空间属于该范围):全局存活,全局有效
- 局部范围(局部名称空间属于该范围):临时存活,局部有效
查看作用域:globals(),locals()
LEGB 代表名字查找顺序: locals -> enclosing function -> globals -> __builtins__
locals 是函数内的名字空间,包括局部变量和形参
enclosing 外部嵌套函数的名字空间(闭包中常见)
globals 全局变量,函数定义所在模块的名字空间
builtins 内置模块的名字空间
二.闭包函数和装饰器
2.1 闭包函数
定义在函数内部的函数,特点是,包含对外部作用域而不是对全局作用域名字的引用。
from urllib.request import urlopen
def get(url):
def inner():
return urlopen(url).read()
return inner
baidu=get('http://www.baidu.com')
baidu()闭包的意义:返回的函数对象,不仅仅是一个函数对象,在该函数外还包裹了一层作用域,这使得,该函数无论在何处调用,优先使用自己外层包裹的作用域
2.2 装饰器
1.为什么要用装饰器:开放封闭原则,对扩展是开放的,对修改是封闭的
2.什么是装饰器
-用来装饰它人,装饰器本身可以是任意可调用对象,被装饰器的对象也可以是任意可调用对象。
-遵循的原则:1.不修改被装饰对象的源代码 2.不修改被装饰对象的调用方式
-目标是:在遵循原则1和2的前提,为被装饰对象添加新功能
从普通的函数逐渐加入装饰器的过程(不修改原函数代码,不修改调用方式):

def get_up():
'''描述睡觉起床过程'''
print('睡他妈的觉')
time.sleep(random.randint(2,4))
print('起他妈的床')
def wash():
'''描述洗漱过程'''
print('洗他妈的脸')
time.sleep(random.randint(1,3))
print('刷他妈的牙')

def count_time(fun):
def wraper():
start_time=time.time()
fun()
fin_time=time.time()
print(fin_time-start_time)
return wraper
def get_up():
'''描述睡觉起床过程'''
print('睡他妈的觉')
time.sleep(random.randint(2,4))
print('起他妈的床')
def wash():
'''描述洗漱过程'''
print('洗他妈的脸')
time.sleep(random.randint(1,3))
print('刷他妈的牙')
get_up=count_time(get_up) #也就是返回的wraper ------fun=get_up
get_up()

import time,random
def count_time(fun):
def wraper():
start_time=time.time()
fun()
fin_time=time.time()
print(fin_time-start_time)
return wraper
#get_up=count_time(get_up) #也就是返回的wraper ------fun=get_up
@count_time
def get_up():
'''描述睡觉起床过程'''
print('睡他妈的觉')
time.sleep(random.randint(2,4))
print('起他妈的床')
@count_time
def wash():
'''描述洗漱过程'''
print('洗他妈的脸')
time.sleep(random.randint(1,3))
print('刷他妈的牙')
get_up()
wash()

import time,random
def count_time(fun):
def wraper(*args,**kwargs):
start_time=time.time()
fun(*args,**kwargs)
fin_time=time.time()
print(fin_time-start_time)
return wraper
#get_up=count_time(get_up) #也就是返回的wraper ------fun=get_up
@count_time
def get_up(name):
'''描述睡觉起床过程'''
print('睡他妈的觉%s'%name)
time.sleep(random.randint(2,4))
print('起他妈的床%s'%name)
@count_time
def wash():
'''描述洗漱过程'''
print('洗他妈的脸')
time.sleep(random.randint(1,3))
print('刷他妈的牙')
get_up('hantao')
wash()

import time,random
def count_time(fun):
def wraper(*args,**kwargs):
start_time=time.time()
res=fun(*args,**kwargs)
fin_time=time.time()
print(fin_time-start_time)
return res
return wraper
#get_up=count_time(get_up) #也就是返回的wraper ------fun=get_up
@count_time
def get_up(name):
'''描述睡觉起床过程'''
print('睡他妈的觉%s'%name)
time.sleep(random.randint(2,4))
print('起他妈的床%s'%name)
return '开心的一天开始了'
@count_time
def wash():
'''描述洗漱过程'''
print('洗他妈的脸')
time.sleep(random.randint(1,3))
print('刷他妈的牙')
res=get_up('hantao')
wash()
print(res)

import time
def index():
time.sleep(2)
print('welcome to index page!')
def timer(func):
def inner():
start_time=time.time()
func()
stop_time=time.time()
print(stop_time-start_time)
return inner
index=timer(index)
index()

def timer(func):
def inner():
start_time=time.time()
func()
stop_time=time.time()
print(stop_time-start_time)
return inner
@timer
def index():
time.sleep(2)
print('welcome to index page!')
index()
#无参装饰器import time
from functools import wraps
def timmer(func):
@wraps(func)
def inner(*args,**kwargs):
start_time=time.time()
res=func(*args,**kwargs)
stop_time=time.time()
print('run time is :%s'%(stop_time-start_time))
return res
return inner
@timmer
def index():
time.sleep(2)
print('welcom to index!')
return 'index'
@timmer
def home(name):
time.sleep(3)
print('welcome %s to home'%name)
return 'home'
index()
home('hantao')
print(index())
print(home('hantao'))
#有参装饰器
import time
current_status={'user':None,'status':False}
def auth(egine='file'):
def wrapper(func):
def inner(*args,**kwargs):
if current_status['user'] and current_status['status']:
res=func(*args,**kwargs)
return res
if egine=='file':
name=input('username>>:').strip()
pwd=input('password>>:').strip()
if name=='hantao'and pwd=='123':
print('login successful!')
current_status['user']=name
current_status['status']=True
res=func(*args,**kwargs)
return res
elif egine=='mysql':
print('mysql')
else:pass
return inner
return wrapper
@auth(egine='file') #@wrapper #index=wrapper(index)
def index():
time.sleep(2)
print('welcom to index!')
return 'index'
index()

'''
编写装饰器,为多个函数加上认证的功能(用户的账号密码来源于文件),要求登录成功一次,后续的函数都无需再输入用户名和密码
'''
from functools import wraps
auth_status={'user':None,}
def auth(engine='file'):
def wrapper(func):
@wraps(func)
def inner(*args,**kwargs):
if engine=='file':
with open('aaa')as read_f:
userinfo=eval(read_f.read())
else:
pass
while True:
if auth_status.get('user'):break
username=input('username:').strip()
password=input('password:').strip()
with open('aaa')as read_f:
if username == userinfo.get('name') and password==userinfo.get('password'):break
res=func(*args,**kwargs)
return res
return inner
return wrapper
@auth(engine='file')
def index(x):
print(x)
index('hantao')

#编写装饰器,为多个函数加上认证功能,要求登录成功一次,在超时时间内无需重复登录,超过了超时时间,则必须重新登录
from functools import wraps
import time
auth_status={'user':None,'auth_time':None}
def auth(engine='file'):
def wrapper(func):
@wraps(func)
def inner(*args,**kwargs):
with open('aaa')as read_f:
userinfo=eval(read_f.read())
while True:
if auth_status.get('user') and time.time()-auth_status['auth_time']<10:break
username=input('username:').strip()
password=input('password:').strip()
if username == userinfo.get('name') and password==userinfo.get('password'):
auth_status['user']=username
auth_status['auth_time']=time.time()
break
res=func(*args,**kwargs)
return res
return inner
return wrapper
@auth(engine='file')
def index1(x):
time.sleep(3)
print(x)
time.sleep(8)
@auth(engine='file')
def index2(x):
print(x)
index1('hantao')
index2('hantao')
三.迭代器和生成器
3.1 迭代器
1.什么叫迭代:迭代是一个重复过程,每次重复都是基于上一次的结果来的
2.为什么用迭代器?
-对于序列类型:字符串,列表,元祖,可以基于索引的迭代取值方式,而对于没有索引的类型,入字典、集合、文件,这种方式不适用,于是我们必须找出一种能不依赖与索引的取值方式,这就是迭代器。
3.可迭代对象:只要对象内置有__iter__方法,obj.__iter__(字符串,列表,元祖,字典,集合,文件)
4.迭代器对象:对象既内置有__iter__方法,又内置有__next__,如文件对象
注意:可迭代对象不一定是迭代器对象,而迭代器对象一定是可迭代的对象
list=[1,2,3,4] #可迭代对象 list_item=list.__item__() #一个迭代器对象 list_item.__next__() #相当于next(list__item) 不依赖所有取值
#for循环就是将被循环对象执行__item__()方法,进行next()操作,进行取值
dic={'a':1,'b':2,'c':3}
iter_dic=dic.__iter__()
while True:
try:
print(next(iter_dic))
except StopIteration:
break
迭代器的优缺点:
-优点:
提供了一种统一的迭代取值方式,该方式不再依赖于索引
更节省内存(迭代器只是一个内存地址连接到文件,next()取值到内存)
-缺点:
无法统计长度
一次性的,只能往后走,不能往后退,无法获取指定位置的值

from collections import Iterable,Iterator print(isinstance([1,2,3],Iterable)) print(isinstance([1,2,3],Iterator))
3.2 生成器
'''
定义:只要函数内部出现yield关键字,那么再调用该函数,将不会立即执行函数体代码,会得到一个结果
该结果就是生成器对象
'''
def fun():
print('first')
yield 1
print('second')
yield 2
print('third')
yield 3
g=fun()**********************************************************************************
#生成器本质就是迭代器'''next() 在生成器的实质是: 1.让函数继续运行,直到运行到yield停止。 2.将yield的值返回到next()'''print(next(g))print(next(g))
for i in g:
print(i)*********************************************************************************
'''
yield的功能:
-为我们提供了一种自定义迭代器的方式
-对比return,可以返回多次值,挂起函数的运行状态
'''**********************************************************************************
#利用生成器实现range()方法
def my_range(start,stop,step=1):
while start<stop:
yield start
start+=step
g=my_range(1,5)
print(next(g))
print(next(g))
print(next(g))
for i in my_range(1,1342341,step=2):
print(i)

import time
def tail(filepath):
with open(filepath,'rb')as read_f:
read_f.seek(0,2)
while True:
read_line=read_f.readline()
if read_line:
yield read_line.decode('utf-8')
else:
time.sleep(0.2)
def grep(pattern,lines):
lines=tail('access.log')
for line in lines:
if pattern in line:
print(line,end='')
grep('404',tail('access.log'))
#协程函数
#yield的表达式形式用法
def eat(name):
food_list=[]
print('%s开始吃了'%(name))
while True:
food=yield food_list
print('%s正在吃%s'%(name,food))
food_list.append(food)
g_eat=eat('喵')
'''
send的作用:
1.next()的作用
2.向yield传值
3.要注意的是第一次要先send(None) == next()
'''
print(g_eat.send(None))
print(g_eat.send('猫粮'))
print(g_eat.send('小鱼干'))
print(g_eat.send('猫罐头'))
g_eat.close()
print(g_eat.send('狗粮'))
四.面向过程编程
定义:面向过程的核心是过程二字,过程指的是解决问题的步骤,即先干什么再干什么 基于面向过程设计程序就好比在设计一条流水线,是一种机械式的思维方式
优点:复杂的问题流程化,进而简单化
缺点:可扩展性差
五.三元表达式,列表推导式,生成器表达式
5.1 三元表达式
name=input('>>:')
if name == 'hantao':
print('sb')
else:
print('nb')
name=input('>>:')
print('sb' if name=='hantao' else 'nb')
5.2 列表推导式
#语法
[expression for item1 in iterable1 if condition1
for item2 in iterable2 if condition2
...
for itemN in iterableN if conditionN
#相当于
res=[]
for item1 in iterable1:
if condition1:
for item2 in iterable2:
if condition2
...
for itemN in iterableN:
if conditionN:
res.append(expression)
egg_list=[]
for i in range(10):
res='egg%s'%i
egg_list.append(res)
print(egg_list)
l=['egg%s'%i for i in range(10) if i >=3]
print(l)
names=['egon','alex_sb','wupeiqi','yuanhao']
names=[name.upper() for name in names if not name.endswith('sb')]
print(names)
5.3 生成器表达式
#把列表推导式的[]换成()就是生成器表达式
l=('hantao%s'%i for i in range(10) if i>=3)
print(l)
print(next(l))
print(next(l))
print(next(l))
#优点:省内存,一次只产生一个值在内存中
六. 函数递归与二分法
#函数递归调用:在调用一个函数的过程中直接或间接的调用该函数本身,称之为函数的递归调用
import sys
sys.setrecursionlimit(3000)
count=1
def func1():
global count
print('func1',count)
count+=1
func1()
func1()
#递归分为两个重要的阶段:递推+回溯
def age(n):
if n==1:
return 18
return age(n-1)+2
res=age(12)
print(res)
#总结递归调用
#1:进入下一次递归时,问题的规模必须降低
#2:递归调用必须要有一个明确的约束条件
#3:在python中没有尾递归优化,递归调用的效率就是不高
l=[1,2,[3,4,[5,6,[7,8]]]]
def func(l):
for i in l:
if isinstance(i,list):
func(i)
else:
print(i)
func(l)
#二分法
l=[1,2,4,8,11,15,19,23,38,80,123,234,345,456,567,678,789] #从小到大排列的数字列表
def get(num,l):
print(l)
if len(l)>0:
mid=len(l)//2
if num>l[mid]:
#in right
l=l[mid+1:]
elif num<l[mid]:
#in left
l=l[:mid]
else:
print('find it')
return
get(num, l)
else:
print('not exists')
get(68,l)

l=[1,2,4,6,9]
def search(num,l,start=0,stop=len(l)-1):
if start <= stop:
mid=start+(stop-start)//2
if num > l[mid]:
start=mid+1
elif num< l[mid]:
stop=mid-1
else:
print(mid)
return
search(num,l,start,stop)
else:
print('meiyou')
search(6,l)
七.匿名函数lambda
7.1 语法
#匿名函数没有绑定名字的函数,没有绑定名字意味着只能用一次就会被回收
#所以匿名函数的应用场景就是,某个功能只用一次就结束了
def f1(n):
res=n**2
return res
lambda n:n**2
7.2 匿名函数和一些内置函数的配合使用
#lambda和max配合使用
#求最高工资
salary={'hantao':1000,
'mayun':500,
'xi':30}
res=max(salary,key=lambda k:salary[k]) #key传入函数进行比较规则制定
print(res)
#与min()函数用法相同
#lambda和sorted配合使用
salary={'hantao':1000,
'mayun':500,
'xi':30}
print(sorted(salary,key=lambda k:salary[k],reverse=True))
#map 映射
l1=['hantao','mayun','xjp']
print(list(map(lambda x:x+'_主席',l1)))
#reduce 进行处理
from functools import reduce
print(reduce(lambda x,y:x+y,range(101)))
#filter 过滤
l2=['hantao主席','mayun主席','xjp']
print(list(filter(lambda name:name.endswith('主席'),l2)))
来源:https://www.cnblogs.com/hantaozi430/p/7602957.html
