Loading

Python基础3(迭代器 生成器 装饰器)

迭代器

迭代器,一种工具

可迭代对象:

list,dict,str,set,tuple -- 可迭代对象 使用灵活

查看是否可迭代

方式一:

list.__iter__()

方式二:

查看源码

方式三:

print(dir(list))

官方声明只要具有__iter__()方法的就是可迭代对象

优缺点

1.优点

1.1 使用灵活

1.2 直接查看值

2.缺点

2.1 消耗内存

迭代器

官方声明只要具有__iter__()方法 next()方法就是迭代器

句柄"f"是个迭代器
f = open("xxxx","w")
f.__iter__()
f.__next__()

lst = [1,2,3,4,6]
new_list = lst.__iter__()  #将可迭代对象转换成迭代器
new_list.__iter__()
new_list.__next__()

s = "123434"
new_s = s.__iter__()       #将可迭代对象转换成迭代器
print(new_s)
new_s.__iter__()
new_s.__next__()

new_s = s.__iter__()       #将可迭代对象转换成迭代器
print(new_s)
new_s.__iter__()
print(new_s.__next__())
print(new_s.__next__())
print(new_s.__next__())

s = "12343"               # 更改版for的本质
s = [1,2,3,4,5,7]
count = len(s)
new_s = s.__iter__()
while count:
    print(new_s.__next__())
    count -= 1

s = "12345"
new_s = s.__iter__()
while True:
    try:
        print(new_s.__next__())   # for真实本质
    except StopIteration:
        break
        
# except Exception:
#     print("我是万能的!")
#     break

递归

定义

1.自己调用自己 (不断调用自己本身) -- 死递归

2.有明确的终止条件

满足以上两个才是有效递归

递:一直执行直到碰到结束条件

归:从结束条件开始往回退

官方声明: 最大层次1000,实际测试 998/997

示例:      猜3
def age(n): # 1,2,3
    if n == 3:
        return "猜对了"
    else:
        return age(n+1)
print(age(1))
分解

def age2(n):
    if n == 3:
        return "猜对了"

def age1(n):
    if n == 3:
        return "猜对了"
    else:
        age2(n+1)

def age(n):
    if n == 3:
        return "猜对了"
    else:
        age1(n+1)
age(1)

总结

可迭代对象: 优点:使用灵活,可以直接查看值 缺点:占内存,不能迭代取值

迭代器: 优点:节省内存,惰性机制 缺点:使用不灵活,操作比较繁琐,不能直接查看元素

迭代器的特性: 1.一次性的(用完就没有了) 2.不能逆行(不能后退) 3.惰性机制(节省内存)

什么是可迭代对象: 具有很多私有方法,具有__iter__()方法的就是一个可迭代对象

什么是迭代器: 具有__iter__()和__next__()方法的就是迭代器

迭代器什么时候使用:当容器中数据量较多的时候使用迭代器

生成器

迭代器和生成器的区别:

迭代器是Python中内置的一种节省空间的工具

生成器的本质就是一个迭代器

迭代器是Python自带的

生成器是咱们(程序员)写得

定义一个生成器:

基于函数,
函数体中存在yield就是一个生成器
函数名() 就是产生一个生成器
def func():
    print(123)
    return "你好"
func()

def func():
    if 3>2:
        yield "你好"   #停
    if 4>2:
        yield "我好"
    yield "大家好"
g = func() # 产生一个生成器
print(g.__next__())
print(g.__next__())
print(g.__next__())
for i in g:
    print(i)
for 循环的本质
while True:              
    try:
        print(g.__next__())
        except StopIterration:
            break

生成器的优点和注意事项

节省空间 -- 惰性机制

不能逆行

一次性

一个next对应一个yield

yield 能够进行返回内容,还能够返回多次

yield能够临时停止循环

yield 能够记录执行的位置

输出方式

def foo():
    for i in range(10):
        pass
        yield i
    count = 1
    while True:
        yield count
        count += 1
g = foo()
print(next(g))  # ---- 推荐使用
print(next(g))
print(next(g))
print(next(g))
print(next(g))

