tuoheng_algN/test/元类/demo1.py

121 lines
3.6 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# -*- coding: utf-8 -*-
class Test:
pass
print(type(Test))
print(type(int))
# 结果都为<class 'type'>type就是内置的元类class关键字定义的所有的类以及内置的类都是由元类type实例化产生。
"""
由于在python3中没有经典类和新式类的区别因此python3中object是所有类的基类那内置元类type又是什么
type是object类的类型总结来说就是type是object的类型同时object又是type的基类这句话看起来就有问题
到底是先有type还是先有object呢这个问题有点类似于先有鸡还是先有蛋我们可以通过代码简单分析一下
在python3中类和类型是同一种东西因此对象.__class__和type(对象)得到的结果是一致的object的基类为空
但是type的基类为object但是object的类型又是type。
"""
print(type(object))
print(object.__class__)
print(type(type))
print(type.__class__)
print(object.__bases__)
print(type.__bases__)
# python字符串
strs = """
global name
global age
name = 'py'
age = 18
addr = 'xx'
"""
# 定义全局作用域中的名字和值
globals = {
'a': '1',
'b': '2'
}
# 定义局部作用域中的名字和值
locals = {
'x': 3,
'y': 4
}
exec(strs, globals, locals)
print(globals['name'])
print(locals)
# 了解了exec的作用之后就可以分析class关键字如何借助type元类产生类的步骤
# 1 定义类名
class_name = 'Test'
# 2 定义类的基类(父类)
class_bases = (object,)
# 3 执行类体代码拿到类的名称空间
class_dic = {}
# 4 定义类体代码(本质是字符串)
class_body = """
def __init__(self,name,age):
self.name=name
self.age=age
def test(self):
print('%s:%s' %(self.name,self.name))
"""
# 5 将字符串转为python能识别的语法:将class_body运行时产生的名字存入class_dic中
exec(class_body, {}, class_dic)
# 查看类的名称空间
print(class_dic)
# 6 调用元类产生类
Test = type(class_name, class_bases, class_dic)
# 7 调用类产生对象
t = Test('python', '12')
t.test()
# 自定义元类
class MyMeta(type): # 自定义元类必须继承type否则就是普通的类
'''
早于__init__方法执行必须返回空对象由于该方法是调用类后第一个运行的方法
此时并没有对象产生,因此该方法的第一个参数必须是类本身(MyMeta),*args, **kwargs
用来接收调用元类产生对象所需的参数(类名 类的基类 名称空间)
'''
def __new__(cls, *args, **kwargs):
return type.__new__(cls, *args, **kwargs) # 直接调用父类type中的__new__方法
'''
通过__init__控制类的产生调用自定义元类与调用内置元类type的方式相同
需要传入类名、类的父类们、类体代码的名称空间,__init__方法中第一个参数来自于__new__方法产生的空对象。
'''
def __init__(self, class_name, class_bases, class_dict):
'''
在该方法内可以控制类的产生
'''
if not class_name.istitle(): # 实现类名首字母必须大写,否则抛出异常
raise NameError('类名的首字母必须大写')
if '__doc__' not in class_dict or len(class_dict['__doc__'].strip())==0: # 实现类必须有文档注释,否则抛出异常
raise TypeError('必须有文档注释')
def __call__(self, *args, **kwargs):
print(self)
print(args)
print(kwargs)
return 'test'
class Test(metaclass=MyMeta):
'''
我是文档注释
'''
def __init__(self):
self.name = 'python'
def test(self):
print('test')
t = Test()