python进阶第四天

元类及迭代器生成器


01.__getattr__和__getattribute__魔法函数

  • __getattr__是当类调用一个不存在的属性时才会调用getattr魔法函数,他传入的值item就是你这个调用的不存在的值。访问的属性不存在,自动触发这个魔术方法。
  • getattribute__则是无条件的优先执行,所以如果不是特殊情况最好不要用__getattribute

02.属性描述符

属性描述符是实现了特定协议的类,只要实现了__get__,__set__和__delete__三个方法中的任意一个,这个类就是描述符,它能实现对多个属性运用相同存取逻辑的一种方式,通俗来说就是:创建一个实例,作为另一个类的类属性。
除了使用类当作一个属性描述符,我们之前学习的 property(),就是可以轻松地为任意属性创建可用的描述符。创建 property() 的语法是 property(fget=None, fset=None, fdel=None, doc=None)

描述符查找顺序
• 当为数据描述符时, get__优先级高于__dict
• 当为非数据描述符时,dict__优先级高于__get


03.元类

就是创建类的类

  • 用type创建元类
# 定义魔法方法
def __init__(self, name):
    self.name = name

# 添加实例方法 slef
def info(self):
    return self.age

# 添加静态方法 无需self 与 cls 参数
@staticmethod
def stat_func():
    print("i am staticmethod")

# 添加类方法 注意一定有cls参数
@classmethod
def cls_method(cls):
    print("classmethod")

User = type("User", (), {"age":18, "__init__":__init__, "info":info, "stat_func":stat_func})
# print(User)     # <class '__main__.User'>

zs = User("C")       # 实例化
# print(zs)       # <__main__.User object at 0x000002B6086BE860>
print(zs.age)     # 类属性
print(zs.name)    # 实例属性

zs_age = zs.info()  # 访问 实例方法
print(zs_age)

zs.stat_func()      # 访问静态方法

type也可以继承

class BaseClass(object):
    def test(self):
        return "baseclass test"

    def test1(self):
        return "baseclass test1"

class BaseClass2(object):
    def test(self):
        return "baseclass2 test"


User = type("User",(BaseClass2, BaseClass),{"name":"oy"})  # 元组必须打逗号 否则报错
oy = User()
print(oy.test())        # 访问父类的test方法
print(oy.test1())  
  • metaclass属性
    如果一个类中定义了__metalass__ = xxx,Python就会用元类的方式来创建类,就可以控制类的创建行为
    比如,以下代码,再不改变类属性的抒写情况下,将属性名规定为大写访问
# 2.创建upper_attr函数
def upper_attr(cls_name, cls_parents, cls_attr):
    # print(cls_name)         # MyClass,当前指定的类名
    # print(cls_parents)      # (<class 'object'>,)
    # print(cls_attr)         # {'__module__': '__main__', '__qualname__': 'MyClass', 'name': 'ls'}
    """
    4.将属性名规定为大写访问
    - 遍历取出属性
    - 如果属性是非_开头的
    - 将其转为大写
    """
    new_attr = {}
    for name, value in cls_attr.items():
        # print(name)
        # print(value)
        if not name.startswith("_"): #判断是否以下划线开头
            new_attr[name.upper()] = value.upper()

    # 5.返回type创建的类
    return type(cls_name, cls_parents, new_attr)

    # # 3.返回type创建的类
    # return type(cls_name, cls_parents, cls_attr)

# 1.创建MyClass类,指定metaclass=upper_attr
class MyClass(object, metaclass=upper_attr):
    name = "ls"

mc = MyClass()
print(mc.NAME)

04.迭代器

指一个重复的过程,每一次重复都是基于上一次结果而来,迭代提供了一种通用的不依赖索引的迭代取值方式
可迭代对象不一定是迭代器

  • 判断是否可迭代
    isinstance()–>用来判断对象是否是相应类型,与type()类似。
  • 可以通过iter()方法将可迭代的对象,转为迭代器。
  • 可迭代对象与迭代器区别
    • 可用于for循环的都是可迭代类型
    • 作用于next()都是迭代器类型
    • list、dict、str等都是可迭代的但不是迭代器,因为next()函数无法调用它们。可以通过iter()函数将它们转为迭代器
    • python的for循环本质就是通过不断调用next()函数实现的

05.生成器

为什么要有生成器
列表所有数据都在内存中,如果有海量数据的话会非常消耗内存。
比如说:我们仅仅需要访问前面几个元素,但后面绝大多元素占用的内存就会浪费了。
那么生成器就是在循环的过程中根据算法不断推算出后续的元素,这样就不用创建整个完整的列表,从而节省大量的空间。
总而言之,就是当我们想要使用庞大数据,又想让它占用的空间少,那就使用生成器。
当一个函数中包含yield关键字,那么这个函数就不再是一个普通的函数,而是一个generator。
注意:
• yield返回一个值,并且记住这个返回值的位置,下次遇到next()调用时,代码从yield的下一条语句开始执行。与return的差别是,return也是返回一个值,但是直接结束函数。


06.迭代器与生成器

  • 生成器能做到迭代器能做的所有事
  • 而且因为生成器自动创建了iter()和next()方法,生成器显得简洁,而且高效
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值