元类总结

元类总结

type只传一个参数有什么用

打印对象的类型

print(type(1))

class底层原理

通过type类来实例化,得到类

def __init__(self,name):
    self.name=name
Person=type('Person',(object,),{'x':1,'__init__':__init__})
p=Person('lqz')
print(Person.__dict__)
print(p.__dict__) #{'name': 'lqz'}
print(p.x)

#等同于
class Person(object):
    x=1
    def __init__(self,name):
        self.name=name
p=Person('lqz')
print(Person.__dict__)
print(p.__dict__)
print(p.x)

exec

执行字符串的代码,当成python解释器

ss='''
x=1
print(x)
'''
g={}
l={}
exec(ss,g,l)
print(l)
#1
#{'x': 1}

自定义元类

继承type

class Mymeta(type):
    def __init__(self,name,bases,dic):
        #self 是Person 这个类(对象)
        #在这个位置,其实self也就说Person这个类,内部已经有东西了,名称空间已经有东西了
        #所以在这个地方,可以通过dic来判断名称空间
        #也可以直接通过self.__dict__/self.属性 来判断
        a=dic.get('name')
        if not a :
            raise Exception('没有name属性,不能创建')
    # def __call__(self, *args, **kwargs):
    #     pass

class Person(metaclass=Mymeta):  #Person=Mymeta('Person',(object,),{...}) Mymeta类实例化,会把三个参数传到Mymeta的__init__方法中
# class Person():  #Person=Mymeta('Person',(object,),{...}) Mymeta类实例化,会把三个参数传到Mymeta的__init__方法中
    def __init__(self,name):
        self.name=name
        raise Exception('就不让你创建')

p=Person('lqz')  #自动触发Person类__init__的执行
# 总结:可以通过自定义元类,重写__init__方法来控制类的产生

通过元类控制类的调用过程,实例化产生对象的过程

class Mymeta(type):
    def __call__(self, *args, **kwargs):
        #该方法必须返回一个对象(类对象),这个地方返回什么 p=Person('lqz') p就是什么
        #返回一个真正的Person类的对象
        #第一步:产生一个空对象
        #object.__new__(self)  传一个参数,传类,就会产生一个该类的空对象
        #obj是Person类的空对象
        obj=object.__new__(self)
        # print(self.__new__ is object.__new__)  # True

        #第二步:初始化该对象,把初始值放到对象中
        #obj是Person类的空对象  obj.__init__  调用自己的绑定方法,也就说Person类中写的__init__方法
        obj.__init__(*args, **kwargs)
        #还可以类来调用
        # Person.__init__(obj,*args, **kwargs)
        # self.__init__(obj,*args, **kwargs)
        # print(obj.name)
        #第三步:把该对象返回
        return obj

class Person(metaclass=Mymeta):
# class Person():
    def __init__(self,name):
        self.name=name
    def __call__(self, *args, **kwargs):
        print('xxx')

p=Person('lqz')
print(p.name)
print(p)
# 原来的理解Person('lqz') 会调用Person类的__init__的方法
# 这个位置会调用元类的__call__方法,所以在__call__方法中调用了Person  __init__方法,来完成对象的初始化
p()

模板:控制对象的产生

class Mymeta(type):
    def __call__(self, *args, **kwargs):
        obj=object.__new__(self)
        obj.__init__(*args,**kwargs)
        return obj
class Person(metaclass=Mymeta):
    def __init__(self,name):
        self.name=name
    def __call__(self, *args, **kwargs):
        print('xxx')
p=Person('lqz')

自定义一个元类,定义一个类,继承字典,使其具备点取值和赋值功能,通过元类控制对象的产生,把所有对象的属性都放到attr字典中,属性全删除

例如:di=Mydic(name=‘lqz‘,age=18)

di的名称空间中没有name和age属性,但是有attr字典属性,字典包含{‘name‘:‘lqz‘,‘age‘:18}

class Mymeta(type):
    def __call__(self, name, age):
        obj=object.__new__(self)
        obj.__dict__['attr']={'name':name,'age':age}
        return obj

