函数
(1)函数的含义:
功能 (包裹一部分代码 实现某一个功能 达成某一个目的)
(2)函数特点:
可以反复调用,提高代码的复用性,提高开发效率,便于维护管理
(3)函数基本格式
# 函数的定义
def func():
code1....
code2....
# 函数的调用
func()
(4)函数命名
"""
函数的命名
字母数字下划线,首字符不能位数字
严格区分大小且,且不能使用关键字
函数命名有意义,且不能使用中文
驼峰命名法:
(1)大驼峰命名法:每个单词的首字符大写 (一般在类中起名用这样的方式, 推荐)
mycar => MyCar
(2)小驼峰命名法:除了第一个单词首字符不用大写之外,剩下首字符都大写 (函数中的命名)
mycar => myCar
"""
函数参数 : 函数运算时需要的值
(1)函数参数概念及分类
函数参数:调用时需要传递的数据.
函数参数大类分为形参和实参:
形参意思: 函数定义时的参数
实参意思: 函数调用时的参数
形实关系:函数调用时,形参和实参个数需要一一对应
形参种类: 普通参数(位置参数),默认参数,普通收集参数,命名关键字参数,关键字收集参数
实参种类: 普通实参,关键字实参
# 1.普通参数 """ 函数的定义处,普通形参 """ def small_start(hang,lie): i = 0 while i<hang: j = 0 while j<lie: # 打印星星 print("*",end="") j+=1 # 打印换行 print() i+=1 # 函数的调用出为实参 small_start(3,8) # 2. 默认形参 hang,lie 在函数定义处给与默认值 """ 如果给与实参,那么就使用实际参数, 如果没给实参,那么就使用参数的默认值 """ def small_start(hang=10,lie=10): i = 0 while i<hang: j = 0 while j<lie: # 打印星星 print("*",end="") j+=1 # 打印换行 print() i+=1 # 3. 普通形参 + 默认形参 """默认形参必须写在普通形参的后面,语法上有要求""" # 函数的定义处 def small_start(hang,lie=10): # def small_start(hang,lie=10): i = 0 while i<hang: j = 0 while j<lie: # 打印星星 print("*",end="") j+=1 # 打印换行 print() i+=1 # (4) 关键字实参 """ (1)如果使用关键字实参进行函数调用,实参的顺序无所谓 (2)如果定义时是普通形参,调用时是关键字实参, 那么这个参数后面的所有调用方式都需要关键字实参进行调用 """ def small_start(hang,a,b,c,lie=10): # def small_start(hang,lie=10): i = 0 while i<hang: j = 0 while j<lie: # 打印星星 print("*",end="") j+=1 # 打印换行 print() i+=1 # 关键字实参 hang 和 lie small_start(lie = 12,hang = 12)
(2)收集参数:
普通收集参数:专门用于收集多余的普通实参,形成一个新的元组
语法:参数前面加* 例:*args(arguments)
# 计算任意长度的累加和
def my_sum(*args):
total = 0
for i in args:
total += i
print(total)
my_sum(1,2,3,4,5)
关键字收集参数:专门用于收集多余的关键字实参,形成一个新的字典
语法:参数前面加** 例:**kwargs(keword arguments)
# 拼接任意字符串
def func(**kwargs):
strvara = ""
strvarb = ""
dictvar = {"stra":"1","strb":"2"}
for k,v in kwargs.items():
if k in dictvar:
strvara += dictvar[k] + ":" + v + "\n"
else:
strvarb += v + " "
print(strvara)
print(strvarb)
func(stra="A",strb="B",strc="C")
(3)命名关键字参数:定义时放在*号后面的参数,调用时强制必须指定关键字实参才能调
语法:(*,x) x是命名关键字参数
# 命名关键字参数
# 方法一
def func(a,b,*,c,d):
print(a,b)
print(c,d)
func(1,2,c=3,d=4)
# 方法二
def func(*args,c,**kwargs):
print(args)
print(c)
print(kwargs)
func(1,2,3,4,a=1,b=2,c=3)
# 方法三
def func(a,b,*,c=3):
print(a,b)
print(c)
func(1,2,c=33)
# 区别于默认形参
def func(a,b,c=3):
print(a,b)
print(c)
func(1,2)
func(1,2,c=33)
func(1,2,33) # 关键字参数只能传关键字
(4)*和**的魔术用法:打包和解包
*和**,在函数的定义处,负责打包(把实参都收集过来,放在元组或字典中)
*和**,在函数的调用处,负责解包(把容器类型的数据,一个一个拿出来,进行传递)
# *
def func(a,b,c):
print(a,b,c)
listvar = [1,2,3]
func(*listvar)
# **
def func(a,*,b,c,d):
print(a)
print(b,c,d)
dictvar = {"b":2,"c":3,"d":4}
func(1,**dictvar)
"""
在字典的前面加上一个*号,默认只传递健
"""
def func(a,b):
print(a,b)
dictvar = {"a":1,"b":2}
func(*dictvar)
# *字符串
def func(a,b):
print(a,b)
strvar = "12"
func(*strvar)
(5)形参声明的位置顺序:
普通参数 -> 默认参数 -> 收集参数 -> 命名关键字参数 -> 关键字收集参数
(6)对于任意函数,都可以通过 def func(*args, **kw) 来获取所有参数
return
return返回值
为这个函数返回一个结果 (return返回值可有可无 按照需求选择)
注意:执行return语句之后,函数执行结束
"""
return 自定义返回值,如果没有写return ,默认返回None
功能:把值返回到函数的调用处;
(1)return 后面可以返回值 是自定义的. 除了6大标准数据类型之外,还有类 对象 函数
(2)如果执行了return 语句,意味着函数终止,后面的代码不执行
"""
# (1) return 后面可以返回值 是自定义的. 除了6大标准数据类型之外,还有类 对象 函数
def func():
# return 1
# return 3.14
# return 3+4j
# return True
# return [1,2,3]
# return {"a":1,"b":2}
pass
res = func() # res ={"a":1,"b":2}
print(res)
# (2) 如果执行了return 语句,意味着函数终止,后面的代码不执行
def func():
print(1)
return
print(2)
res = func()
print(res)
def func():
for i in range(5):
if i == 3:
return i
print(i)
res = func()
# (3) 计算器示例
def calc(sign, num1, num2):
if sign == "+":
res = num1 + num2
elif sign == "-":
res = num1 - num2
elif sign == "*":
res = num1 * num2
elif sign == "/":
if num2 == 0:
return "除数不能为零"
res = num1 / num2
return res
res = calc("+", 1, 1)
res = calc("-", -1, 90)
res = calc("*", 52, 10)
res = calc("/", 52, 10)
res = calc("/", 5200, 10)
print(res)
__doc__或者help查看文档
# __doc__
help(print)
res = print.__doc__
print(res)
# 自定义函数文档
def defined_word():
"""
功能:自定义函数文档
参数:
:return: None
"""
print("自定义函数文档")
# 方法一
res = defined_word.__doc__
print(res)
# 方法二
help(defined_word)
内置函数
abs 绝对值函数
>>> res = abs(-90.7)
>>> res
90.7
>>>
round 四舍五入 (n.5 n为偶数则舍去 n.5 n为奇数,则进一!)
>>> print(round(2.5))
2
>>> print(round(3.5))
4
>>>
sum 计算一个序列得和
>>> tuplevar = (1,2,3,4,5)
>>> print(sum(tuplevar))
15
>>>
max 获取一个序列里边的最大值
min 获取一个序列里边的最小值
>>> listvar = [11,88,66,33,77]
>>> print(max(listvar))
88
>>> print(min(listvar))
11
>>> listvara = sorted(listvar)
>>> listvara
[11, 33, 66, 77, 88]
>>> # 最大值
...
>>> print(listvara[-1])
88
>>> # 最小值
...
>>> print(listvara[0])
11
>>>
>>> # 获取一个序列里面的最小值,key=自定义函数
...
>>> listvar = [("a",88),("b",66),("c",99)]
>>> def func(n):
... return n[1] % 10
...
>>> res = min(listvar,key=func)
>>> print(res)
('b', 66)
>>>
pow 计算某个数值的x次方
>>> # 第三个参数时可选项,如果存在,前两个平方后和第三个取余
...
>>> print(pow(2,3))
8
>>> print(pow(2,3,3))
2
>>>
range 产生指定范围数据的可迭代对象
>>> for i in range(9,0,-2):
... print(i)
...
9
7
5
3
1
>>>
bin 将10进制数据转化为二进制
oct 将10进制数据转化为八进制
hex 将10进制数据转化为16进制
>>> print(bin(6))
0b110
>>> print(oct(9))
0o11
>>> print(hex(16))
0x10
>>>
chr 将ASCII编码转换为字符
ord 将字符转换为ASCII编码
>>> print(chr(97))
a
>>> print(ord("A"))
65
>>>
eval 将字符串当作python代码执行
exec 将字符串当作python代码执行(功能更强大)
>>> strvar = "print(123)"
>>> res = eval(strvar)
123
>>> print(res) # 返回值没有意义
None
>>>
>>> strvar = 'course = "python"'
>>> res = eval(strvar) # 声明变量,eval不允许
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<string>", line 1
course = "python"
^
SyntaxError: invalid syntax
>>>
>>> strvar = 'course = "python"'
>>> res = exec(strvar)
>>> print(course)
python
>>> print(res)
None
>>>
>>> strvar = """
... for i in range(5):
... print(i)
... """
>>> exec(strvar)
0
1
2
3
4
>>>
repr 不转义字符输出字符串
>>> strvar = "D:\note"
>>> print(strvar)
D:
ote
>>> print(repr(strvar))
'D:\note'
>>>
input 接受输入字符串
>>> res = input("Please input username>>>")
Please input username>>>admin
>>>
hash 生成哈希值
>>> strvara = "password"
>>> strvarb = "password"
>>> print(hash(strvara))
-8671913786014747281
>>> print(hash(strvarb))
-8671913786014747281
>>>
参数练习
def f1(a, b, c=0, *args, **kw):
print('a =', a, 'b =', b, 'c =', c, 'args =', args, 'kw =', kw)
def f2(a, b, c=0, *, d, **kw):
print('a =', a, 'b =', b, 'c =', c, 'd =', d, 'kw =', kw)
以上两个函数 打印结果
#(一)
f1(1, 2)
f1(1, 2, c=3)
f1(1, 2, 3, 'a', 'b')
f1(1, 2, 3, 'a', 'b', x=99)
f2(1, 2, d=99, ext=None)
#(二)
args = (1, 2, 3, 4)
kw = {'d': 99, 'x': '#'}
f1(*args, **kw)
#(三)
myargs = (1, 2, 3)
mykw = {'d': 88, 'x': '#'}
f2(*myargs, **mykw)
#(四)
def f1(a, b, c=0, *args,d,**kw):
print('a =', a, 'b =', b, 'c =', c, 'args =', args, 'kw =', kw)
print(d)
f1(1,2,3, 'a', 'b',d=67, x=99,y=77)
>>> def f1(a,b,c=0,*args,**kw):
... print('a=',a,'b=',b,'c=',c,'args=',args,'kw=',kw)
...
>>> def f2(a,b,c=0,*,d,**kw):
... print('a=',a,'b=',b,'c=',c,'d=',d,'kw=',kw)
...
>>> f1(1,2,c=3)
a= 1 b= 2 c= 3 args= () kw= {}
>>> f1(1,2,3,'a','b')
a= 1 b= 2 c= 3 args= ('a', 'b') kw= {}
>>> f1(1,2,3,'a','b',x=99)
a= 1 b= 2 c= 3 args= ('a', 'b') kw= {'x': 99}
>>> f2(1,2,d=99,ext=None)
a= 1 b= 2 c= 0 d= 99 kw= {'ext': None}
>>> args=(1,2,3,4)
>>> kw={'d':99,'x':'#'}
>>> f1(*args,**kw)
a= 1 b= 2 c= 3 args= (4,) kw= {'d': 99, 'x': '#'}
>>> myargs=(1,2,3)
>>> mykw={'d':88,'x':'#'}
>>> f2(*myargs,**mykw)
a= 1 b= 2 c= 3 d= 88 kw= {'x': '#'}
>>> def f1(a,b,c=0,*args,d,**kw):
... print('a=',a,'b=',b,'c=',c,'args=',args,'kw=',kw)
... print(d)
...
>>> f1(1,2,3,'a','b',d=67,x=99,y=77)
a= 1 b= 2 c= 3 args= ('a', 'b') kw= {'x': 99, 'y': 77}
67
python中的函数可以像变量一样,动态创建,销毁,当参数传递,作为值返回,叫第一类对象.其他语言功能有限
1.函数名是个特殊的变量,可以当做变量赋值
2.函数名可以作为容器类型数据的元素
3.函数名可以作为函数的参数
4.函数名可作为函数的返回值
>>> # 1.函数名是个特殊的变量,可以当做变量赋值
... def func():
... print("函数名可以当成变量赋值")
...
>>> abc = 45
>>> abc = func
>>> print(abc)
<function func at 0x00000209F87256A8>
>>> abc()
函数名可以当成变量赋值
>>>
>>># 2.函数名可以作为容器类型数据的元素
>>> def func1():
... print(1)
...
>>> def func2():
... print(2)
...
>>> listvar = [func1,func2]
>>> print(listvar)
[<function func1 at 0x00000209F87257B8>, <function func2 at 0x00000209F8725730>]
>>> for i in listvar:
... i()
...
1
2
>>>
>>> # 3.函数名可以作为函数的参数
...
>>> def func1(func):
... func()
...
>>> def func2():
... print('func2')
...
>>> func1(func2)
func2
>>>
>>> # 4.函数名可以作为函数的返回值
...
>>> def func1(func):
... return func
...
>>> def func2():
... print('func2')
...
>>> res = func1(func2)
>>> print(res)
<function func2 at 0x00000209F8725840>
>>> res()
func2
>>>
__doc__或者help查看文档
作用域:作用范围
命名空间 : 划分一块区域保存所有数据,以字典的方式存储(变量与值形成映射关系).一共三种.
(1)内建命名空间:解释器启动时创建,直到解释器运行结束,生存周期最长
(2)全局命名空间:文件运行时创建,直到解释器运行结束,生存周期较长
(3)局部命名空间:函数调用时,里面的局部变量才创建,调用结束后即释放,生存周期较短
命名空间的提出是为了划分和控制变量是否可见,以及生存周期的长短.
命名空间 创建顺序:(了解)
python解释器启动->创建内建命名空间->创建全局命名空间->创建局部命名空间
命名空间 销毁顺序:(了解)
函数调用结束后->销毁函数对应的局部命名空间数据->销毁全局命名空间数据->销毁内建命名空间数据
全局变量 与 局部变量 及 其关键字的使用
局部变量:函数内部的变量是局部变量,作用域仅在函数内部可见(局部命名空间)
全局变量:函数外部的变量是全局变量,作用域横跨整个文件(全局命名空间)
# 局部变量的获取 与 修改
def func():
a = 15
# 获取局部变量
print(a)
# 修改局部变量
a = 17
print(a)
func()
# print(a) error a局部变量值限定在函数内部使用;
# 全局变量的获取 与 修改
b = 100
# 获取全局变量
print(b)
# 修改全局变量
b += 200
print(b)
内置函数:内建命名空间
global :关键字:声明全局变量获修改全局变量
# 在函数内部可以直接获取全局变量,但是不能直接修改
# 用global关键字,修改全局变量
c = 50
def func():
global c
print(c)
c = 60
print(c)
func()
print(c)
# 在函数内部可以直接定义一个全局变量
def func():
global d
d = 90
func()
print(d)
nonlocal :关键字:修改局部变量(当前函数上一层的局部变量)
# (1) nonlocal 只能用来修改局部变量
a = 90
def func():
# nonlocal a error
a = 80
print(a)
func()
# (2) nonlocal 会不停的寻找上一层空间所对应的值,拿来修改
"""通过LEGB原则,可以获取到上一层空间的值,只能单纯的获取,不能直接修改
如果想要修改 通过nonlocal 加以修饰.
"""
def outer():
a = 20
def inner():
nonlocal a
print(a)
a += 1
print(a)
inner()
outer()
# (3) 如果上一层找不到,继续向上寻找,再也找不到了,直接报错; nonlocal 只能修饰局部变量
a = 100
def outer():
a = 100
def inner():
# a = 110
def smaller():
nonlocal a
a += 10
# print(a)
smaller()
print(a,"<=1=>")
inner()
print(a,"<=2=>")
outer()
# (4) 不通过nonlocal 是否可以改变局部变量? 可以! 需要使用列表进行操作;
def outer():
lst = [100,101,102]
def inner():
lst[0] += 1
inner()
print(lst)
outer()
locals() :返回字典,获取当前作用域的所有内容
如果在函数里:获取locals()调用之前,该作用域出现的内容
如果在函数外:获取locals()打印返回值之前,该作用域出现的内容
# 当前作用域在全局范围
a = 1
b = 2
res = locals()
c = 3
print(res)
# 当前作用域在局部范围
zz = 90
def func():
d = 4
f = 5
res = locals()
g = 6
print(res)
func()
globals() :返回字典,获取全局作用域的所有内容
如果在函数里: 获取globals()调用之前,全局作用域出现的内容
如果在函数外: 获取globals()打印返回值之前,全局作用域出现的内容
""" globals 无论在函数内外,都只获取全局作用域当中的所有内容 如果globals在函数外:所获取的是globals(),打印返回值之前的所有内容 如果globals在函数内:所获取的是globals(),调用之前所有内容 """ # 当前作用域在全局范围 a = 1 b = 2 res = globals() c = 3 print(res) # 当前作用域在局部范围 aa = 11 bb = 22 def func(): d =1 f = 2 res = globals() z = 3 print(res) cc = 33 func() #res = globals() dd = 4 # globals 动态的创建全局变量 """ globals() 返回的是系统的字典,只需要在字典里面添加键值对,就可以创建全局变量 字典中的键 就是变量名 字典中的值 就是变量所指代的值 """ dic = globals() print(dic) dic["strvar"] = "abc" print(strvar) # 创建p1~p5 5个全局变量 def func(): dic = globals() for i in range(1,6): # p1 ~ p5 5个键 dic["p%d" % (i)] = i func() print(p1) print(p2) print(p3) print(p4) print(p5)
LEGB原则(即就近原则找变量)
找寻变量的调用顺序采用LEGB原则(即就近原则)
B —— Builtin(Python);Python内置模块的命名空间 (内建作用域)
G —— Global(module); 函数外部所在的命名空间 (全局作用域)
E —— Enclosing function locals;外部嵌套函数的作用域(嵌套作用域)
L —— Local(function);当前函数内的作用域 (局部作用域)
依据就近原则,从下往上 从里向外 依次寻找
内部函数
(1)内部函数可以直接在函数外部调用么
(2)调用外部函数后,内部函数可以在函数外部调用吗
(3)内部函数可以在函数内部调用吗
(4)内部函数在函数内部调用时,是否有先后顺序
>>> # 函数的嵌套
...
>>> def outer():
... def inner():
... def smaller():
... print(id)
... print('small func')
... smaller()
... inner()
...
>>> outer()
<built-in function id>
small func
>>>
闭包
获取闭包函数使用的变量 __closure__ , cell_contents
闭包的定义:
内函数使用外函数的局部变量,并且外函数将内函数返回出来的方法叫闭包,
返回的内函数叫 闭包函数.
闭包的特点:
内函数使用了外函数的局部变量,外函数的局部变量与内函数发生绑定,延长该变量的生命周期
(实际内存给它存储了这个值,暂时不释放)
"""
内函数使用了外函数的局部变量,外函数的局部变量与内函数发生绑定,延长了该变量的生命周期
"""
def outer(val):
def inner(num):
return num + val
return inner
func = outer(10)
res = func(5) # func = inner() = num + val = 10 + 5 = 15
print(res)
闭包的意义:
闭包可以优先使用外函数中的变量,并对闭包中的值起到了封装保护的作用.外部无法访问.
"""
闭包可以优先使用外函数中的变量,并对闭包中的值起到了封装保护的作用.外部无法访问.
模拟一个鼠标点击计数功能:
"""
clicknum = 0
def clickfunc():
global clicknum
clicknum += 1
print(clicknum)
# 模拟点击操作,点击一次就调用一次
clickfunc()
clickfunc()
clickfunc()
clickfunc()
clickfunc()
clicknum = 100
clickfunc()
# 用闭包函数来进行改造
def clickfunc():
x = 0
def func():
nonlocal x
x +=1
print(x)
return func
clickfunc2 = clickfunc()
clickfunc2() # clickfunc2() = func()
clickfunc2()
clickfunc2()
clickfunc2()
clickfunc2()
x = 100
clickfunc2()
匿名函数
lambda 表达式:用一句话来表达只有返回值的函数
好处:简洁,方便,定义函数快速简单
语法:lambda 参数 : 返回值
>>> # 1.无参数的lambda表达式
...
>>> def func():
... return 123
...
>>> res = func()
>>> print(res)
123
>>> func = lambda:123
>>> res = func()
>>> print(res)
123
>>>
>>> # 2.有参数的lambda表达式
...
>>> def func(n):
... return type(n)
...
>>> res = func('123')
>>> print(res)
<class 'str'>
>>> func = lambda n : type(n)
>>> res = func('123')
>>> print(res)
<class 'str'>
>>>
>>> # 3.带有条件判断的lambda表达式
"""
三元运算:
真值 if 条件表达式 else 假值
如果条件表达式成立,执行真值
如果条件表达式不成立,执行假值
"""
>>> def func(n):
... if n % 2 == 0:
... return "偶数"
... else:
... return "奇数"
...
>>> func(11)
>>> n = 11
>>> func = "偶数" if n % 2 == 0 else "奇数"
>>> func
'奇数'
>>>
>>> # 计算参数中的最大值
...
>>> def func(m,n):
... if m > n:
... return m
... else:
... return n
...
>>> print(func(11,33))
33
>>> func = lambda m,n : m if m > n else n
>>> print(func(11,33))
33
>>>
递归函数
递归函数:自己调用自己的函数 (递:去 归:回 一去一回是递归)
(1)每调用一次函数,就是开辟一个栈帧空间的过程
每结束一次函数,就是释放一个栈帧空间的过程
递归函数就是不停的开辟栈帧空间和释放栈帧空间的过程
(2)回的过程有两种触发时机:
(1)当最后一层函数全部执行完毕,触发回的过程,回到上一层函数调用处
(2)当遇到return 返回值的时候,触发回的过程,回到上一层函数调用处
>>> def recursion(n):
... print("session01>>>",n)
... if n > 0:
... recursion(n-1)
... print("session02>>>",n)
...
>>> recursion(5)
session01>>> 5
session01>>> 4
session01>>> 3
session01>>> 2
session01>>> 1
session01>>> 0
session02>>> 0
session02>>> 1
session02>>> 2
session02>>> 3
session02>>> 4
session02>>> 5
>>>
>>> # 计算n的阶乘
...
>>> def factorial(n):
... if n <= 1:
... return 1
... return n * factorial(n-1)
...
>>> res = factorial(5)
>>> print(res)
120
>>>
如果我们计算fact(5)
,可以根据函数定义看到计算过程如下:
===> fact(5)
===> 5 * fact(4)
===> 5 * (4 * fact(3))
===> 5 * (4 * (3 * fact(2)))
===> 5 * (4 * (3 * (2 * fact(1))))
===> 5 * (4 * (3 * (2 * 1)))
===> 5 * (4 * (3 * 2))
===> 5 * (4 * 6)
===> 5 * 24
===> 120
内存栈区堆区(了解内容)
单独讲栈堆是数据结构
栈:后进先出的一种数据结构
堆:排序后的一种树状数据结构
栈区堆区是内存空间
栈区:按照后进先出的数据结构(栈),无论创建或销毁都是自动为数据分配内存,释放内存
(系统自动做的)
堆区:按照排序后的树状数据结构(堆),可优先取出必要数据,无论创建或销毁都是手动分配内存,释放内存(程序员手动做的)
--内存中的栈区 : 自动分配 自动释放
--内存中的堆区 : 手动分配 手动释放
运行程序时在内存中执行,会因为数据类型的不同而在内存的不同区域运行
因不同语言对内存划分的机制不一,但大体来讲,有如下四大区域
--栈区: 分配局部变量空间.
--堆区: 是用于手动分配程序员申请的内存空间.
--静态区(全局栈区): 分配静态变量,全局变量空间.
--代码区(只读区,常量区): 分配常量和程序代码空间的.
栈区 堆区 静态区 代码区 都是内存中的一段空间
迭代器
迭代器:能被next()函数调用并不断返回下一个值的对象称为迭代器(Iterator 迭代器是对象)
特征:迭代器会生成惰性序列,它通过计算把值依次的返回,一边循环一边计算而不是一次性得到所有数据
优点:需要数据的时候,一次取一个,可以大大节省内存空间.而不是一股脑的把所有数据放进内存.
--Iterable可迭代的 Iterator迭代器
惰性序列:没有一次性的把所有数据都放在序列中,而是遍历一个放一个,这样的序列
1.可迭代对象。
如果一个数据类型其中的成员包含了__iter__方法,这个数据类型就是可迭代对象
dir 这个函数可以获取该数据类型的成员结构
>>> setvar ={1,2,'a','b'} >>> setvar {1, 2, 'b', 'a'} >>> for i in setvar: ... print(i) ... 1 2 b a >>> res = dir(setvar) >>> res ['__and__', '__class__', '__contains__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__iand__', '__init__', '__init_subclass__', '__ior__', '__isub__', '__iter__', '__ixor__', '__le__', '__len__', '__lt__', '__ne__', '__new__', '__or__', '__rand__', '__reduce__', '__reduce_ex__', '__repr__', '__ror__', '__rsub__', '__rxor__', '__setattr__', '__sizeof__', '__str__', '__sub__', '__subclasshook__', '__xor__', 'add', 'clear', 'copy', 'difference', 'difference_update', 'discard', 'intersection', 'intersection_update', 'isdisjoint', 'issubset', 'issuperset', 'pop', 'remove', 'symmetric_difference', 'symmetric_difference_update', 'union', 'update'] >>>
2.迭代器
for循环在迭代数据的时候,内部先转化为迭代器,然后通过next方法来进行调用
变成迭代器:
(1)iter (2)__iter__()
>>> setvar ={1,2,'a','b'}
>>> res = iter(setvar)
>>> res
<set_iterator object at 0x00000135A70DB8B8>
>>> ret = setvar.__iter__()
>>> ret
<set_iterator object at 0x00000135A70DB900>
>>>
遍历迭代器
(1)next (2)__next__()
>>> setvar ={1,2,'a','b'}
>>> res = iter(setvar)
>>> ret = next(res)
>>> ret
1
>>> ret = next(res)
>>> ret
2
>>> ret = next(res)
>>> ret
'b'
判断可迭代对象
>>> setvar ={1,2,'a','b'}
>>> res = iter(setvar)
>>> print("__iter__" in dir(setvar))
True
>>>
判断迭代器
(1)含有__iter__和__next__两个方法,该数据类型就是迭代器
>>> setvar ={1,2,'a','b'}
>>> res = iter(setvar)
>>> print("__iter__" in dir(res) and "__next__" in dir(res))
True
>>>
(2)from collections import Iterator,Iterable
>>> from collections import Iterator,Iterable
>>> listvar = [1,2,3,4]
>>> # 是否是一个迭代器
...
>>> res = isinstance(listvar,Iterator)
>>> res
False
>>> # 是否是可迭代对象
...
>>> res = isinstance(listvar,Iterable)
>>> res
True
>>>
迭代器是可迭代对象
可迭代对象不一定是迭代器
range 是 可迭代对象
>>> res = isinstance(range(10),Iterator)
>>> res
False
>>> res = isinstance(range(10),Iterable)
>>> res
True
>>>
range 和 迭代器 能够产生惰性序列
在调用时,超出了原有的数据个数,会直接越界报错
>>> it = iter(range(3))
>>> print(next(it))
0
>>> print(next(it))
1
>>> print(next(it))
2
>>> print(next(it))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration
>>>
遍历
通过for和next配合使用
>>> it = iter(range(5))
>>> for i in range(3):
... res = next(it)
... print(res)
...
0
1
2
>>>
通过for一次性遍历迭代器中所有数据
>>> it = iter(range(5))
>>> for i in it:
... print(i)
...
0
1
2
3
4
>>>
高阶函数
高阶函数:能够把函数当成参数传递的就是高阶函数
map
map(func,iterable)
功能:
把iterable里面所有数据 一一的放进到func这个函数中进行操作 ,把结果扔进迭代器
参数:
func 内置或自定义函数
iterable 具有可迭代性的数据 ([迭代器],[容器类型的数据],[range对象])
返回值:
返回最后的迭代器
例1:["1","2","3","4"] ==> [1,2,3,4]
常规方法
>>> listvar = ["1","2","3","4"]
>>> listvara = []
>>> for i in listvar:
... res = int(i)
... listvara.append(res)
...
>>> listvara
[1, 2, 3, 4]
>>>
使用map
>>> listvar = ["1","2","3","4"]
>>> from collections import Iterator,Iterable
>>> it = map(int,listvar)
>>> print(isinstance(it,Iterator))
True
>>> print(next(it))
1
>>> print(next(it))
2
>>> print(next(it))
3
>>> print(next(it))
4
>>> # 使用for进行调用
...
>>> it = map(int,listvar)
>>> for i in it:
... print(i)
...
1
2
3
4
>>> # for配合next进行调用
...
>>> it = map(int,listvar)
>>> for i in range(2):
... res = next(it)
... print(res)
...
1
2
>>> # 使用list强转成列表
...
>>> it = map(int,listvar)
>>> lst = list(it)
>>> lst
[1, 2, 3, 4]
>>>
例2:[1,2,3,4] ==> [3,6,9,12]
>>> listvar = [1,2,3,4]
>>> listvara = []
>>> for i in listvar:
... res = i * 3
... listvara.append(res)
...
>>> listvara
[3, 6, 9, 12]
>>>
map
>>> listvar = [1,2,3,4]
>>> def func(n):
... return n * 3
...
>>> it = map(func,listvar)
>>> print(list(it))
[3, 6, 9, 12]
>>>
例3:{97:"a",98:"b",99:"c"} ==> {"a":97,"b":98,"c":99}
>>> dictvar = {97:"a",98:"b",99:"c"}
>>> dictvara = {}
>>> res = dictvar.items()
>>> res
dict_items([(97, 'a'), (98, 'b'), (99, 'c')])
>>> # 反转字典中的键值对
...
>>> for k,v in res:
... dictvara[v] = k
...
>>> dictvara
{'a': 97, 'b': 98, 'c': 99}
>>>
map自定义函数,需要一个参数,必须写一个返回值
>>> def func(n):
... dictvar = {97:"a",98:"b",99:"c"}
... for k,v in dictvar.items():
... dictvara[v] = k
... return dictvara[n]
...
>>> it = map(func,["a","b","c"])
>>> print(list(it))
[97, 98, 99]
>>>
reduce
reduce(func,iterable)
功能:
先把iterable里面的前2个数据拿到func函数当中进行运算,得到结果,
在把计算的结果和iterable中的第三个数据拿到func里面进行运算,
依次类推 ,直到iterable里面的所有数据都拿完为止,程序结束
参数:
func 内置或自定义函数
iterable 具有可迭代性的数据 ([迭代器],[容器类型的数据],[range对象])
返回值:
计算的最后结果
例1:[5,4,8,8] ==> 5488
>>> listvar = [5,4,8,8]
>>> strvar = ''
>>> for i in listvar:
... strvar += str(i)
...
>>> print(strvar,type(strvar),int(strvar))
5488 <class 'str'> 5488
>>>
方法二:
5 * 10 + 4 = 54
54 * 10 + 8 = 548
548 * 10 + 8 = 5488
>>> listvar = [5,4,8,8]
>>> it = iter(listvar)
>>> res1 = next(it)
>>> res2 = next(it)
>>> res = res1 * 10 + res2
>>> res
54
>>> for i in it:
... res = res * 10 + i
...
>>> print(res,type(res))
5488 <class 'int'>
>>>
使用reduce进行改写
>>> from functools import reduce
>>> listvar = [5,4,8,8]
>>> def func(x,y):
... return x*10 + y
...
>>> res = reduce(func,listvar)
>>> print(res,type(res))
5488 <class 'int'>
>>>
例2:"789" ==> 789 不适用int强转的前提下完成
>>> strvar = "789"
>>> def func(n):
... dictvar = {"0":0,"1":1,"2":2,"3":3,"4":4,"5":5,"6":6,"7":7,"8":8,"9":9}
... return dictvar[n]
...
>>> def funca(x,y):
... return x*10 + y
...
>>> it = map(func,strvar)
>>> res = reduce(funca,it)
>>> print(res,type(res))
789 <class 'int'>
>>>
sorted
sorted(iterable,reverse=False,key=函数)
功能:
对数据进行排序
参数:
iterable : 具有可迭代性的数据(迭代器,容器类型数据,可迭代对象)
reverse : 是否反转 默认为False 代表正序, 改成True 为倒序
key : 指定函数 内置或自定义函数
返回值:
返回排序后的数据
>>> # 默认从小到大排序
...
>>> listvar = [88,31,-90,0]
>>> res = sorted(listvar)
>>> res
[-90, 0, 31, 88]
>>> # 从大到小排序
...
>>> listvar = [88,31,-90,0]
>>> res = sorted(listvar,reverse=True)
>>> res
[88, 31, 0, -90]
>>>
列1:按照绝对值排序,使用内置函数
>>> listvar = [-99,-2,45,1]
>>> res = sorted(listvar,key=abs)
>>> res
[1, -2, 45, -99]
>>>
例2:按照余数排序,使用自定义函数
>>> def func(n):
... return n % 10
...
>>> listvar = (19,24,91,36)
>>> res = sorted(listvar,key=func)
>>> res
[91, 24, 36, 19]
>>> listvar
(19, 24, 91, 36)
>>>
filter
filter(func,iterable)
功能:
用来过滤的,如果func函数中返回True , 会将这个值保留到迭代器中
如果func函数中返回False , 会将此值舍弃不保留
参数:
func : 自定义函数
iterable : 具有可迭代性的数据(迭代器,容器类型数据,可迭代对象)
返回值:
返回处理后的迭代器
例1:保留偶数
基本写法
>>> listvar = [1,2,3,4,5,6,7,8,9]
>>> for i in listvar:
... if i % 2 ==0:
... print(i)
... else:
... pass
...
2
4
6
8
>>>
filter写法
>>> def func(n):
... if n % 2 == 0:
... return True
... else:
... return False
...
>>> it = filter(func,listvar)
>>> print(list(it))
[2, 4, 6, 8]
>>>
简洁写法
>>> func = lambda n:True if n % 2 == 0 else False
>>> it = filter(lambda n : True if n % 2 == 0 else False,listvar)
>>> print(list(it))
[2, 4, 6, 8]
>>>
通过一行循环判断,遍历出一系列数据的方式是推导式
语法: val for val in Iterable (把想要的值写在 for的左侧)
里面是一行循环判断!根据套在推导式外层的符号判断具体是什么类型的推导式
推导式种类三种:
[val for val in Iterable] 列表推导式
{val for val in Iterable} 集合推导式
{a:b for a,b in iterable} 字典推导式
例1:生成一个列表 listvar=[1,2,3,4,5,6,7,8,9,10]
>>> listvar = []
>>> for i in range(1,11):
... listvar.append(i)
...
>>> listvar
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
>>>
普通列表推导式
>>> listvar = [i for i in range(1,11)]
>>> listvar
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
>>> listvar = [i*2 for i in range(1,11)]
>>> listvar
[2, 4, 6, 8, 10, 12, 14, 16, 18, 20]
>>>
带有判断条件的列表推导式
基本写法
>>> listvar = [1,2,3,4,5,6,7,8,9]
>>> listvara = []
>>> for i in listvar:
... if i % 2 == 1:
... listvara.append(i)
...
>>> listvara
[1, 3, 5, 7, 9]
>>>
推导式写法
>>> listvar = [1,2,3,4,5,6,7,8,9]
>>> listvara = [i for i in listvar if i % 2 == 1]
>>> listvara
[1, 3, 5, 7, 9]
>>>
双循环列表推导式
>>> listvara = ["1","2","3"]
>>> listvarb = ["a","b","c"]
>>> listvar = []
>>> for i in listvara:
... for j in listvarb:
... strvar = i + ":" + j
... listvar.append(strvar)
...
>>> listvar
['1:a', '1:b', '1:c', '2:a', '2:b', '2:c', '3:a', '3:b', '3:c']
>>>
>>> listvar = [i + ":" + j for i in listvara for j in listvarb]
>>> listvar
['1:a', '1:b', '1:c', '2:a', '2:b', '2:c', '3:a', '3:b', '3:c']
>>>
带有条件判断的双循环列表推导式
>>> listvara = ["1","2","3"]
>>> listvarb = ["a","b","c"]
>>> listvar = []
>>> for i in listvara:
... for j in listvarb:
... if listvara.index(i) == listvarb.index(j):
... strvar = i + ":" + j
... listvar.append(strvar)
...
>>> listvar
['1:a', '2:b', '3:c']
>>>
>>>
>>> listvar = [i + ":" + j for i in listvara for j in listvarb if listvara.index(i) == listvarb.index(j)]
>>> listvar
['1:a', '2:b', '3:c']
>>>
列表推导式,集合推导式,字典推导式的相关写法
(1)普通推导式
(2)带有判断条件的推到式
(3)多循环推到式
(4)带有判断条件的多循环推到式
集合推导式(去重)
>>> setvar = {15 if i % 2 == 1 else 16 for i in range(3)}
>>> setvar
{16, 15}
(1)enumerate
enumerate(iterable,[start=0])
功能:枚举 ; 将索引号和iterable中的值,一个一个拿出来配对组成元组放入迭代器中
参数:
iterable: 可迭代性数据 (常用:迭代器,容器类型数据,可迭代对象range)
start: 可以选择开始的索引号(默认从0开始索引)
返回值:迭代器
>>> from collections import Iterator,Iterable
>>> listvar = [1,2,3,4]
>>> it = enumerate(listvar)
>>> print(it)
<enumerate object at 0x000001D7FC53BAB0>
>>> print(isinstance(it,Iterator))
True
>>> print(list(it))
[(0, 1), (1, 2), (2, 3), (3, 4)]
>>>
强制迭代器变成字典
>>> listvar = ["a","b","c"]
>>> it = enumerate(listvar)
>>> res = dict(it)
>>> print(res)
{0: 'a', 1: 'b', 2: 'c'}
>>>
字典推导式变成字典
>>> listvar = ["a","b","c"]
>>> it = enumerate(listvar)
>>> dictvar = {k:v for k,v in it}
>>> print(dictvar)
{0: 'a', 1: 'b', 2: 'c'}
>>>
>>> it = enumerate(listvar,start=10)
>>> dictvar = {k:v for k,v in it}
>>> print(dictvar)
{10: 'a', 11: 'b', 12: 'c'}
>>>
(2)zip
zip(iterable, ... ...)
功能: 将多个iterable中的值,一个一个拿出来配对组成元组放入迭代器中
iterable: 可迭代性数据 (常用:迭代器,容器类型数据,可迭代对象range)
返回: 迭代器
>>> listvara = ["1","2","3"]
>>> listvarb = ["a","b","c"]
>>> listvarc = ["e","f","g"]
>>> it = zip(listvara,listvarb,listvarc)
>>> print(list(it))
[('1', 'a', 'e'), ('2', 'b', 'f'), ('3', 'c', 'g')]
>>>
dict强转迭代器变成字典
>>> listvara = ["1","2","3"]
>>> listvarb = ["a","b","c"]
>>> res = dict(zip(listvara,listvarb))
>>> print(res)
{'1': 'a', '2': 'b', '3': 'c'}
>>>
字典推导式
>>> dictvar = {k:v for k,v in zip(listvara,listvarb)}
>>> print(dictvar)
{'1': 'a', '2': 'b', '3': 'c'}
>>>
元组推导式是生成器(generator)
元组推导式的返回值是一个生成器对象,简称生成器,生成器本质就是迭代器.
迭代器和生成器区别:
迭代器本身是系统内置的.重写不了.而生成器是用户自定义的,可以重写迭代逻辑
生成器可以用两种方式创建:
(1)生成器表达式 (里面是推导式,外面用圆括号)
(2)生成器函数 (用def定义,里面含有yield)
yield 类似于 return
共同点在于:执行到这句话都会把值返回出去
不同点在于:yield每次返回时,会记住上次离开时执行的位置 , 下次在调用生成器 , 会从上次执行的位置往下走
而return直接终止函数,每次重头调用.
yield 6 和 yield(6) 2种写法都可以 yield 6 更像 return 6 的写法 推荐使用
基本定义,返回生成器对象,简称生成器
>>> from collections import Iterator
>>> generator_obj = (i for i in range(10))
>>> print(generator_obj)
<generator object <genexpr> at 0x000001D7FC506570>
>>> print(isinstance(generator_obj,Iterator))
True
>>>
使用next方法调用
>>> res = next(generator_obj)
>>> res
0
>>>
for配合next调用
>>> for i in range(5):
... res = next(generator_obj)
... print(res)
...
1
2
3
4
5
for循环遍历生成器
>>> for i in generator_obj:
... print(i)
...
6
7
8
9
>>>
生成器函数
1.基本语法
>>> def mygen():
... print(1)
... yield 1
... print(2)
... yield 2
... print(3)
... yield 3
...
>>>
初始化生成器函数,返回生成器对象,调用完后会报错
>>> gen = mygen()
>>> res = next(gen)
1
>>> res = next(gen)
2
>>> res = next(gen)
3
>>> res = next(gen)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration
>>>
例1:
def mygen():
for i in range(100):
yield "num:{:d}".format(i)
# 初始化生成器函数 ,返回生成器对象,简称生成器
gen = mygen()
for i in range(50):
res = next(gen)
print(res)
for i in range(30):
print(next(gen))
数据量大使用for进行遍历,会死循环
生成器send 与 yield from
send
next和send区别:
next 只能取值
send 不但能取值,还能发送值
send注意点:
第一个 send 不能给 yield 传值 默认只能写None
最后一个yield 接受不到send的发送值
>>> def mygen():
... print(1)
... res1 = yield 1
... print(res1,"接受返回1")
... res2 = yield 2
... print(res2,"接受返回2")
...
>>> # 初始化生成器函数
...
>>> gen = mygen()
>>> # 第一次无法给上一个yield发送数据,强制发送None
...
>>> res = gen.send(None)
1
>>> res = gen.send(111)
111 接受返回1
>>> res = gen.send(222)
222 接受返回2
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration
>>>
yield from : 将一个可迭代对象变成一个迭代器返回
>>> def mygen():
... yield from [1,2,3]
...
>>> gen = mygen()
>>> res = next(gen)
>>> res
1
>>> res = next(gen)
>>> res
2
>>> res = next(gen)
>>> res
3
>>>
斐波那契数列(用前两数相加得到第三个)
>>> def mygen(n):
... a,b = 0,1
... i = 0
... while i < n:
... yield b
... a,b = b,a+b
... i += 1
...
>>> gen = mygen(5)
>>> for i in gen:
... print(i)
...
1
1
2
3
5
>>>
练习题:
(1).{'x': 'A', 'y': 'B', 'z': 'C' } 把字典写成x=A,y=B,z=C的列表推导式
(2).把列表中所有字符变成小写 ["ADDD","dddDD","DDaa","sss"]
(3).x是0-5之间的偶数,y是0-5之间的奇数 把x,y组成一起变成元组,放到列表当中
(4).使用列表推导式 制作所有99乘法表中的运算
(5)#求M,N中矩阵和元素的乘积
M = [ [1,2,3],
[4,5,6],
[7,8,9] ]
N = [ [2,2,2],
[3,3,3],
[4,4,4] ]
=>实现效果1 [2, 4, 6, 12, 15, 18, 28, 32, 36]
=>实现效果2 [[2, 4, 6], [12, 15, 18], [28, 32, 36]]