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)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#限制一个类必须拥有类注释 否则不允许创建类
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__ 添加判断逻辑 保证只能实例化一个对象
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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)
查找顺序:
先自己 在父类 在元类