### 坑
如果不用变量接受,直接输出
print(foo().__next__())
print(foo().__next__())
一直循环输出#9

生成器应用场景

def func():
    lst = []
    for i in range(100000):
        lst.append(i)
    return  lst
print(func())
# 一次性打印全部结果,数据过大时特别消耗内存

def func():
    for i in range(100000):
        yield i
g = func()
for i in range(50):
    print(next(g))
# 每次打印可选的一部分,不用的部分不打印,节省空间
 yield from
 将一个可迭代对象的元素逐个返回

def func():
    lst = ["牛羊配","老奶奶花生米","卫龙","瞎扯淡","米老头","老干妈"]
    for i in lst:
        yield i
g = func()
print(next(g))
print(next(g))
print(next(g))
print(next(g))
print(next(g))
# 牛羊配
# 老奶奶花生米
# 卫龙
# 瞎扯淡
# 米老头

def func():
    lst1 = ["牛羊配","老奶奶花生米","卫龙","虾扯蛋","米老头","老干妈"]
    lst2 = ["小浣熊","老干爹","亲嘴烧","麻辣烫","黄焖鸡","井盖"]
    yield from lst1
    yield from lst2
g = func()
print(next(g))
print(next(g))
print(next(g))
print(next(g))

# 牛羊配
# 老奶奶花生米
# 卫龙
# 虾扯蛋
# 所以循环第一个列表直到全部打印再循环第二个

推导式

循环模式

lst = []for i in range(20):   
lst.append(i)print(lst)
转换list推导式
print([i for i in range(20)])
[变量 for i in range(20)]

筛选模式

lst = []for i in range(20): 
if i % 2 == 0:       
lst.append(i)print(lst)
转换成list表达式
[print([i for i in range(20) if i % 2 == 0])]
[变量(加工后的变量) for循环 加工方式]

其他例子:
print([i for i in range(50)f i % 2 ==1])print([i for i in range(1,50,2)])

循环模式

生成器:
g = (i for i in range(20))
	print(next(g))
	print(next(g))
	print(next(g))
# 0 1 2 转换成列表
print(list((i for i in range(20))))

字典推导式(了解)

print({i:i+1 for i in range(10)})
print({i:i+1 for i in range(10) if i % 2 == 0})
{键:值 for循环 加工条件}

集合推导式(了解)

print({i for i in range(10)})
print({i for i in range(10) if i % 2 == 0})

总结:

list:
[变量(加工后的变量) for循环]
[变量(加工后的变量) for循环 加工条件]

生成器表达式:
(变量(加工后的变量) for循环)
(变量(加工后的变量) for循环 加工条件)

字典推导式:
{键:值 for循环 加工条件}

集合推导式:
{变量(加工后的变量) for循环 加工条件}

闭包

def func():   
	a = 1  
	def f1():   
		def foo():   
		print(a)     
		return foo   
	return f1ret = func()   
# 或者直接 
func()()()a = ret()a()
# 在嵌套函数内,使用非全局变量(且不是本层变量) -- 就是闭包# print(foo()()().__closure__)判断是否闭包了解:print(ret.__code__.co_freevars)
# 获取的是自由变量print(ret.__code__.co_varnames)# 获取的是局部变量闭包的作用:1.保证数据的安全性2.装饰器

装饰器

定义:

用来装饰的工具

在不改变源代码及调用方式的基础上额外增加新的功能

开放封闭原则:

扩展是开放的(增加新功能)

修改源码是封闭的(修改已经实现的功能)

版一:

import time
start_time = time.time()
def func():
    time.sleep(2)
    print("asdf")
func()
print(time.time() - start_time)

start_time = time.time()
def foo():
    time.sleep(3)
    print("qwer")
foo()
print(time.time() - start_time)

版二:

def times(f):
    start_time = time.time()
    f()
    print(time.time() - start_time)

def foo():
    time.sleep(3)
    print("asdf")

s = foo
foo = times
foo(s)

版三(初识版装饰器):

