可迭代对象 迭代器对象 for循环原理 生成器 常用内置函数 匿名函数 结合匿名函数的内置函数 format字符串格式化 递归
1.可迭代对象:指的是有.__iter__()方法的对象是可迭代对象,可迭代对象调用.__iter__()得到的是迭代器对象。 2.基本数据类型中是可迭代对象有:字符串;列表;元组,字典,集合 3.文件对象(执行内置的__iter__之后还是本身 没有任何变化):文件对象本身就是迭代器对象 ls = [4, 1, 5, 2, 3] res = ls.__iter__() # => 说明ls是可迭代对象;调用了.__iter__()得到了迭代器对象res;res=ls.__iter__() 与res = iter(ls)结果一样 print(res) # <list_iterator object at 0x000002732B0C7470>
1.可迭代器对象:指的是有.__iter__()和.__next__()两种方法的对象是迭代器对象,迭代器对象调用.__next__()方法进行取值。 2.示例: l = [1,2,3,4] # 生成一个迭代器对象 iter_l = l.__iter__() # 迭代器取值 调用__next__ print(iter_l.__next__()) # 1 print(iter_l.__next__()) # 2 print(iter_l.__next__()) # 3 print(iter_l.__next__()) # 4 print(iter_l.__next__()) # 如果取完了在使用.__next__(); 直接报错 StopIteration 3.注意:迭代器对象无论执行多少次.__iter__()方法得到的还是迭代器对象本身(******)
1.for循环原理:for v in obj 1.将in后面的对象调用__iter__转换成迭代器对象 2.调用__next__迭代取值,依次将当前循环的取值结果赋值给v 3.内部有异常捕获StopIteration,当__next__报这个错 自动结束循环
四.迭代取值优缺点
1.总结: 可迭代对象:内置有.__iter__()方法的 迭代器对象:既内置有.__iter__()也内置有.__next__()方法 2.迭代取值: 优点 1.不依赖于索引取值 2.内存中永远只占一份空间,不会导致内存溢出 缺点 1.只能从前往后依次取值,不能够获取指定的元素 2.取完之后在取值会报StopIteration错误
1.什么是生成器:用户自定义的迭代器对象;本质上就是迭代器对象(简单来说就是函数体中有关键字yield的函数) 2.例: def fn(): yield 1 yield 3 yield 5 obj = fn() # 得到的是生成器对象;并不会调用函数执行函数体代码 obj.__next__() # 从开始往下执行,遇到第一个yield停止,拿到yield的返回值 obj.__next__() # 从上一次停止的yield往下执行,在再遇到的yield时停止,拿到当前停止的yield的返回值,以此类推,直到无法获得下一个yield,抛StopIteration异常。 # 可以直接被for循环遍历 for v in fn(): print v 3.生成器表达式 res = (i for i in range(1,100000000) if i != 4) # 生成器表达式 print(res) # <generator object <genexpr> at 0x00000208F8E01E08> # 生成器对象不会主动执行任何一行代码 # 必须通过.__next__()触发代码的运行 4.总结: #1.有yield关键字的函数,函数名() 不是调用函数,而是生成得到 生成器对象,生成器对象就是迭代器对象,可以通过 __next__() 进行取值 #2.yield后面跟的值就是调用迭代器.__next__()方法你能得到的值 yield既可以返回一个值也可以返回多个值 并且多个值也是按照元组的形式返回 3.注意与普通函数关键字return进行区分 yield 1.帮你提供了一种自定义生成器方式 2.会帮你将函数的运行状态暂停住 3.可以返回值 与return之间异同点 相同点:都可以返回值,并且都可以返回多个 不同点: yield可以返回多次值,而return只能返回一次函数立即结束 yield还可以接受外部传入的值
1.匿名函数: # 1.匿名函数没有函数名 # 2.匿名函数的关键字采用lambda # 3.关键字 lambda 与标识函数功能体 : 之间一定是参数,所以省略() # 4.匿名还是没有函数体,只有返回值,所以函数体和返回值的return关键字都省略了 2.语法和注意点: lambda 参数: '返回值' # 注意: # 1.参数的使用和有名函数一样,六种形参都支持 # 2.返回值必须明确成一个值,可以为单个值对象,也可以为一个容器对象 a = lambda *args, **kwargs: '返回值1', '返回值2' print(a) # (<function <lambda> at 0x0000022D0B7E88C8>, '返回值2') # 返回值1 print(a[0]()) # 正确返回两个值: 主动构成成容器类型 lambda *args, **kwargs: ('返回值1', '返回值2')
# 1.max内部会遍历iter,将遍历结果一一传给lambda的参数x # 2.依据lambda的返回值作为比较条件,得到最大条件下的那个遍历值 # 3.对外返回最大的遍历值 max(iter, lambda x: x) # min工作原理一样,得到的是最小值
1.求绝对值:abs() print(abs(-11.11)) # 求绝对值 11.11 2.all() 和 any() l = [0,1,0] print(all(l)) # 只要有一个为False就返回False print(any(l)) # 只要有一个位True就返回True 3.进制转换int() 和 bin() oct() hex() print(int('1100',2)) # 第二个参数表示第一个参数是什么进制,然后转成十进制 # 10进制转二进制 # print(bin(12)) # 0b1100 0b表示后面的数字是二进制数 # 10进制转八进制 # print(oct(12)) # 0o14 0o表示后面的数字是八进制数 14 >>> 1*(8**1) + 4*(8**0)) # 10进制转16进制 # print(hex(12)) # 0xc 0x表示后面的数字是十六进制数 4.bool()判断布尔类型值 print(bool(1)) # True print(bool(0)) # False 5.bytes()转换为字节形式 s = 'hello' print(s.encode('utf-8')) # b'hello' print(bytes(s,encoding='utf-8')) # b'hello' 6.callable()判断对象是否可以被调用 l = [1,2,3] def index(): pass print(callable(l)) # False print(callable(index)) # True 7.char() 和 order() # print(chr(97)) # 将数字转换成ascii码表对应的字符 # print(ord('a')) # 将字符按照ascii表转成对应的数字 8.dir获取当前对象名称空间里面的名字 l = [1,2,3] print(dir(l)) # 列表形式 9.eval()和 exec() s = """ print('hello baby~') x = 1 y = 2 print(x + y) """ exec(s) # hello baby~ 3# name = 'jason' # s2 = """ # name # """ # print(eval(s2)) # json eval():eval不支持逻辑代码,只支持一些简单的python代码 exec():支持逻辑代码 10.isinstance (对象,数据类型)判断对象是否属于某个数据类型 # n = 1 # print(type(n)) # <class 'int'> # print(isinstance(n,list)) # False (判断对象是否属于某个数据类型) 11.pow()求次方 print(pow(2,3)) # 8(2的3次方) 12.round()四舍五入 print(round(3.4)) # 3(3.4四舍五入为3) 13.#enumerate(对象,开始值) 枚举 # l = ['a','b'] # for i,j in enumerate(l,1): # print(i,j) 14globals() 和 locals() def index(): username = '我是局部名称空间里面的username' # print(locals()) # 当前语句在哪个位置 就会返回哪个位置所存储的所有的名字 print(globals()) # 无论在哪 查看的都是全局名称空间
补充: format() 字符串格式化(https://www.cnblogs.com/jonm/p/8280968.html)
1.{}占位
1 >>> li = ['hoho',18] 2 >>> 'my name is {} ,age {}'.format('hoho',18) 3 'my name is hoho ,age 18' 4 >>> 'my name is {1} ,age {0}'.format(10,'hoho') 5 'my name is hoho ,age 10' 6 >>> 'my name is {1} ,age {0} {1}'.format(10,'hoho') 7 'my name is hoho ,age 10 hoho' 8 >>> 'my name is {} ,age {}'.format(*li) 9 'my name is hoho ,age 18'
2.指名道姓
1 >>> hash = {'name':'hoho','age':18}
2 >>> 'my name is {name},age is {age}'.format(name='hoho',age=19)
3 'my name is hoho,age is 19'
4 >>> 'my name is {name},age is {age}'.format(**hash)
5 'my name is hoho,age is 18'
3.索引
1 >>> li
2 ['hoho', 18]
3 >>> 'name is {0[0]} age is {0[1]}'.format(li)
4 'name is hoho age is 18
结合匿名函数的内置函数
1.max 和 min 函数 max(iter, key=lambda x: x) # 1.max内部会遍历iter,将遍历结果一一传给lambda的参数x # 2.依据lambda的返回值作为比较条件,得到最大条件下的那个遍历值 # 3.对外返回最大的遍历值 # min工作原理一样,得到的是最小值 d = { 'egon':30000, 'jason':88888888888, 'nick':3000, 'tank':1000 } print(max(d,key=lambda name:d[name])) 2.sort和sorted #1.sort() :仅对list对象进行排序,会改变list自身的顺序,没有返回值,即原地排序; list.sort(key=None, reverse=False) key :设置排序方法,或指定list中用于排序的元素; reverse :升降序排列,默认为升序排列; #2.sorted() :对所有可迭代对象进行排序,返回排序后的新对象,原对象保持不变; sorted(iterable, key=lambda x: x)) key :设置排序方法,或指定迭代对象中,用于排序的元素; reverse :升降序排列,默认为升序排列; 一维元素组成的迭代对象排序 3.map映射 l = [1,2,3,4,5,6] print(list('hello')) print(map(lambda x:x+5,l)) # <map object at 0x00000193A75A8400> print(list(map(lambda x:x+5,l))) # 基于for循环[6, 7, 8, 9, 10, 11] 3.filter过滤 l = [1,2,3,4,5,6] print(list(filter(lambda x:x != 3,l))) # 基于for循环[1, 2, 4, 5, 6] 4.reduce from functools import reduce l = [1,2,3,4,5,6] print(reduce(lambda x,y:x+y,l,19)) # 19初始值 第一个参数 # 当初始值不存在的情况下 按照下面的规律 # 第一次先获取两个元素 相加 # 之后每次获取一个与上一次相加的结果再相加 5.zip拉链 1 = [1,2,] l2 = ['jason','egon','tank'] l3 = ['a','b','c'] print(list(zip(l1,l2,l3))) # [(1, 'jason', 'a'), (2, 'egon', 'b')]
递归
# 递归: # 函数直接或间接调用本身,都称之为递归 # 回溯:找寻答案的过程 # 递推:推出结果的过程 # 前提条件: # 1.递归必须有出口 # 2.递归回溯递推的条件一定有规律 # 案例一:获得第 count 个人的年纪 def get_age(count): if count == 1: return 58 # 第 九...一 个人 - 2 age = get_age(count - 1) - 2 return age age = get_age(3) print(age) # 案例二:求n的阶乘 5! = 5 * 4 * 3 * 2 * 1 = 120 # 5! = 5 * 4! # 4! = 4 * 3! # 3! = 3 * 2! # 2! = 2 * 1! # 1! = 1 def jiecheng(n): if n == 1 or n == 0: return 1 ji = n * jiecheng(n - 1) return ji res = jiecheng(5) print(res)
补充
可以通过sys.setrecursionlimit()进行设置,但是一般默认不会超过3925-3929这个范围 sys.setrecursionlimit(3000) def foo(n): print(n) n += 1 foo(n) if __name__ == '__main__': foo(1) # 打印到998,所以Python的默认递归层数是998 # 但是可以通过设置,来改变递归层数的上限,但是也是上限也是有限制的. # 可以看到打印到2998