1 什么是函数? 函数就是具备某一个功能的工具, ----需要工具时,需要提前准备好,然后拿来就用且可以重复使用 所以 函数需要先定义,再使用
2 为什么要用函数?
1,代码的组织结构不清晰,可读性差 2,遇到重复的功能只能重复编写实现代码,代码冗余 3,功能需要扩展时,需要找出所有实现该功能的地方修改之,无法统一管理且维护难度极大
3 函数的分类:内置函数与自定义函数 内置函数:python解释器已经为我们定义好了的函数 自定义函数:我们自己根据需求,事先定制好的我们自己的函数,来实现某种功
4 如何自定义函数
语法 def 函数名(参数1,参数2,参数3.......): """注释""" 函数体 return 返回的值 # 函数名要能反映其意义 函数使用的原则:先定义,再调用 函数即"变量","变量"必须先定义后引用。未定义而直接引用函数,就相当于在引用一个不存在的变量名 函数的使用,必须遵循原则:先定义,后调用 ###我们在使用函数时,一定要明确区分定义阶段和调用阶段### #定义阶段 def foo(): print('from foo') bar() def bar(): print('from bar') #调用阶段 foo()
定义有参数函数,及有参函数的应用场景 有参:需要根据外部传进来的参数,才能执行相应的逻辑,比如统计长度等 def tell_tag(tag,n): #有参数 print (tag*n)
定义无参数函数,及无参函数的应用场景 无参:应用场景仅仅只是执行一些操作,比如用户交互,打印 def tell_msg(): #无参数 print ('hello world')
定义空函数,及空函数的应用场景 设计代码结构 #结论: #1,定义是无参,意味着调用时也无需传入参数 #2,定义是有参,意味着调用时则必须传入参数
函数在定义阶段: 只检测语法,不执行代码 --语法错误在函数定义阶段就会检测出来,而代码的逻辑错误只有在执行时才会知道
5 调用函数
如何调用函数 函数的调用:函数名加括号 1,先找到名字 2,根据名字调用代码
函数的返回值 无return--->None return 1个值->返回1个值 return 逗号分隔多个值 -->返回元组 什么时候该有返回值: 调用函数,经过一系列的操作,最后拿到一个明确的结果,则必须要有返回值 通常有参函数需要有返回值,输入参数,经过计算,得到一个最终的结果 什么时候不需要有返回值: 调用函数,仅仅只是执行一系列的操作,最后不需要得到什么结果,则无需有返回值 通常无参函数不需要有返回值 函数调用的三种形式 1,语句形式:foo() 2,表达式形式:3*len(’hello‘) 3,当中另外一个函数的参数:range(len(’hello‘))
函数参数的应用: 形参和实参 形参即变量名,实参即变量名,函数调用时,将值绑定到变量名上,函数调用结束,解除绑定 位置参数:按照从左到右的顺序定义的参数 位置形参:必选参数 位置实参:按照位置给形参传值
关键字参数:按照key=value的形式定义的实参 无需按照位置为形参传值 注意的问题: 1,关键字实参必须在位置实参后面 2,对同一个形参不能重复传值 默认参数:形参在定义时就已经为其赋值 可以传值也可以不传值,经常需要变的参数定义成位置形参,变化较小的参数定义成默认参数(形参) 注意的问题: 1,只在定义的时候赋值一次 2,默认参数的定义应该在位置形参右边 3,默认参数通常应该定义成不可变类型 可变长参数: 可变长指的是实参值得个数不固定 而实参有按位置和按关键字两种形式定义,针对这两种形式的可变长,形参对应有两种解决方案来完整的存放它们, 分别是 *args,**kwargs(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])
===========**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})
===========*args+**kwargs===========
def foo(x,y):
print(x,y)
def wrapper(*args,**kwargs):
print('====>')
foo(*args,**kwargs)
命名关键字参数:
* 后定义的参数,必须被传值(有默认值得除外),且必须按照关键字实参的形式传递
可以保证,传入的参数中一定包含某些关键字
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
6 高阶函数(函数对象) 函数是第一类对象,即函数可以当做数据传递 1,函数可以被引用 2,函数可以当做参数传递 3,函数的返回值可以是函数 4,函数可以当做容器类型的元素 利用这些特性,可以取代多分支的if
1 def foo():
2 print('foo')
3
4 def bar():
5 print('bar')
6
7 dic={
8 'foo':foo,
9 'bar':bar,
10 }
11 while True:
12 choice=input('>>: ').strip()
13 if choice in dic:
14 dic[choice]()
7 函数嵌套 函数的嵌套调用
1 def max(x,y): 2 return x if x > y else y 3 4 def max4(a,b,c,d): 5 res1=max(a,b) 6 res2=max(res1,c) 7 res3=max(res2,d) 8 return res3 9 print(max4(1,2,3,4))
8 作用域与名称空间 名称空间:存放名字的地方,三种空间:内置名称空间,全局名称空间,局部名称空间 存放的是名字和内存地址的对应关系
名称空间的加载顺序
python test.py #1、python解释器先启动,因而首先加载的是:内置名称空间 #2、执行test.py文件,然后以文件为基础,加载全局名称空间 #3、在执行文件的过程中如果调用函数,则临时产生局部名称空间
名字的查找顺序 局部名称空间--全局名称空间--内置名称空间 注意:在全局无法查看局部的,在局部可以查看全局的作用域:作用域即范围 -全局范围:(内置名称空间与全局名称空间属于该范围):全局存活,全局有效 -局部范围:(局部名称空间属于该范围):临时存活,局部有效 查看作用域: globals(),locas()
1 LEGB 代表名字查找顺序: locals -> enclosing function -> globals -> __builtins__ 2 locals 是函数内的名字空间,包括局部变量和形参 3 enclosing 外部嵌套函数的名字空间(闭包中常见) 4 globals 全局变量,函数定义所在模块的名字空间 5 builtins 内置模块的名字空间
闭包函数 内部函数包含对外部作用域而非全局作用域的引用
1 def index(url): 2 def get(): 3 return urlopen(url).read() 4 return get
1 #闭包的意义:返回的函数对象,不仅仅是一个函数对象,在该函数外还包裹了一层作用域,这使得,该函数无论在何处调用,优先使用自己外层包裹的作用域
2 #应用领域:延迟计算(原来我们是传参,现在我们是包起来)
3 from urllib.request import urlopen
4
5 def index(url):
6 def get():
7 return urlopen(url).read()
8 return get
9
10 baidu=index('http://www.baidu.com')
11 print(baidu().decode('utf-8'))
9 装饰器 为什么要用装饰器? 开放封闭原则:对修改封闭,对扩展开放 什么是装饰器? 装饰器本身是任意可调用对象,被装饰着也可以是任意可调用对象 装饰器的原则: 1,不修改被装饰对象的源代码 2,不修改被装饰对象的调用方式 3,在遵循1和2的前提下,为被装饰对象添加新功能 装饰器的基本语法:(任何装饰器都可以套用)
def foo(func):
def wrappers(*args,**kwargs):
res = func()
return res
return wrappers
无参装饰器
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 res
return wrapper
@timmer
def foo():
time.sleep(3)
print('from foo')
foo()
有参装饰器
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 res
elif driver == 'ldap':
print('ldap')
return wrapper
return auth2
@auth(driver='file')
def foo(name):
print(name)
foo('egon')
10 迭代器与生成器及协程函数 1,迭代器就是迭代的工具,迭代就是一个重复的过程,每次重复就是一次迭代,并且每次迭代的结果都是下一次迭代的初始值 2,为什么要有迭代器? 对于没有索引的数据类型,迭代器提供了一种不依赖索引的迭代方式 3,可迭代对象 内置有__iter__方法的对象,即obj.__iter__ 可迭代对象:字符串,列表,元组,字典,集合,文件 4,迭代器对象 可迭代对象执行__iter__得到的结果就是迭代器对象 迭代器对象指的是既内置有__iter__又内置有__next__方法的对象 文件类型是迭代器对象