def times(f):
    def inner():
        start_time = time.time()
        f()
        print(time.time() - start_time)
    return inner
def foo():
    time.sleep(1)
    print("asdf")
foo = times(foo)
foo()

版四(第二版装饰器):

def wrapper():   
	def inner():  
		print(1)   
		return innerprint(wrapper()())
		def wrapper(f):   
			def inner():           
				f()                 
	return inner      
		def func():         
		print("123456")   
        
func = wrapper(func)       
func()                          

low版

import timedef wrapper(f):  
def inner(*args,**kwargs):    
	start_time = time.time()       
f(*args,**kwargs)       
	print(time.time() - start_time)  
	return innerdef func(*args,**kwargs):  
print(f"这是{args,kwargs}函数")    
time.sleep(2)
func = wrapper(func)
func("alex","wusir")

高级版:

import timedef wrapper(f):   
def inner(*args,**kwargs):   
	start_time = time.time()      
f(*args,**kwargs)        
	print(time.time() - start_time)  
	return inner@wrapperdef func(*args,**kwargs): 
print(f"这是{args,kwargs}函数")  
time.sleep(2)

@wrapperdef
foo(*args,**kwargs):  
print(f"这是{args,kwargs}函数,123456") 
time.sleep(3)
func("alex","ahfe")
foo("alex1","faikewfhn")

标准版:

def func(a):  
	#a是要被装饰的函数名 
	def foo(*args,**kwargs):   
		"装饰之前的操作"     
		ret = a(*args,**kwargs)    
		"装饰之后的操作"    
		return ret   
	return foo
@funcdef 
f1(*args,**kwargs): 
print(f"这是一个{args}")  
return "我可以返回了"f1(1,2,3,34,4,5)

语法糖

语法糖必须放在被装饰的函数正上方

@wrapper  就等于   func = wrapper(func)
@wrapper  就等于   foo = wrapper(foo)

1.有参装饰器

基本版

def auth(argv):
    def wrapper(f):
        def inner(*args,**kwargs):
            f(*args,**kwargs)
        return inner
    return wrapper

示例:

login_dic = {"username": None, "flag": False}
msg = """请选择app:QQ微信抖音邮箱"""
chose = input(msg).upper()
def auth(argv):    
	def wrapper(f):     
		def inner(*args,**kwargs):    
			if login_dic["flag"]:    
				f(*args,**kwargs)        
			else:          
		if argv == "QQ":         
print("欢迎登陆QQ")  
user = input("请输入账号:")      
password = input("请输入密码:")
if user == "alex" and password == "alex123":   
login_dic["flag"] = True                 
login_dic["username"] = user               
f(*args,**kwargs)               
else:                
print("账号或者密码错误")  
elif argv == "微信":      
print("欢迎登陆微信")     
user = input("请输入账号:")  
password = input("请输入密码:")   
if user == "alex123" and password == "alex123456":  
login_dic["flag"] = True                     
login_dic["username"] = user                     
f(*args, **kwargs)   
else:                  
print("账号或者密码错误")     
elif argv == "抖音":       
print("欢迎登陆抖音")         
user = input("请输入账号:") 
password = input("请输入密码:")  
if user == "alex456" and password == "alex456123":     
login_dic["flag"] = True             
login_dic["username"] = user       
f(*args, **kwargs)            
else:                   
print("账号或者密码错误")    
else:                
print("欢迎登陆邮箱")       
user = input("请输入账号:")     
password = input("请输入密码:")       
if user == "alex@qq.com" and password == "alex123":       
login_dic["flag"] = True            
login_dic["username"] = user    
f(*args, **kwargs)        
else:   
print("账号或者密码错误")     
return inner   
return wrapper@auth(chose)
def foo():
print("这是一个被装饰的函数")
foo()
# @auth(chose) 相等于以下两行代码的解构
# wrapper = auth(chose)# foo = wrapper(foo)

多个装饰器装饰一个函数

def wrapper1(func):
    def inner1(*args,**kwargs):
        print(1)
        func(*args,**kwargs)
        print(11)
    return inner1

