函数
1. 生成式
列表生成式即List Comprehensions,是Python内置的非常简单却强大的可以用来创建list的生成式。
#需求:生成一个1~10的整数列表
list1 = list(range(1,11))
print(list1) #[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
#需求:生成列表:[1*1, 2*2, 3*3, 4*4, 5*5, 6*6, 7*7, 8*8, 9*9, 10*10]
#列表生成式:[]
#写下面的列表生成式的时候,需要生成的元素x*x放到最前面,后面跟的就是for-in循环
list3 = [x * x for x in range(1,11)]
print(list3)
#生成式公式:[exp for iter_var in iterable] 其中exp是个表达式,会用到循环变量iter_var,每循环一次就会执行一次exp,生成一个元素,添加到列表.等价:
'''
l = []
for iter_var in iterable:
l.append(exp)
'''
#升级需求:生成偶数的平方的列表
list4 = [x * x for x in range(1,11) if x % 2 == 0]
print(list4)
#可以在列表生成式中使用两层循环
suit = ['♥','♦','♣','♠']
face = ['A','2','3','4','5','6','7','8','9','10','J','Q','K']
poke = [(x,y) for x in suit for y in face]
#字典生成式
#列表生成式可以使用两个变量,实现字典的键值交换
d = {"X":"A","Y":"B","Z":"C"}
list5 = {v:k for k,v in d.items()}
print(list5)
#集合生成式
print({x for x in range(10)})
#练习:
1.将一个列表中所有的字符串变成小写
l = ["Hello","World","IBM","Apple"]
如果是这样的列表呢
l = ["Hello","World",10,"IBM","Apple"]
2.生成器
如果列表元素可以按照某种算法推算出来,那我们是否可以在循环的过程中不断推算出后续的元素呢?这样就不必创建完整的list,从而节省大量的空间。在Python中,这种一边循环一边计算的机制,称为生成器(Generator)。
- 延迟计算、惰性求值
- 节省内存,高效
生成器(Generator) 生成器会产生一个对象,而不是一个列表
2.1 yield表达式
#通过函数和yield关键字生成
#使用了 yield 的函数被称为生成器(generator)
#yield语句一次返回一个结果,在每个结果中间,挂起函数的状态,以便下次从它离开的地方继续执行
def test(n):
for i in range(1,n + 1):
yield i
#print(i)
#得到生成器
result = test(10)
print(result)
#生成器只能遍历一次, 所以下面不会有任何输出
for x in result:
print(x)
#可以这样遍历
for x in test(10):
print(x)
#一般不通过这种方式遍历
print(next(result))
2.2生成器表达式
生成器【Generator】生成器会产生一个可迭代对象,而不是一个列表。生成器表达式很类似列表生成式:
(表达式 for var in 可迭代对象)
#将列表生成式中的[]替换成()
ge = (x for x in range(1,6))
print(ge,type(ge))
#生成器需要通过next()方法获取数据,调用一次则返回一个数据
print(next(ge))
print(next(ge))
print(next(ge))
print(next(ge))
print(next(ge))
#注意:如果通过next函数获取生成器中的数据,当数据取完之后,
#将不能再调用next函数,否则出现StopIteration
#print(next(ge)) #StopIteration
#生成器主要通过for-in的方式进行遍历
for x in ge:
print(x,end=' ')
3.迭代器
3.1 迭代对象
可以直接作用于for-in循环的数据类型都被称为可迭代对象(Iterable),可以使用isinstance()判断一个对象是否是可迭代对象,可以直接作用于for-in循环的数据类型:
- 数据结构:list、set、tuple、dict、string
- generator【生成器】【(),函数结合yield】
#引入 from collection import Iterable
from collections import Iterable
print(isinstance("",Iterable))#True
print(isinstance({},Iterable))#True
print(isinstance((),Iterable))#True
print(isinstance(1,Iterable))#False
3.2 迭代器
迭代器不但可以作用于for-in循环,还可以使用next()函数将其中的元素获取出来,当获取完最后一个元素之后,当再次调用next方法,则会出现StopIteration错误,表示无法继续返回一个值。可以使用isinstance()判断一个对象是否是迭代器。迭代器的类型是Iterator
from collections import Iterator,Iterable
print(isinstance([],Iterator)) #False
print(isinstance((),Iterator)) #False
print(isinstance({},Iterator)) #False
print(isinstance("",Iterator)) #False
print(isinstance((x for x in range(0,6)),Iterator)) #True 生成器是迭代器
print(isinstance((x for x in range(0,6)),Iterable)) #True 生成器也是迭代对象
结论:list、set、tuple、dict、string是可迭代对象,但是,不是迭代器,只有生成器才是迭代器
3.3 将迭代对象转换为迭代器
迭代器一定是可迭代对象,但是,可迭代对象不一定是迭代器
iter():将可迭代对象转化为迭代器【主要针对list、set、tuple、dict、string】
print(isinstance(iter([]),Iterator)) #True
print(isinstance(iter(()),Iterator)) #True
print(isinstance(iter({}),Iterator)) #True
print(isinstance(iter(""),Iterator)) #True
l2 = iter(l1) #将列表转换为迭代器
print(next(l2)) #使用next获取迭代器中的元素
while True:
try:
print(next(l2)) #可能出问题的代码放到try块中
except StopIteration: #捕获异常
break #终止循环
4 装饰器(重点,难点)
软件开发中有一条非常重要的规则就是:对修改封闭,对扩展开放。
对于一个现有的函数,如果想要增强此函数的功能,但是不允许修改此函数源代码的时候,使用装饰器来解决这个问题
-
本质:就是一个闭包,还是一个返回函数的高阶函数
-
好处:就是在不用修改原函数代码的前提下给函数增加新的功能
###4.1 装饰器写法
#被修饰的函数
def say_hello(name):
print('我就是人见人爱,花见花开的%s'%name)
# 参数是被修饰函数
def wrapper(func): #1.定义装饰器
def inner(name): #2.定义闭包 在闭包中增加功能
print('-' * 50)
func(name) #3.调用原函数实现原来的功能
print('*' * 50)
return inner #4.返回增强功能的函数
say_hello = wrapper(say_hello) #5.获取增强功能的函数
say_hello('风流小王子') #6. 调用增强函数,实现功能
###4.2使用@语法糖将装饰器应用到指定函数上,简化使用
#用法:在需要被装饰的函数前面加上: @装饰器的名字 【外层函数的名字】
def wrapper(func):
def inner(age1):
#增加的功能
if age1 < 0:
age1 = 0
#调用原函数
func(age1)
return inner
@wrapper #相当于 getAge = wrapper(getage)
def getAge(age):
print(age)
getAge(18) #调用增强的函数
注意:使用@的时候,如果装饰器和需要被装饰的函数在同一个.py文件中的时候,装饰器一定要出现在被装饰函数的前面【Python中的代码是从上往下依次执行的】
4.3 带有不定长参数的装饰器
同一个装饰器可以应用于多个函数
def wrapper(func):
def inner(*tup,**kw): #变长参数
func(*tup,**kw)
print('-'*50)
return inner
@wrapper
def test1(a,b):
print(a,b)
test1(1,2)
@wrapper
def test1(a):
print(a)
4.4 多个装饰器作用在一个函数上(不重要)
#多个装饰器同时作用于一个函数的时候,要注意一下装饰器执行顺序
def wrapper1(func):
print("wrapper1~~~~外部函数")
def inner(a,b):
print('wrapper1-----内部函数')
func(a,b)
return inner
def wrapper2(func):
print("wrapper2~~~~外部函数")
def inner(a, b):
print("wrapper2~~~~内部函数")
func(a, b)
return inner
@wrapper1
@wrapper2
def text(num1,num2):
print(num1 + num2)
text(10,20)
5.递归函数
###5.1 嵌套调用
在函数A中可以调用函数B,在函数B中可以调用函数C,这种调用方式称为函数的嵌套调用。
5.2 递归调用
一个函数直接或间接的调用自己则称为递归调用。
def fac(n):
if n ==0: #递归终止条件,如果n为0,则结束递归调用,返回
return 1
else:
tmp = fac(n-1) #调用自己计算n-1的阶乘
return n * tmp #返回n * (n-1)!
print(factorial(5)) #120
5.3 递归调用过程
递归调用可分解为两个过程,正向递归调用和逆向递归返回。
5.4 递归适用条件
如果一个问题规模缩减后,求解方式和原来一样,小规模问题解决后导致问题的最终解决,则可适用递归
- 形式是递归的 阶乘和斐波那契数列
- 结构是递归的 列表遍历
- 解法是递归的 汉诺塔
递归的写法:
- 一个递归程序必须包含两部分:
- 1) 递归终止条件
- 2) 递归调用自己
def recurve(*args,**kw):
if 递归终止条件: #递归终止条件必须在递归调用前
# to do
else:
#to do
recurve(参数)
#to do
6 栈和队列
6.1栈
抽象成一个开口向上的容器【羽毛球球筒】
- 特点:先进后出
stack
#创建一个栈【列表】 my_stack = [] #入栈【向栈中存数据】:append my_stack.append(23) print(my_stack) my_stack.append(30) print(my_stack) my_stack.append(4) print(my_stack) my_stack.append(11) print(my_stack) my_stack.append(20) print(my_stack) #出栈【从栈中取数据】:pop #pop每调用一次,则取出一个数据,先添加进去的最后被取出来【先进后出】 my_stack.pop() print(my_stack) my_stack.pop() print(my_stack) my_stack.pop() print(my_stack) my_stack.pop() print(my_stack) my_stack.pop() print(my_stack)
6.2 队列
queue
抽象成一个水平放置的水管
特点:先进先出
import collections #创建队列 queue = collections.deque([12,43,8,10]) print(queue) #入队【存数据】,append queue.append(66) print(queue) queue.append(77) print(queue) #deque([12, 43, 8, 10, 66, 77]) #出队【取数据】,popleft queue.popleft() print(queue) queue.popleft() print(queue) queue.popleft() print(queue)
课后练习:
#队列:先进先出
import collections
queue = collections.deque([10,20,30])
#出队
print(queue.popleft())
print(queue.popleft())
print(queue.popleft())
#入队
queue.append(40)
queue.append(50)
queue.append(60)
#约瑟夫环
def josephus(m,n):
queue = collections.deque([x for x in range(1,42)])
while len(queue) != 2:
for x in range(1,n):
queue.append(queue.popleft()) #左边出队,右边入队
queue.popleft() #直接出队
return queue
que = josephus(41,3)
print(que.popleft(),que.popleft())
标签:10,函数,迭代,基础,queue,print,my,stack
From: https://blog.csdn.net/2402_83194310/article/details/140584840