可迭代对象 迭代器对象 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__()方法得到的还是迭代器对象本身(******)

三 for循环迭代器的本质原理

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')

max和min结合匿名工作原理

# 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