# 元类
# 说python当中一切皆对象,
# 用class关键字定义的类其实本质也是一个对象。
# class Foo:
# pass
# 说Foo是一个对象的话,对象肯定是由一个类实例化而来的。
# 也就是说在class的时候,调class关键字的时候,必然是这个关键字去调了一个类的类,类的类就称之为元类。
# 就是调了一个元类加括号实例化,元类加括号的结果就是用class定义的类
# class Foo: # Foo = 元类()
# pass
# 所以说元类就是负责产生类的那一个类,是类的老祖宗。
# 1.什么是元类?
# 在python中一切皆对象,那么我们用class关键字定义的类本身也是一个对象
# 负责产生该对象的类称之为元类,即元类可以简称为类的类
# 2.为何要用元类?
# 什么情况下用元类?
# 元类是负责产生类的,可以控制类的产生过程,还可以控制对象的产生过程。
# 什么叫对象的产生过程?
# class Foo:
# pass
# Foo()
# 对Foo这个类的产生控制,以及对调用Foo的这个过程的控制,因为调用Foo的过程就是产生Foo对象的过程
# 3.如何用元类
# 3.1 需要储备几点知识
# 第一点知识: exec()这个内置函数
# exec()这个内置函数用来干什么的呢?
# 将一个字符串中的代码提出出来运行一下
cmd = '''
x=1
y=2
print('我爱老婆杨静,哈哈哈')
'''
local_dic = {}
# exec(cmd,)
# 模拟的就是执行python代码的过程,会产生一个名字,必然往名称空间里面去丢
# 名称空间的格式是以字典的形式展现的
# 所以造两个名称空间,一个全局名称空间
# 怎么查看全局的名称空间:
# print(globals())
# 造一个空字典
# local_dic = {}
# exec(第一个参数是你的字符串,第二个参数是你要引用的那个全局作用域(不需要定义个空字典就好了),第三个是local_dic)
exec(cmd,{},local_dic)
print(local_dic)
# 会发生什么是呢?
# exec会执行字符串中的代码,将执行过程中产生的名字都往local_dic = {}里面丢
# exec干了一件事:给你一段代码,只要执行过程中产生名字都丢到一个名称空间字典里面去。
# 函数也可以!!
# 函数体代码提取出来
# def func():
# x= 1
# y=2
# print('杨静爱老公张仁国,哈哈哈')
# cmd = '''
# x = 1
# y = 2
# print('杨静爱老公张仁国,哈哈哈')
# '''
# func_dic = {}
# exec(cmd,{},func_dic)
#
# print(func_dic)
# 类也可以!!
# 类体代码提取出来
cmd = '''
x=1
def func():
y = 2
'''
class_dic = {}
exec(cmd,{},class_dic)
print(class_dic)
# 类体执行过程中产生的名字都丢到名称空间里面去了
# 这是模拟了类创建过程中类定义阶段造名称空间那一步操作
# 用这个功能干嘛使?
# 可以用来模拟造名称空间这个过程。
# 3.2创建类过程当中有几个关键的要素
# 创建类的方法有两种
# 第一种class关键字去创建,用的是默认的元类:type
# class People():
# country = 'china'
# def __init__(self,name,age):
# self.name = name
# self.age = age
#
# def eat(self):
# print('%s is eating'%self.name)
# # 查看People的类是谁:
# print(type(People))
# # <class 'type'>
#
# print(People)
# obj = People('zrg',24)
# print(obj)
# obj.eat()
# print(type(obj))
# 大前提:如果说类也是对象的话,那么用class关键字去创建类的过程也是一个实例化的过程
# 该实例化的目的是为了得到一个类,调用的是元类
# 调用的元类又分为两种:
# 一种是默认的元类type
# 另一种是自定义的
# 默认的元类的造类的过程:
# 类的名字 class_name
# 类的基类 class_bases
# 类的名称空间 class_dic
#
# class_name = 'People' #类名必须是字符串形式
# class_bases = (object,) #不继承任何类默认就是object逗号才叫一个元组
# class_dic = {} #最关键的最难得,类的名称空间一个字典的形式
# 类的名称空间从何而来----->从类体的执行而来,而类体就是一堆字符串
# class_body = '''
# country = 'china'
# def __init__(self,name,age):
# self.name = name
# self.age = age
#
# def eat(self):
# print('%s is eating'%self.name)
# '''
# 要做的事根据类体代码得到字典让他里面有值,就用exec函数
# exec(class_body,{},class_dic)
# 查看造类的三要素
# print(class_name)
# print(class_bases)
# print(class_dic)
# type(类名,基类,类的名称空间)得的结果给一个变量名People1
# People1 = type(class_name,class_bases,class_dic)
# print(People1)
# obj1 = People1('yj',25)
# obj1.eat()