一、三元表达式,列表、字典、集合生成式,生成器表达式
1、三元表达式
三元表达式是python为我们提供的一种简化代码的解决方案,优雅的取代双分支if。语法如下
res = 条件成立时返回的值 if 条件 else 条件不成立时返回的值
针对下述场景
def max2(x,y):
if x > y:
return x
else:
return y
res = max2(1,2)
用三元表达式可以一行解决
x=1
y=2
res = x if x > y else y # 三元表达式
2、列表生成式
列表生成式是python为我们提供的一种简化代码的解决方案,用来快速生成列表,语法如下
案例一
l = []
for i in range(10):
l.append(i)
print(l)
用列表生成式可以一行解决
l = [i for i in range(10)]
案例二
l = []
for i in range(10):
if i > 5:
l.append(i)
print(l)
用列表生成式可以一行解决
l = [i for i in range(10) if i > 5]
案例三
names = ["lxx",'hxx',"wxx",'lili'] #如果每个人的名字后面加'_sb'
l = [name + "_sb" for name in names]
案例四
names = ["egon","lxx_sb","hxx_sb","wxx_sb"] #取有'_sb'的值
res = [name for name in names if name.endswith("sb")]
3、字典生成式
res = {i: i ** 2 for i in range(5)}
print(res) #生成字典
items = [('k1',111),('k2',222),('k3',333)]
print(dict(items))
或 print({k:v for k,v in items}) #生成字典
4、集合生成式
res = {i for i in range(5)}
print(res)
5、生成器表达式
创建一个生成器对象有两种方式,一种是调用带yield关键字的函数,另一种就是生成器表达式,与列表生成式的语法格式相同,只需要将[]换成(),即:
res = (i for i in range(3))
如果我们要读取一个大文件的字节数,应该基于生成器表达式的方式完成
with open('db.txt','rb') as f:
nums=(len(line) for line in f)
total_size=sum(nums) # 依次执行next(nums),然后累加到一起得到结果=
with open('a.txt',mode='rt',encoding='utf-8') as f:
res = f.read()
print(len(res))
res = 0
for line in f:
res += len(line)
res = sum((len(line) for line in f))
res = sum(len(line) for line in f)
print(res)
二、函数递归
1、函数递归调用
是函数嵌套调用的一种特殊形式,函数在调用时,直接或间接调用了自身,就是递归调用,本质就是一个循环的过程
#1、递归调用应该包含两个明确的阶段:回溯,递推
回溯就是从外向里一层一层递归调用下去,
回溯阶段必须要有一个明确地结束条件,每进入下一次递归时,问题的规模都应该有所减少(否则,单纯地重复调用自身是毫无意义的)
递推就是从里向外一层一层结束递归
大前提:递归调用一定要在某一层结束
2、示例
age(5) = age(4) + 10
age(4) = age(3) + 10
age(3) = age(2) + 10
age(2) = age(1) + 10
age(1) = 18
def age(n):
if n == 1:
return 18
return age(n-1) + 10
res = age(5)
print(res)
函数递归取值
nums = [1,[2,[3,[4,[5,[6,[7,]]]]]]]
def get(l):
for num in l:
if type(num) is list:
get(num)
else:
print(num)
get(nums)
python中的递归效率低且没有尾递归优化
#python中的递归
python中的递归效率低,需要在进入下一次递归时保留当前的状态,在其他语言中可以有解决方法:尾递归优化,即在函数的最后一步(而非最后一行)调用自己,尾递归优化:http://egon09.blog.51cto.com/9161406/1842475
但是python又没有尾递归,且对递归层级做了限制
#总结递归的使用:
1. 必须有一个明确的结束条件
2. 每次进入更深一层递归时,问题规模相比上次递归都应有所减少
3. 递归效率不高,递归层次过多会导致栈溢出(在计算机中,函数调用是通过栈(stack)这种数据结构实现的,每当进入一个函数调用,栈就会加一层栈帧,每当函数返回,栈就会减一层栈帧。由于栈的大小不是无限的,所以,递归调用的次数过多,会导致栈溢出)
2、二分法
想从一个按照从小到大排列的数字列表中找到指定的数字,遍历的效率太低,用二分法(算法的一种,算法是解决问题的方法)可以极大低缩小问题规模
nums = [-3,1,3,7,13,23,37,43,57,63,77,91,103] #从小到大排列
find_num = 64
def find(nums,find_num):
print(nums)
if len(nums) == 0:
print("not exists")
return
mid_index = len(nums) // 2
if find_num > nums[mid_index]:
# in the right
find(nums[mid_index+1:],find_num)
elif find_num < nums[mid_index]:
# in the left
find(nums[:mid_index], find_num)
else:
print('you got it')
find(nums,find_num)
三、匿名函数
概念
匿名就是没有名字的函数。特点:临时用一次
def func(x,y,z=1):
return x+y+z
匿名
lambda x,y,z=1:x+y+z #与函数有相同的作用域,但是匿名意味着引用计数为0,使用一次就释放,除非让其有名字
func=lambda x,y,z=1:x+y+z
func(1,2,3)
#让其有名字就没有意义
有名字的函数与匿名函数的对比
#有名函数与匿名函数的对比
有名函数:循环使用,保存了名字,通过名字就可以重复引用函数功能
匿名函数:一次性使用,随时随时定义
应用:max,min,sorted,map,reduce,filter
四、面向过程编程
#1、首先强调:面向过程编程绝对不是用函数编程这么简单,面向过程是一种编程思路、思想,而编程思路是不依赖于具体的语言或语法的。言外之意是即使我们不依赖于函数,也可以基于面向过程的思想编写程序
#2、定义
面向过程的核心是过程二字,过程指的是解决问题的步骤,即先干什么再干什么
基于面向过程设计程序就好比在设计一条流水线,是一种机械式的思维方式
#3、优点:复杂的问题流程化,进而简单化
#4、缺点:可扩展性差,修改流水线的任意一个阶段,都会牵一发而动全身
#5、应用:扩展性要求不高的场景,典型案例如linux内核,git,httpd
#6、举例
流水线1:
用户输入用户名、密码--->用户验证--->欢迎界面
流水线2:
用户输入sql--->sql解析--->执行功能