元类

一切皆对象,类实际上也是一个对象。

元类的定义:而元类指的是由一个类实例化,那个类叫做元类

简单来说元类就是:产生类的类

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来生成实例,那么在调用时传入的参数都有哪些呢:

  1. 类名class_name= 传入的
  2. 基类们class——bases = (object)
  3. 类的名称空间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