exec(object, global=None, local=None)
code = '''
x = 0
sum = x + y + z
print(sum)
'''
y = 1
z = 2
global_dict = {'y': 2, 'z': 3}
local_dict = {'y': 3, 'z': 4}
exec(code)
'''
y = 1
z = 2
x = 0
sum = x + y + z
print(sum)
'''
exec(code, global_dict)
'''
相当于
y = 2
z = 3
x = 0
sum = x + y + z
print(sum)
'''
exec(code, global_dict, local_dict)
'''
相当于
y = 2
z = 3
def exec_func():
y = 3
z = 4
x = 0
sum = x + y + z
print(sum)
exec_func()
'''
'''
3
5
7
'''
MyClass = type(class_name, class_bases, class_dict)
# 用type元类来创建一个Chinese类
def __init__(self, name, gender, age):
self.name = name
self.gender = gender
self.age = age
class_name = 'Chinese'
class_bases = (object,)
class_dict = {'country': 'China', '__init__': __init__}
Chinese = type(class_name, class_bases, class_dict)
c1 = Chinese('bigb', 'male', 18)
print(c1.name) # bigb
print(c1.country) # China
__init__
的方法'''
通过自定义元类来实现:
1. 类名首字母必须大写
2. 类中必须有文档注释
'''
class MyMeta(type):
def __init__(self, class_name, class_bases, class_dict):
print(class_name) # chinese
print(class_bases) # (<class 'object'>,)
print(class_dict) # {'__module__': '__main__', '__qualname__': 'chinese', 'country': 'China', '__init__': <function chinese.__init__ at 0x0000000009FBFD90>, 'kongfu': <function chinese.kongfu at 0x0000000009FBFE18>}
# 类名首字母必须大写
if not class_name.istitle():
raise TypeError('类的首字母必须大写!')
# 类中必须有注释
if not class_dict.get('__doc__'):
raise TypeError('类中必须有文档注释!')
# 调用type中的__init__方法初始化对象
super().__init__(class_name, class_bases, class_dict)
class chinese(object, metaclass=MyMeta): # foo = MyMeta('foo', (object, ) {...})
country = 'China'
def __init__(self, name, gender, age):
self.name = name
self.gender = gender
self.age = age
def kongfu(self):
print('降龙十八掌!')
'''
raise TypeError('类的首字母必须大写!')
TypeError: 类的首字母必须大写!
'''
# 将类名大写, 再运行
class Chinese(object, metaclass=MyMeta): # foo = MyMeta('foo', (object, ) {...})
country = 'China'
def __init__(self, name, gender, age):
self.name = name
self.gender = gender
self.age = age
def kongfu(self):
print('降龙十八掌!')
'''
raise TypeError('类中必须有文档注释!')
TypeError: 类中必须有文档注释!
'''
__call__
方法__call__
方法class MyMeta(type):
def __call__(self, *args, **kwargs):
# 产生一个空对象
obj = self.__new__(self) # self是类对象
# 初始化空对象
self.__init__(obj, *args, **kwargs)
# 返回初始化好的对象
return obj
class Chinese(object, metaclass=MyMeta): # foo = MyMeta('foo', (object, ) {...})
country = 'China'
def __init__(self, name, gender, age):
self.name = name
self.gender = gender
self.age = age
def kongfu(self):
print('降龙十八掌!')
# 这里调用了类对象Chinese, 因此会触发Chinese的类(元类)中的__call__方法
c1 = Chinese('bigb', 'male', 18)
print(c1.name)
'''
1. __call__中的__new__生成了一个空对象
2. __call__中的__init__初始化这个空对象
3. __call__返回了这个对象,并赋值给了c1
'''
__call__
的逻辑从而控制类的调用过程# 通过元类让Chinese类实例化出来的对象的属性变为私有属性
class MyMeta(type):
def __call__(self, *args, **kwargs):
# 产生一个空对象
obj = self.__new__(self) # self是类对象
# 初始化空对象
self.__init__(obj, *args, **kwargs)
# 将对象的属性变成私有属性(对象._类__属性名)
obj.__dict__ = {f'_{self.__name__}__{k}': v for k, v in obj.__dict__.items()}
# 返回初始化好的对象
return obj
class Chinese(object, metaclass=MyMeta): # foo = MyMeta('foo', (object, ) {...})
country = 'China'
def __init__(self, name, gender, age):
self.name = name
self.gender = gender
self.age = age
def kongfu(self):
print('降龙十八掌!')
# 这里调用了类对象Chinese, 因此会触发Chinese的类(元类)中的__call__方法
c1 = Chinese('bigb', 'male', 18)
print(c1._Chinese__name) # bigb
# 定义字段类
class Field:
def __init__(self, name, column_type, primary_key, default):
self.name = name
self.column_type = column_type
self.primary_key = primary_key
self.default = default
# 定义整数字段类
class IntegerField(Field):
def __init__(self, name, column_type='int', primary_key=False, default=0):
super().__init__(name, column_type, primary_key, default)
# 定义字符字段类
class StringField(Field):
def __init__(self, name, column_type='varchar(64)', primary_key=False, default=None):
super().__init__(name, column_type, primary_key, default)
# 定义元类
class OrmMetaClass(type):
def __new__(cls, class_name, class_bases, class_dict):
print(class_name)
print(class_dict)
# Models类中什么都不做, 将类原路返回
if class_name == 'Models':
return type.__new__(cls, class_name, class_bases, class_dict)
# 获取表名, 如果没有,则将类名当做表名
table_name = class_dict.get('table_name', class_name)
# 主键名标记
primary_key = None
# 定义一个空字典, 用来存放字段对象
mappings = {}
for key, value in class_dict.items():
# 过滤字段对象以外的属性
if isinstance(value, Field):
mappings[key] = value
# 判断该字段对象中的primary key是否为True
if value.primary_key:
# 判断主键是否已经存在
if primary_key:
raise TypeError('只能有一个主键!')
# 若主键不存在, 则给primary key赋值
primary_key = value.name
# 删除mappings与类名称空间中重复的属性, 节省空间
for key in mappings.keys():
class_dict.pop(key)
if not primary_key:
raise TypeError('必须有一个主键!')
# 给类的名称空间添加表名
class_dict['table_name'] = table_name
# 给类的名称空间添加主键名
class_dict['primary_key'] = primary_key
# 给类的名称空间中添加mappings字典, 字典中拥有所有字段属性
class_dict['mappings'] = mappings
return type.__new__(cls, class_name, class_bases, class_dict)
class Models(dict, metaclass=OrmMetaClass):
# 让表对象(字典)可以通过 对象.属性的方式获取值
def __getattr__(self, item):
return self.get(item)
# 让表对象(字典)可以通过 对象.属性 = 值 的方式进行赋值
def __setattr__(self, key, value):
self[key] = value
# 定义用户表类
class User(Models):
user_id = IntegerField(name='user_id', primary_key=True)
user_name = StringField(name='name')
pwd = StringField(name='pwd')
原文:https://www.cnblogs.com/bigb/p/11796023.html