class Person(metaclass=Mymeta):
    def __init__(self,name,age):
        self.name=name
        self.age=age

p=Person('lqz',18)
print(p.__dict__)
print(p.attr['name'])

赠送元类

#object.__new__
class Person():
    def __init__(self,name,age):
        print('__init__')
        self.name=name
        self.age=age
    def __new__(cls,*args,**kwargs):
        print('__new__')
        #生成一个Person类的空对象
        return object.__new__(cls)
p=Person('lqz',19)
print(p)
#object.__new__ 传哪个类就得到哪个类的空对象
p=object.__new__(Person)
print(p)

#__new__和__init__的区别
__new__ 创建空对象
__init__ 初始化空对象

#object.__new__(Person)    :生成Person类的对象  空的
#type.__new__(cls,name,bases,dic)  :生了cls这个类对象,里面有东西

元类中

#__init__:控制类的产生,在__new__之后
#__call__:对着对象的产生
#__new__:控制类产生最根上,其实本质最根上也不是它,是type的__call__,但是我们控制不了了

class Mymeta(type):
    def __init__(self,name,bases,dic):
        #self 是Person类,Person类中有名称空间之类的了
        # print('xxxxxxx')
        # print(args)
        # print(kwargs)
        # print(name)
        # print(bases)
        # print(dic)
        pass
        # self.name='xxxxxxx'
    def __new__(cls, name,bases,dic):
        # print(name)
        # print(bases)
        # print(dic)
        #产生空对象(空类),在这里面生成的并不是空类,是有数据的类了
        #如何完成类的初始化,并且把name,bases,dic这些东西放入
        # return type.__new__(cls,name,bases,dic)
        dic2={'attr':{}}
        for k,v in dic.items():
            #加入这一句,类名称空间中带__的就不会放到attr中
            if not k.startswith('__'):
                dic2['attr'][k]=v
        print('-------',dic2)
        return type.__new__(cls,name,bases,dic2)

class Person(metaclass=Mymeta):     # Person=Mymeta(name,bases,dic)   调用type的__call__,内部调用了Mymeta.__new__,又掉Mymeta的__init__
    school='oldboy'
    age=10
    def __init__(self,name,age):
        self.name=name
        self.age=age

print(Person.__dict__)
print(Person.attr['school'])
# p=Person('nick',18)

原文地址:https://www.cnblogs.com/aden668/p/11459726.html

时间: 2024-07-31 06:36:38

元类总结的相关文章

深刻理解Python中的元类(metaclass)

译注:这是一篇在Stack overflow上很热的帖子.提问者自称已经掌握了有关Python OOP编程中的各种概念,但始终觉得元类(metaclass)难以理解.他知道这肯定和自省有关,但仍然觉得不太明白,希望大家可以给出一些实际的例子和代码片段以帮助理解,以及在什么情况下需要进行元编程.于是e-satis同学给出了神一般的回复,该回复获得了985点的赞同点数,更有人评论说这段回复应该加入到Python的官方文档中去.而e-satis同学本人在Stack Overflow中的声望积分也高达6

【原创】Python 对象创建过程中元类, __new__, __call__, __init__ 的处理

原始type: type是最原始的元类,其__call__方法是在你使用" t_class = type(classname_string, base_classes_tuple, attributes_dict)" 这种语法来使用时, 在__call__方法内使用又会调用type的__new__和__init__方法来创建classname_string的具体类,并初始化类信息.当type(***)调用完成, classname_string代表的类可以用来创建实例了. 元类调用过程

QObject提供了QMetaObject元类信息(相当于RTTI和反射),信号与连接,父子关系,调试信息,属性,事件,继承关系,窗口类型,线程属性,时间器,对象名称,国际化

元类信息(相当于RTTI和反射),信号与连接,父子关系,调试信息,属性,事件,继承关系,窗口类型,线程属性,时间器,对象名称,国际化其中元类又提供了:classInfo,className,构造函数,多重祖先元类,method, property, Enumerator, Signal, Slot等等 http://doc.qt.io/qt-5/qobject.html http://doc.qt.io/qt-5/qmetaobject.html 我感觉Qt的出现,除了提供GUI以外,主要就是提

