exec模块的补充
1.定义
python中的内置模块
2.作用
可以把 '字符串' 形式的python代码,添加到全局名称空间或局部名称空间中
3.使用
- 文本形式的python 的源代码
- 全局的名称空间{}
- 局部名称空间{}
1.python代码
code='''
global x
x=10
y=20
def func():
pass
'''
2.全局名称空间字典
global_dict = {'x':200}
3.局部名称空间字典
local_dict = {'y':100}
4.调用exec
exec(code,global_dict,local_dict)
print(global_dict)
print(local_dict)
元类
1.什么是元类
元类就是类的类,chinese类的类是type,type是所有类的类,type就是一个元类
1. **道** 即是 type
2. **一** 即是 metaclass(元类,或者叫类生成器)
3. **二** 即是 class(类,或者叫实例生成器)
4. **三** 即是 instance(实例)
5. **万物** 即是 实例的各种属性与方法,我们平常使用python时,调用的就是它们。
创建类的两种方式
- 通过class关键字创建类,内部会调用type(),type帮我们创建一个自定义类
- 通过手动调用type()实例化得到自定义的类
type创建类
类名,父类,类内的属性方法
class_name = '类名',class_base = (父类,),class_dict = {}
我是谁,我来自哪里,又要到哪去.
***************************************************************
# type创建类
# 获得type元类的三大要素
class_name='China'
class_base = (object,)
class_dict = {}
# 创建exec语句
code = '''
country = "china"
def __init__(self,name,age):
self.name = name
self.age = age
def speak(self,name,age):
print(f"speak {name} {age}华诞!......")
'''
# 创建exec传入
exec(code,{},class_dict)
china = type(class_name,class_base,class_dict) # 得到china类
print(china)
c = china("你好","70") # 实例化对象c
c.speak("你好","70") # 对象.方法调用 speak 你好 70华诞!......
class创建类
class 类名:
pass
2.元类的作用
元类可以帮我们控制类的创建
3.怎么自定义创建元类
- 自定义一个元类,继承type,派生出自己的属性与方法
- 给需要使用的类,通过metaclass指定自定义好的元类
class 类名(metaclass = '自定义的类')
自定义创建元类
class MyMetaclass(type):
# 子类的方法与父类的方法一样,先用子类的,子类覆盖父类的方法
def __init__(self,class_name,class_base,class_dict):
# Foo并没有被调用,metaclass=MyMetaclass调用元类,类在定义时会定义名称空间,所以__init__触发,打印
print(class_name) # 类名 Foo
print(class_base) # 父类 (<class 'object'>,)
print(class_dict) # 类的所有属性 {'__module__': '__main__', '__qualname__': 'Foo', 'x': 10, 'f1': <function Foo.f1 at 0x000001EF0423E9D8>}
# 使用super()函数指向type,type需要what,where,go三个参数
super().__init__(class_name,class_base,class_dict)
# metaclass= 自定义的元类
# 因为Foo继承了元类,所以必须手动继承object
class Foo(object,metaclass=MyMetaclass):
x = 10
def f1(self):
print('这是foo的打印.......')
增加元类限制创建类的规则
class MyMetaclass(type):
# 子类的方法与父类的方法一样,先用子类的,子类覆盖父类的方法
def __init__(self,class_name,class_base,class_dict):
# 1.判断定义类的首字母必须大写
if not class_name.istitle():
raise TypeError('类名必须首字母大小')
# 2.控制类中必须有缩进
if not class_dict.get('__doc__'):
raise TypeError('类中必须书写注释!')
# 使用super()函数指向type,type需要what,where,go三个参数
super().__init__(class_name,class_base,class_dict)
# metaclass= 自定义的元类
# 因为Foo继承了元类,所以必须手动继承object
class Foo(object,metaclass=MyMetaclass):
'''这是注释,但是不能使用 "#" '''
x = 10
def f1(self):
print('这是foo的打印.......')
元类限制对象的调用
# 对象调用时自动触发type 的__call__ 方法,call方法又会触发__new__,__init__来得到obj,通过重写覆盖父类的方法来限制对象的调用
def __call__(self, *args, **kwargs):
# 1.会调用__new__方法,创建一个空对象
obj = object.__new__(self)
# 2.会执行__init__方法,传参实例化
obj.__init__(*args,**kwargs)
return obj # 将对象返回出去
# 控制类的调用
class MyMetaclass(type):
# 子类的方法与父类的方法一样,先用子类的,子类覆盖父类的方法
def __init__(self,class_name,class_base,class_dict):
# 使用super()函数指向type,type需要what,where,go三个参数
super().__init__(class_name,class_base,class_dict)
# 对象调用时自动触发type 的__call__ 方法,这里定义call方法,限制对象的调用
def __call__(self, *args, **kwargs):
# 1.会调用__new__方法,创建一个空对象
obj = object.__new__(self)
# 2.会执行__init__方法,传参实例化
obj.__init__(*args,**kwargs)
return obj # 将对象返回出去
# metaclass= 自定义的元类
# 因为Foo继承了元类,所以必须手动继承object
class Foo(object,metaclass=MyMetaclass):
'''这是注释,但是不能使用 "#" '''
x = 10
def __init__(self,x,y):
self.x = x
self.y = y
def f1(self):
print('这是foo的打印.......')
foo = Foo(20,30) # 调用foo对象会触发__call__方法