元类
code=' gloabl s s=1000 a=10 print(a) ' global_dic={} local_dic={} exec(code,global_dic,local_dic) # print(global_dic) # print(globals()) # print(local_dic)
# 要求你把你一个字符串中出现的名字 存储到一个名称空间中 # text = """ # def func(): # print("func run") # """ # l_dic = {} # exec(text,{},l_dic) # l_dic["func"]()
什么是元类
一切接对象
类的类就是元类
Person类是由type实例化产生的 默认情况下 所有类的元类都是type(object除外)
# """ # import abc # 抽象类 # # class Person(metaclass=type): # Person == type(..........) # def __init__(self,name,gender): # self.name = name # self.gender = gender # # def say_hi(self): # print("hello im am %s gender is %s" % (self.name,self.gender)) # # p = Person("jerry","男神") # # p.say_hi() # # # 函数对象 # # ls = [Person] # # print(ls[0]) # # # # def f1(cls): # # print(cls) # # # # f1(Person) # # print(type(p)) # print(type(Person)) # Person类是有type实例化产生的 一个类需要包含三个部分 类名称 他的父类 名称空间
# class_name = "myclass" # class_bases = (object,) # class_namespace = {} # # code = """ # school = "oldboy" # def hello(self): # print(self) # """ # # exec(code,{},class_namespace) # print(class_namespace) 从创建类的另一种方式 自己来实例化type类 # obj = type(class_name,class_bases,class_namespace)
#限制一个类必须拥有类注释 否则不允许创建类 class MyMeta(type): def __init__(self,cls_name,bases,namespace): if not self.__doc__: raise TypeError('必须包含类注释!!') super().__init__(cls_name,bases,namespace)#保证父类代码也走过了 class Animal(metaclass=MyMeta): ''' kjl ''' pass print(Animal.__doc__) # print(Animal) #a继承b 都拥有func #ORM框架中 要通过检测类的信息来创建表
type类中肯定有__init__方法 class MyMetaClass(type): # 创建类时 就会自动执行元类中的init方法 def __init__(self,class_name,bases,namespace): print("MyMetaClass init run") # 产生一个空的类对象 在调用MyMetaClass中的__init__方法 class ClassA(metaclass=MyMetaClass): # ClassA = type("ClassA",(,),{}) def __init__(self,name): self.name = name
# 创建出一个CLassA的类对象
class Test:
def __init__(self):
pass
t = Test() #实例化
# 1.创建一个对象的名称空间 空对象
# 2.执行__init__方法来为对象赋初始值
元类中init方法的执行:
class A: pass # print(A) # print(type(A)) namespace = {} namespace["name"] = "jack" cls = type("这是一个实例化Type产生的类",(object,),namespace) # # print(cls.name) # print(A)
一个类是通过实例化type类产生的
元类就是用于产生类的类
# 自定义一个元类
class MyMeta(type): # # 创建B这个类对象的时候回自动执行 def __init__(self,a,b,c): print('MyMeta init run') print(a) print(b) print(c) self.school='xxx' pass class B(metaclass=MyMeta):#B=MyMeta(B,'B',(object,),{....}) pass print(B.school)
# 必须保证类名大写开头
# class Meta1(type): # def __init__(self,clas_name,bases,namespace): # if not clas_name.istitle(): # raise TypeError("类名必须大写开头!") # # 命名方式 大驼峰 # class person(metaclass=Meta1): # pass
__call__方法的执行时机:
会在某个时间自动执行:调用对象时自动执行该函数
class MyMeta(type): # 会在类对象 准备实例化产生对象时执行 # 该函数可以控制实例化对象的过程 def __call__(self, *args, **kwargs): print("Mymeta call run!") # print(self) # print(args) # print(kwargs) #无论你要添加什么功能 只要覆盖了__call__ 就必须把下面两个步骤做了 #1.需要创建一个对象 obj = object.__new__(self) #2.调用对应init来初始化这个对象 self.__init__(obj,*args,**kwargs) return obj # super().__call__(*args,**kwargs) class Student(metaclass=MyMeta): def __init__(self,name): self.name = name pass s = Student("bgon") # 是为了创建并实例化一个Student类的对象 print(s)
__init__创建类对象的时候执行 控制类的创建过程
__call__实例化产生对象时执行 控制对象的创建过程
单例模式:
一种设计模式,MVVM MVC MTV
常推荐书籍见设计模式
要保证一个类只能有一个实例(单例)
目的是为了节省内存开销
如果两个对象的数据一模一样 就没有必要创建新对象 直接使用已有的即可
场景:当一个类的所有实例数据都完全相同时,则应该设计为实例
音乐播放器类 实例化产生播放器对象
单例的实现方式:
自定义元类 覆盖__call__ 添加判断逻辑 保证只能实例化一个对象
class MySingleton(type): obj = None def __call__(self, *args, **kwargs): if not self.obj: # 创建空对象 obj = object.__new__(self) # 调用初始化方法 self.__init__(obj, *args, **kwargs) self.obj = obj return self.obj class Player(metaclass=MySingleton): # 默认为空 obj = None def __init__(self): print("创建了一个播放器对象....") def play(self,path): self.stop() print("playing...",path) def stop(self): print("stop music") # 用于获取播放器对象 @classmethod def get_player(cls): if not cls.obj: print("创建播放器...") cls.obj = cls() return cls.obj # p = Player("给我一杯忘情水.mp3") # p.play() # # # p.stop() # p1 = Player("回首掏.mp3") # p1.play() # p = Player() # p.play("一杯忘情水.") # # p1 = Player.get_player() p1.play("爱你一万年1.") p2 = Player.get_player() p2.play("爱你一万年2.") # 上述代码 有bug 可以通过直接调用类 来产生新对象 Player().play("我的滑板鞋!")
存在元类时的属性查找:
# class Meta(type): # s = 1000 # # # class A: # s = 1 # pass # class B(A,metaclass=Meta): # # s = 2 # pass # # b = B() # # b.s = 3 # # print(b.s) class Mymeta(type): #只有继承了type类才能称之为一个元类,否则就是一个普通的自定义类 n=444 class Bar(object): # n = 333 pass class Foo(Bar): # n=222 pass class Teacher(Foo,metaclass=Mymeta): # n=111 pass print(Teacher.n)
查找顺序:
先自己 在父类 在元类