Python全栈开发之9、面向对象、元类以及单例

前面一系列博文讲解的都是面向过程的编程,如今是时候来一波面向对象的讲解了 一.简介 面向对象编程是一种编程方式,使用 “类” 和 “对象” 来实现,所以,面向对象编程其实就是对 “类” 和 “对象” 的使用.类就是一个模板,模板里可以包含多个方法(函数),方法里实现各种各样的功能,,对象则是根据模板创建的实例,通过实例,对象可以执行类中的方法,每个对象都拥有相同的方法,但各自的数据可能不同. 二.类.对象和方法 在Python中,定义类是通过class关键字,class后面紧接着是类名,类名通常

Objective-C对象之类对象和元类对象

作者:wangzz 原文地址:http://blog.csdn.net/wzzvictory/article/details/8592492 转载请注明出处 如果觉得文章对你有所帮助,请通过留言或关注微信公众帐号wangzzstrive来支持我,谢谢! 作为C语言的超集,面向对象成为Objective-C与C语言的最大区别,因此,对象是Objective-C中最重要的部分之一.目前面向对象的语言有很多,Objective-C中的对象又和其他语言中的对象有什么区别呢?下面来简单介绍Objectiv

.NET 中,编译器直接支持的数据类型称为基元类型(primitive type).基元类型和.NET框架类型(FCL)中的类型有直接的映射关系.

.NET 中,编译器直接支持的数据类型称为基元类型(primitive type).基元类型和.NET框架类型(FCL)中的类型有直接的映射关系. The primitive types are Boolean, Byte, SByte, Int16, UInt16, Int32, UInt32, Int64, UInt64, IntPtr, UIntPtr, Char, Double, and Single. https://msdn.microsoft.com/zh-cn/library/s

MyPython-->进阶篇-->使用枚举类 元类

当我们需要定义常量时,一个办法是用大写变量2通过整数来定义,例如月份 JAN = 1 FEB = 2 MAR = 3 好处是简单,缺点是类型是int,并且仍然是变量 更好的方法是为这样的枚举类型定义一个class类,然后每个常量都是class的一个唯一实例,python提供了Eum类来实现这个功能 from enum import Enum Month = Enum('Month',('Jan','Feb','Mar','Apr','May')) print(Month.May) for nam

Python中元类

一. 前提: python中一切都是对象,要么是类的对象,要么是元类的对象,type元类是自己的对象.继承层次表示为type(元类)-->类(内置和用户自定义的) --> 类的实例. 二.  目的: 创建类时自动改变类,换句话说就是创建类这种东西的东西. 三.  __metaclass__ 可以通过指定__metaclass__来使用用户自定义的元类创建类. class语句解析顺序: class Myclass(object): pass Myclass里面的__metaclass__ --&

Python-深入理解元类(metaclass)

1.使用 type 动态创建类(type 是一个类, 用来创建类对象的元类, 所以也可以继承) type("Person", (), {"name": "John"}) 2.元类 Python 中类也是对象, 元类就是创建这些类对象的类, 可以理解为 MyClass = MetaClass() MyObject = MyClass() 3.type实际上是一个元类, type就是Python在背后用来创建所有类的元类, 类似 str 是创建字符串

Python中的元类(metaclass)

推荐+收藏:深刻理解Python中的元类(metaclass) 做一些笔记学习学习: 在大多数编程语言中,类就是用来描述如何生成一个对象的代码段,在Python中类也是一个对象,这个(类)对象自身拥有创建对象(类实例)的能力. 因为它的本质是一个对象: 可以将它赋值给一个变量 可以拷贝它 增加属性 作为参数进行传递 可以在运行时动态地创建他们,可以在函数中创建类,只需要使用class关键字即可 当使用class关键字的时候,Python解释器会自动地创建这个对象,Python还提供了手动处理的方