一.元类
# exec() 其字符串操作的变量默认为局部变量
# 参数1:字符串形式的命令
# 参数2:全局作用域字典,默认为globals(),
# 参数3:局部作用域字典,默认locals()
g = {'x': 1, 'y': 2}
l = {}
exec('''
global x,m
x = 10
m = 100
z = 3''',
g,
l)
# 对象的作用
# 1、都可以被引用
# 2、都可以当做函数的参数传入
# 3、可以当作函数的返回值
# 4、可以当作容器类的元素
# 类也是对象
# 类的的类就是元类,默认用class 定义的类的元类 为 type
# 定义类的方式一:class
class Foo:
pass
# 定义类的方式二:type
# 三要素:类名 基类 类的名称空间(def 之类的字符串内容)
class_name = ('Foo')
class_bases = (object,)
class_body = '''
def __init__(self):
self.name = 'hello'
def ppp(self):
print(self.name)
'''
class_dict={}
exec(class_body,globals(),class_dict)
Foo = type(class_name, class_bases, class_dict)
k = Foo()
k.ppp()
二.自定义类
class Mymeta(type):
# 控制类的创建行为
def __init__(cls, class_name, class_bases, class_dict):
print('mcs init')
if not class_name.istitle():
raise TypeError('类名首字母必须大写')
if '__doc__' not in class_dict or not class_dict['__doc__'].strip():
raise TypeError('类里面需要有注释')
super(Mymeta, cls).__init__(class_name, class_bases, class_dict)
# # 控制类的实例化行为
# def __call__(cls, *args, **kwargs):
# print('call')
# # 第一步:创建空对象obj
# obj = type.__new__(type, cls.__name__, cls.__bases__, dict(cls.__dict__)) #获得一个新式类,命名为obj
#
# # 第二步:初始化obj
# cls.__init__(obj, *args, **kwargs)
#
# # 第三步:返回obj
# return obj
# 单例模式
# 对于相同数据的对象, 同一时间只允许开辟同一内存地址
__instance = None
def __call__(cls, *args, **kwargs):
print('Meta call by', cls.__name__)
if not cls.__instance:
# 第一步:创建空对象
obj = type.__new__(type, cls.__name__, cls.__bases__, dict(cls.__dict__))
# 第二步:初始化
cls.__init__(obj, *args, **kwargs) # 调用此函数是类,没有实力化的(内存地址),因此需要手动传入第一参数
# 第三步:返回
cls.__instance = obj
return cls.__instance
class Foo(object,metaclass=Mymeta):
'''
fdsf
'''
def __init__(self):
print('self init')
pass
# __instance = None
# @classmethod
# def singleton(cls):
# if not cls.__instance:
# obj = cls()
# cls.__instance = obj
# return cls.__instance
f = Foo()