面向对象学习笔记(4)

part4

1.可迭代对象

通俗来讲就是可以被for循环的对象。

如何判断?

通过dir函数来查看类中定义好的所有方法. 在打印结果中. 寻找__iter__如果能找到. 那么这个类的对象就是一个可迭代对象.(list, tuple, dict, set)

如何让一个对象变成可迭代对象?

在类中实现__iter__方法且返回一个迭代器(生成器)

迭代器

迭代器最大的作用个就是统一了容器类型循环遍历的标准。

如果对象中有__iter__函数. 那么我们认为这个对象遵守了可迭代协议. 就可以获取到相应的迭代器. 这里的____iter____是帮助我们获取到对象的迭代器. 我们使用迭代器中的__next__来获取到一个迭代器中的元素.

s = "我爱北京天安门"
c1 = s.__iter__() # 获取迭代器
# c1 =iter(s) # 同上
print(c1.__next__()) # 使用迭代器进行迭代. 获取一个元素 我
print(c1.__next__()) # 爱
print(c1.__next__()) # 北
print(c1.__next__()) # 京
print(c1.__next__()) # 天
print(c1.__next__()) # 安
print(c1.__next__()) # 门
print(c.__next__())  # StopIteration 

for循环:

lst = [1,2,3]
lst_iter = lst.__iter__()
while True:
    try:
        i = lst_iter.__next__()
        print(i)
    except StopIteration:
        break

list可以一次性把迭代器中的内容全部拿空. 并装载在一个新列表中

s = "我要吃饭, 你吃不吃".__iter__()
print(list(s)) # ['我', '要', '吃', '饭', ',', ' ', '你', '吃', '不', '吃']

总结

Iterable: 可迭代对象. 内部包含__iter__函数

Iterator: 迭代器. 内部包含__iter__同时包含__next__

迭代器的特点:

  1. 节省内存.

  2. 惰性机制

  3. 不能反复, 只能向下执行.

生成器

生成器的本质就是迭代器. 在python中有两种方式来获取生成器:

  1. 通过生成器函数
  2. 通过生成器表达式来实现生成器
def func():
    print("111")
    return 222

ret = func()
print(ret)

将函数中的return换成yield就是生成器

def func():
    print("111")
    yield 222

ret = func()
print(ret)

由于函数中存在了yield. 那么这个函数就是一个生成器函数. 这个时候. 我们再执行这个函数的时候. 就不再是函数的执行了. 而是获取这个生成器. 可以直接使用__next__来执行该生成器

def func():
    print("111")
    yield 222
    print("333")
    yield 444

gener = func()
ret = gener.__next__()
print(ret)
ret2 = gener.__next__()
print(ret2)
ret3 = gener.__next__() # 最后一个yield执行完毕. 再次__next__()程序报错, 也就是说. 和return无关了.

2.约束

class Message:
    def send(self):
        print("发信息")

class Foo:
    pass

def func(arg):
    arg.send()
    
if 1 == 1:
    func(Message())
else:
    func(Foo()) # 虽然运行不到这里,但是会有bug
# 改进
# 用一个基类进行约束,起规范代码的作用
class Interface:
    def send(self):
        raise NotImplementedError()
        # 要求子类必须重写send方法,否则抛出NotImplementedError异常

class Message(Interface):
    def send(self):
        print("发信息")


class Email(Interface):
    def send(self):
        print("发邮件")

class Foo(Interface):
    pass


def func(arg):
    arg.send()

i = input()
if i == '1':
    func(Message())
elif i == '2':
    func(Email())
else:
    func(Foo())  

3.反射

根据字符串的形式,去某个对象中操作它的成员。

  1. getattr(对象,‘字符串’)

    根据字符串的形式去某个对象中获取对象的成员

  2. hasattr(对象,‘字符串’)

    根据字符串的形式去某个对象中判断是否有该成员

  3. setattr(对象,‘变量’,‘值’)

    根据字符串的形式去某个对象中设置对象的成员

  4. delattr(对象,‘变量’,‘值’)

    根据字符串的形式去某个对象中删除对象的成员

class Foo:
    def __init__(self,name):
        self.name = name

obj = Foo("a1")

v1 = obj.name
v1 = getattr(obj,'name') # 效果同上

obj.name = "b2"
setattr(obj,'name','b2') # 效果同上
class Foo:
    pass

obj = Foo()
obj.k1 = 999
setattr(obj,'k1',123)
# obj.k1 = 123
print(obj.k1)
delattr(obj,'k1')
print(obj.k1)
class Foo:
    def login(self):
        print("login")
    def register(self):
        print("register")

obj = Foo()

obj.login()
# 效果同上
method_name = getattr(obj,'login')
method_name()

obj.register()
# 效果同上
method_name = getattr(obj,'register')
method_name()

# 因此可以实现通过用户输入的字符串进行对象的调用
func_name = input("请输入方法名:")
getattr(obj,func_name)()
class Foo:
    def get(self):
        pass
obj = Foo()
if hasattr(obj,post):
    getattr(obj,'get')
# 或者
v1 = getattr(obj,'get',None)
print(v1)
# 存在get方法就会返回方法,否则返回none
# 目的:帮助判断类中是否真的存在该类方法。

补充

python一切皆对象

  • py文件
  • 对象

以后想要通过字符串的形式操作其内部成员都可以通过反射的机制实现。

4.模块

# # 传统:
# # import utils.mysql 同下
# from utils import mysql
# mysql.func()

import importlib
# 用字符串的形式导入模块
mysql = importlib.import_module('utils.mysql')
# 用字符串的形式去对象(模块)找到对应的成员
getattr(mysql,'func')()
# 优化一下
import importlib

path = 'utils.mysql.func'

module_path,func_name = path.rsplit('.',maxsplit=1)
module_object = importlib.import_module(module_path)
getattr(module_object,func_name)()
# 再升级一下
import importlib

middleware_classes = [
    'utils.mongo.Mongo',
    'utils.mysql.Mysql',
]
for item in middleware_classes:
    module_path,class_name = item.rsplit('.',maxsplit=1)
    module_object = importlib.import_module(module_path)
    cls = getattr(module_object,class_name)()
    cls.func()
# 开放封闭原则,对配置文件开放,对源代码封闭
# 尽量去改配置文件,降低耦合(代码的关联)
# 补充:
# 1.模块导入通过模块的名字进行成员的区分
# 2.多次导入重新加载
import xxx # 第一次加载:会加载一遍xxx中所有的内容
import xxx # 由于已经加载过了就不再加载

# 硬要重新加载
import importlib
import xxx
importlib.reload(xxx)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值