属性描述符是实现了特定协议的类,只要实现了__get__,__set__和__delete__三个方法中的任意一个,这个类就是描述符,它能实现对多个属性运用相同存取逻辑的一种方式,通俗来说就是:创建一个实例,作为另一个类的类属性。 除了使用类当作一个属性描述符,我们之前学习的 property(),就是可以轻松地为任意属性创建可用的描述符。创建 property() 的语法是 property(fget=None, fset=None, fdel=None, doc=None)
描述符查找顺序 • 当为数据描述符时, get__优先级高于__dict • 当为非数据描述符时,dict__优先级高于__get
就是创建类的类
用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)指一个重复的过程,每一次重复都是基于上一次结果而来,迭代提供了一种通用的不依赖索引的迭代取值方式 可迭代对象不一定是迭代器
判断是否可迭代 isinstance()–>用来判断对象是否是相应类型,与type()类似。可以通过iter()方法将可迭代的对象,转为迭代器。可迭代对象与迭代器区别 • 可用于for循环的都是可迭代类型 • 作用于next()都是迭代器类型 • list、dict、str等都是可迭代的但不是迭代器,因为next()函数无法调用它们。可以通过iter()函数将它们转为迭代器 • python的for循环本质就是通过不断调用next()函数实现的为什么要有生成器 列表所有数据都在内存中,如果有海量数据的话会非常消耗内存。 比如说:我们仅仅需要访问前面几个元素,但后面绝大多元素占用的内存就会浪费了。 那么生成器就是在循环的过程中根据算法不断推算出后续的元素,这样就不用创建整个完整的列表,从而节省大量的空间。 总而言之,就是当我们想要使用庞大数据,又想让它占用的空间少,那就使用生成器。 当一个函数中包含yield关键字,那么这个函数就不再是一个普通的函数,而是一个generator。 注意: • yield返回一个值,并且记住这个返回值的位置,下次遇到next()调用时,代码从yield的下一条语句开始执行。与return的差别是,return也是返回一个值,但是直接结束函数。