zoukankan      html  css  js  c++  java
  • Python 元类

    元类

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

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

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

    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

  • 相关阅读:
    从零开始学习OpenCL开发(一)架构
    Android平台利用OpenCL框架实现并行开发初试
    g++ error: expected nested-name-specifier before 'XXX'
    Linux命令之xargs的分析及隐患
    Linux目录结构
    Linux系统目录/bin /sbin /usr/bin /usr/sbin和/lib /usrlib的一些分析
    rpm包制作
    git与svn的使用比较
    SVN的错误: working copy locked
    Linux远程桌面
  • 原文地址:https://www.cnblogs.com/ledgua/p/11454976.html
Copyright © 2011-2022 走看看