dic={'a':1,'b':2,'c':3}
iter_dic=dic.__iter__() #可迭代对象执行__iter__方法得到的结果就是迭代器对象
#迭代器对象内置有__iter__方法和__next__方法
iter_dic.__iter__() id iter_dic # 迭代器执行__iter__()得到的仍然是迭代器本身
print(iter_dic.__next__())
print(iter_dic.__next__())
print(iter_dic.__next__()) #等同于next(iter_dic)
#迭代对象有几个值就需要执行几次,直到没有值可取
print(iter_dic.__next__()) #抛出异常StopIteration,标志迭代对象的值已经全部取出

基于for循环,我们可以实现不依赖索引取值
1 dic={'a':1,'b':2,'c':3}
2 for k in dic:
3 print(dic[k]
for循环工作原理
1,执行in后的对象__iter__()方法,得到一个迭代器对象
2,执行__next__方法,将得到的值赋值变量,然后执行循环体代码
3,重复过程2,直到捕捉到异常StopIteration
迭代器的优缺点:
优点:提供了一种不依赖索引的迭代方式
缺点:无法获取长度
只能一直往前取,无法往后取生成器 函数内包含有yield关键字 再调用函数,就不会执行函数体代码,拿到的返回值就是一个生成器对象 注意::生成器本质就是迭代器,也就是说迭代器的用法就是生成器的用法 11 三元运算,列表解析、生成器表达式 三元运算: 格式: 为真时的结果 if 判断条件 else 为假时的结果 例子: print(1 if 5>3 else 0) 列表解析(列表推导式) 基本形式:[表达式 for 参数 in 可迭代对象] 或者 [表达式 for 参数 in 可迭代对象 if 条件] 实例

1 l = []
2 for i in range(100):
3 l.append('egg%s' %i)
4 print i
5
6 #不带if条件
7 l = ['agg%s' %i for i in range(100) ]
8
9 #带if条件
10 l = ['agg%s' %i for i in range(100) if i>10]
生成器表达式
将列表推导式的中括号改为小括号即可

l = ('egg%s' %i for i in range(100) if i>10)
print(next(l))
注意:得到的结果为迭代器
12 函数的递归调用 递归调用是函数嵌套调用的一种特殊形式,函数在调用时,直接或间接调用了自身就是递归调用 递归的两个阶段: 回溯:往前搜索,以达到目标 注意:一定要在满足某个条件的情况下结束回溯,否则就是无限递归 递推:往回推

1 def age(n): 2 if n == 1: 3 return 1 4 else: 5 return age(n-1)+2 6 7 print(age(5))
递归总结: 递归必须有一个明确的结束条件 每次进入更深一层递归时,问题规模相比上次递归都应有所减少 python没有尾递归优化,但是设置了最大递归层数
13 内置函数 内置函数就是python解释器定义好的函数
reduce(func,iterable) 从可迭代系列中循环取值,参与第一个函数参数的计算,最后得到一个结果
reduce(lambda x, y: x+y, [1,2,3,4,5]) # 使用 lambda 匿名函数
bytes()将unicode指定编码后转化为bytes类型
chr()返回值是传入整数对应的ascii字符
divmod()将除数和余数的运算结果结合起来,返回一个包含商和余数的元组(a//b,a%b)
>>>divmod(7, 2) (3, 1) >>> divmod(8, 2) (4, 0) >>> divmod(1+2j,1+0.5j) ((1+0j), 1.5j)
enumerate()将一个可遍历的数据对象组合为一个索引序列,同时列出数据个数据下标,一般用在for循环
>>>seasons = ['Spring', 'Summer', 'Fall', 'Winter'] >>> list(enumerate(seasons)) [(0, 'Spring'), (1, 'Summer'), (2, 'Fall'), (3, 'Winter')]
eval()执行一个字符串表达式,并返回表达式的值
>>>x = 7
>>> eval( '3 * x' )
21
>>> eval('pow(2,2)')
4
>>> eval('2 + 2')
4
>>> n=81
>>> eval("n + 4")
85
filter(func,iterable)函数用于过滤序列,过滤掉不符合条件的元素,返回由符合条件元素组成的新列表
import math
def is_sqr(x):
return math.sqrt(x) % 1 == 0
newlist = filter(is_sqr, range(1, 101))
print(newlist)
id() 返回参数的内存地址序号
input()获取输入
iter(object)生成迭代器
len()返回参数长度
map(func,iterable)第一个参数 function 以参数序列中的每一个元素调用 function 函数,返回包含每次 function 函数返回值的新列表。
map(lambda x: x ** 2, [1, 2, 3, 4, 5]) # 使用 lambda 匿名函数 [1, 4, 9, 16, 25] >>> map(lambda x, y: x + y, [1, 3, 5, 7, 9], [2, 4, 6, 8, 10]) [3, 7, 11, 15, 19]
max()返回给定参数的最大值,参数可以是系列
egon male 18 3000
alex male 38 30000
wupeiqi female 28 20000
yuanhao female 28 10000
with open('db.txt') as f:
items=(line.split() for line in f)
info=[{'name':name,'sex':sex,'age':age,'salary':salary} \
for name,sex,age,salary in items]
print(max(info,key=lambda dic:dic['salary']))
max(iterable, key, default) 求迭代器的最大值,其中iterable 为迭代器,max会for i in … 遍历一遍这个迭代器,然后将迭代器的每一个返回值当做参数传给key=func 中的func(一般用lambda表达式定义) ,然后将func的执行结果传给key,然后以key为标准进行大小的判断
min()返回给定参数的最小值,参数可以是系列
ord()返回给定参数的十进制数
>>>ord('a')
97
>>> ord('b')
98
>>> ord('c')
99
sorted()对所有可迭代的对象进行排序操作。
sort 与 sorted 区别: sort 是应用在 list 上的方法,sorted 可以对所有可迭代的对象进行排序操作。 list 的 sort 方法返回的是对已经存在的列表进行操作,而内建函数 sorted 方法返回的是一个新的 list,而不是在原来的基础上进行的操作。
iterable -- 可迭代对象。 cmp -- 比较的函数,这个具有两个参数,参数的值都是从可迭代对象中取出,此函数必须遵守的规则为,大于则返回1,小于则返回-1,等于则返回0。 key -- 主要是用来进行比较的元素,只有一个参数,具体的函数的参数就是取自于可迭代对象中,指定可迭代对象中的一个元素来进行排序。 reverse -- 排序规则,reverse = True 降序 , reverse = False 升序(默认)。
>>>a = [5,7,6,3,4,1,2]
>>> b = sorted(a) # 保留原列表
>>> a
[5, 7, 6, 3, 4, 1, 2]
>>> b
[1, 2, 3, 4, 5, 6, 7]
>>> L=[('b',2),('a',1),('c',3),('d',4)]
>>> sorted(L, cmp=lambda x,y:cmp(x[1],y[1])) # 利用cmp函数
[('a', 1), ('b', 2), ('c', 3), ('d', 4)]
>>> sorted(L, key=lambda x:x[1]) # 利用key
[('a', 1), ('b', 2), ('c', 3), ('d', 4)]
>>> students = [('john', 'A', 15), ('jane', 'B', 12), ('dave', 'B', 10)]
>>> sorted(students, key=lambda s: s[2]) # 按年龄排序
[('dave', 'B', 10), ('jane', 'B', 12), ('john', 'A', 15)]
>>> sorted(students, key=lambda s: s[2], reverse=True) # 按降序
[('john', 'A', 15), ('jane', 'B', 12), ('dave', 'B', 10)]
>>>
14 面向过程编程

#1、首先强调:面向过程编程绝对不是用函数编程这么简单,面向过程是一种编程思路、思想,而编程思路是不依赖于具体的语言或语法的。言外之意是即使我们不依赖于函数,也可以基于面向过程的思想编写程序 #2、定义 面向过程的核心是过程二字,过程指的是解决问题的步骤,即先干什么再干什么 基于面向过程设计程序就好比在设计一条流水线,是一种机械式的思维方式 #3、优点:复杂的问题流程化,进而简单化 #4、缺点:可扩展性差,修改流水线的任意一个阶段,都会牵一发而动全身 #5、应用:扩展性要求不高的场景,典型案例如linux内核,git,httpd #6、举例 流水线1: 用户输入用户名、密码--->用户验证--->欢迎界面 流水线2: 用户输入sql--->sql解析--->执行功能
来源:https://www.cnblogs.com/guodengjian/p/8710617.html