def wrapper2(func):
    def inner2(*args,**kwargs):
        print(2)
        func(*args,**kwargs)
        print(22)
    return inner2

def wrapper3(func):
    def inner3(*args,**kwargs):
        print(3)
        func(*args,**kwargs)
        print(33)
    return inner3

@wrapper3
@wrapper2
@wrapper1
def foo():
    print("这是一个被装饰的函数")

foo()

# 3
# 2
# 1
# 这是一个被装饰的函数
# 11
# 22
# 33

元类type

type  获取对象从属于的类

python 中 一切皆对象, 类在某种意义上也是一个对象, python中自己定义的类, 以及大部分内置类, 都是由type元类(构建类)实例化得来的

type 与 object 的关系

print(type(object)) 
object类是type类的一个实例
object类是type类的父类

反射

程序对自己内部代码的一种自省方式

反射是什么

通过字符串去操作对象的方式

具体方法

hasattr
getattr
setattr
delattr

反射角度

实例对象

# obj = A('赵海狗',47)
class A:
    country = "中国"
    def __init__(self, name, age):
        self.name = name
        self.age = age
    def func(self):
        print("in A func")

obj = A("赵海狗", 47)

print(hasattr(obj,"name"))
print(hasattr(obj,"country"))
print(hasattr(obj,"func"))

print(getattr(obj,"name"))
print(getattr(obj,"country"))
f = getattr(obj,"func")
f()
print(getattr(obj, "sex", None))

obj.sex = "公"
setattr(obj, "sex", "公")
print(obj.__dict__)

delattr(obj,"name")
print(obj.__dict__)

class A:
    country = "中国"
    def __init__(self, name, age):
        self.name = name
        self.age = age
    def func(self):
        print(self)
        print("in A func")

if hasattr(A,"country"):
    print(getattr(A, "country"))
if hasattr(A, "func"):
    obj = A("赵海狗", 26)
    getattr(obj, "func")()
    # 和下方方法一样 区别在于一个对象反射,一个类反射,一个不用传参, 一个需要传参
    getattr(A, "func")(obj)

本模块

a = 666
def func1():
    print("in 本模块这个对象")

import sys
print(sys.modules[__name__])
print(getattr(sys.modules[__name__], "a"))
getattr(sys.modules[__name__], "func1")()
练习题
1.使用反射依次调用所有函数
def func1():
    print("in func1")
def func2():
    print("in func2")
def func3():
    print("in func3")
def func4():
    print("in func4")

import sys
func_lst = [f"func{i}" for i in range(1,5)]
for func in func_lst:
    getattr(sys.modules[__name__], func)()
2.使用反射做出一个注册登录系统
class User:
    user_list = [("login", "登录"),("register", "注册"),("save", "存储")]

    def login(self):
        print("欢迎来到登录页面")
    def register(self):
        print("欢迎来到注册页面")
    def save(self):
        print("欢迎来到存储页面")

while 1:
    choose = input("请输入序号: \n: 登录\n2: 注册\n3: 存储\n").strip()
    obj = User()
    getattr(obj, obj.user_list[int(choose)-1][0])()

其他模块

tbjx文件
name = "太白金星"
def func():
    print("in tbjx func")

class C:
    area = "北京"
    def __init__(self, name):
        self.name = name
    def func(self):
        print("in B func")
import tbjx
print(getattr(tbjx,"name"))
getattr(tbjx, "func")()
import tbjx
# 1. 找到tbjx对象 的C类,实例化一个对象.
obj = getattr(tbjx, "C")("太白金星")
print(obj.__dict__)
# 2. 找到tbjx对象 的C类,通过对C类这个对象使用反射取到area.
f = getattr(getattr(tbjx, "C"), "area")
print(f)
# 3. 找到tbjx对象 的C类,实例化一个对象,对对象进行反射取值.
print(getattr(obj, "name"))
posted @ 2021-02-24 21:01  丨渍丨  阅读(68)  评论(0)    收藏  举报