元类
一切皆对象,类实际上也是一个对象。
元类的定义:而元类指的是由一个类实例化,那个类叫做元类
简单来说元类就是:产生类的类
class Person:
def __init__(self,name):
self.name = name
def score(self):
print('分数是100')
p = Person
p1 = p('nick')
print(p1.name)
我们都知道我们平时用的type可以查看类型,那么我们对使用type查看类型会怎么样呢
print(type(p)) #####<class 'type'>
那么我们常用的数据类型呢
print(type(dict)) #####<class 'type'>
print(type(list)) #####<class 'type'>
print(type(str)) #####<class 'type'>
print(type(object)) #####<class 'type'>
那么既然这些都是type类型的,那么我们查看他本身呢
print(type(type)) #####<class 'type'>
由此我们可以得知,type是产生所有类的元类
class底层原理分析
我们在python中通常通过calss来定义类,那么它是怎么样的一个过程呢
首先从上面我们发现type是python中内置的元类
那么在使用class创建类的时候,关键字会帮助我们调用元类type来生成实例,那么在调用时传入的参数都有哪些呢:
- 类名class_name= 传入的
- 基类们class——bases = (object)
- 类的名称空间class_dic,类的名称空间是执行类体代码而得到的
调用type时,会自动传入以上三个参数
那么如何使用type产生类呢
l = {}
Person = type('Person',(object,),l)
a = Person()
print(a.__dict__) ##结果##{}
exce来创建类的方法:
l = {}
exec('''
school = 'oldboy'
def __init__(self,name):
self.name = name
def score(self):
print('分数是100')
''',{},l)
Person = type('Person',(object,),l)
a = Person('nick')
print(a.__dict__)
eval()和exec()的区别与联系
联系:都可以把字符串里的字符转换为可执行代码
区别:
-
eval只支持一行字符。可以返回执行后得到的值
-
f = "3+6+9+8" s = eval(f) print(s) ###26
-
-
exec可以支持多行字符。但是拿不到返回结果。
-
code = ''' def func(): print('test') return 555 func() ''' f = exec(code) print('---'*5) print(f) ################## test --------------- None
-
通过元类控制类的产生
自定义元类:
- 来控制类的产生
- 可以控制类名
- 可以控制类的继承父类
- 控制类的名称空间
type
自定义元类必须继承type,写一个类继承type 这种类都叫做元类
class Mymeta(type):
#def __init__(self,*args,**kwargs):
def __init__(self,name,bases,dic):
#self就是Person类
# print(name)
# print(bases)
# print(dic)
#print(args)
#print(kwargs)
#加限制,控制类名必须用驼峰体或以什么开头
# if not name.startswith('sb'):
# raise Exception('类名开头错误')
#二、类必须加注释
print(self.__dict__['__doc__'])
##metaclass=Mymeta指定这个类生成是使用自己定义的元类,可以不用type类型
class sbPerson(object , metaclass=Mymeta):
'''
nihao
'''
school = 'oldboy'
def __init__(self,name):
self.name = name
def score(self):
print('分数是100')
通过元类控制类的调用过程
# class Mymeta(type):
# def __call__(self, *args, **kwargs):
# #self 是Person这个类
# # print(args)
# # print(kwargs)
# # return self(*args) #这里不行,会递归
# # self.__new__(self)
# #实例化产生一个Person类的对象,借助__new__来产生,需要把类传过去,才能产生对象
# #obj 是Person类的对象,只不过是空的
# obj=object.__new__(self)
# # obj=self.__new__(self)
# #调用__init__方法完成初始化
# #类来调用__init__方法,就是个普通函数,有几个参数就穿几个惨
# # self.__init__(obj,*args, **kwargs)
# #对象来调用__init__方法,对象的绑定方法,会把自身穿过来
# obj.__init__(*args, **kwargs)
# print(obj)
# return obj
#
#
# class Person(object, metaclass=Mymeta):
# school = 'oldboy'
# def __init__(self, name):
# self.name = name
# def score(self):
# print('分数是100')
# p = Person(name='nick')
# print(p)
# print(p.name)
#把对象所有的属性都变成私有
有了元类以后的属性查找
type
6
Mymeta
5
Oldboy Teacher----2----Foo----3----Bar-----4------object
1
Oldboy Teacher.n