Python三大器:装饰器、迭代器、生成器

dir()

  1. 查看对象的属性和方法:对于任何给定的Python对象或类,dir()可以帮助你快速了解它有哪些可用的属性和方法。这对于学习新的库或框架时特别有用,可以快速了解对象提供了哪些功能。
  2. 调试和探索:当你在探索一个新的或不熟悉的Python对象时,dir()可以帮助你发现可以调用的方法或者可以访问的属性,这对于调试和理解对象的内部结构非常有帮助。
  3. 交互式使用:在Python的交互式环境中(如Python shell或Jupyter notebook),dir()是探索对象的快捷方式之一。它可以让你快速看到一个对象的“目录”,从而探索其功能。
  4. 反射编程dir()函数也可以用于反射编程(introspection programming),即代码能够检查并动态地访问其他模块或函数的属性。这在动态加载模块或者动态调用方法时非常有用。
# 示例:使用dir()查看列表的方法
my_list = [1, 2, 3]
print(dir(my_list))

# 输出示例(输出会根据Python版本有所不同,以下为示例输出):
# ['__add__', '__class__', '__contains__', '__delattr__', ..., 'append', 'clear', 'copy', 'count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort'...]

迭代器(Iterators)

  迭代器是一个可以记住遍历的位置的对象。迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束。迭代器只能往前不会后退。迭代器有两个基本的方法:iter() 和 next()。字符串、列表或元组对象都可用于创建迭代器:

my_list = [1, 2, 3, 4]
my_iter = iter(my_list)

print(next(my_iter))  # 输出 1
print(next(my_iter))  # 输出 2
  • for 循环内部大致的工作机制
lst = ['张无忌', '谢广坤', '张晨晨']

it = lst.__iter__()
while True:
    try:
        obj = it.__next__()
        prit(obj)
    except StopIteration:
        break
        
# for循环
for item in lst:
    print(item)
迭代器总结
  • Iterable:可迭代对象,内部宝行__iter__()函数
  • Iterator:迭代器,内部包含__iter__()同时包含__next__()
  • 迭代器的特点:
    1. 节省内存
    2. 惰性机制
    3. 不能反复,只能向下执行(即无法后退)

生成器(Generators)

def func():
    print(123)
    yield "你好"
  • 当函数中有yield,该函数就是一个生成器函数,yield也有返回的意思
  • 生成器函数在被执行时,实际上是创建一个生成器出来
  • 生成器函数.__next__()可以让生成器函数执行到下一个yield结束
  • 当后面没有yield之后,再次__next__()会报错StopIteration
  • 深坑:要值的时候才拿值(惰性机制-生成器本质上就是迭代器)
def func():
    print(11)
    yeild "你好"
    print(22)
    yeild "你不好"
    print(33)
    yeild "你很好"
gen = func() # 此时控制台没有打印
r = gen.__next__()
print(r) # 控制台打印:11\n你好
r2 = gen.__next__()
print(r2) # 控制台打印:22\n你不好
r3 = gen.__next__()
print(r3) # 控制台打印:33\n你很好

生成器最大作用就是节省内存

def order():
    lst = []
    for i in range(10000):
        lst.append(f'衣服{i}')
    return lst # 列表占内存
lst = order()
print(lst)
def order():
    for i in range(10000):
        yield f'衣服{i}'
        
g = order()
print(g.__next__())
print(g.__next__())
print(g.__next__())
print(g.__next__())
def order():
    lst = []
    for i in range(10000):
        lst.append(f'衣服{i}')
        if len(lst) == 50:
            yield lst
            lst = []

g = order()
print(g.__next__()) # 衣服0~衣服49
print(g.__next__()) # 衣服50~衣服99
send()
  • __next__异同
    • 相同点:可以执行到下一个yield
    • 不同点:send可以给上一个yield位置传值
  • 第一次执行必须用next,不能用send
def func():
    print("111")
    a = yield "酥饼"
    print("222", a)
    b = yield "韭菜盒子"
    print("333", b)
    yield "红酒"
g = func()
r1 = g.__next__()
print(r1)
r2 = g.send("哈哈哈") # send给上一个yield位置传递“哈哈哈”
print(r2)

# 打印结果
# 111
# 酥饼
# 222 哈哈哈
# 韭菜盒子

各种推导式

  • 列表推导式的基本语法: [结果 for循环 if 条件]
# 常规写法
lst = []
for i in range(1, 11):
    lst.append(i)
print(lst)

# 推导式写法
lst = [i for i in range(1,11)]

## 把1-10中所有奇数添加到列表
lst = [i for i in range(1, 11) if i %2 == 1]

## 把1-10中所有奇数的平方添加到列表
lst = [i**2  for i in range(1,11) if i % 2 == 1]

## python x 1 ~ python x 255
lst = ["python x %s" % i for i in range(1, 256)]
  • 字典推导式的基本语法:{key: value for循环 if条件}
lst = ['你好', '你不好', '你很好']
d = {i: lst[i] for i in range(len(lst))}
  • 集合推导式的基本语法:{key for循环 if条件}
lst = ['张无忌', '张三丰', '周芷若']
s = {item for item in lst}

Python中没有元组推导式

  • 生成器推导式的基本语法:(结果 for循环 if条件)
g = (i for i in range(5))
print(g)
print(g.__next__())
print(g.__next__())
print(g.__next__())
  • 拿空生成器中的数据
#直接for循环
g = (i for i in range(5))
print(g)
for item in g:
    print(item)
    
# 可以使用list、tuple、set
g = (i for i in range(5))
print(g)
print(list(g))  # tuple(g)、set(g)

匿名函数

  • 语法:函数名 = lambda 参数: 返回值

为了解决一些简单的需求而设计的一句话函数

# 计算n的n次方:
def func(n):
    return n**n
print(func(10))

# 匿名函数实现
f = lambda n: n**n
print(f(10))
  1. 函数的参数可以有多个,多个参数之间用逗号隔开
  2. 匿名函数不管多复杂,只能写一行,且逻辑结束后直接返回数据
  3. 返回值和正常函数一样,可以是任意数据类型
  • 匿名函数并不是说一定没有名字,这里前面的变量就是一个函数名,说他是匿名函数原因是我们通过__name__查看的时候是没有名字的,统一都叫lambda,在调用的时候没有什么特别之处,像正常函数调用即可

评论