python定义一个圆类_python高级(元类、自定义元类)

什么是元类(metaclass)?

元类是类的类,是类的模板

元类的实例为类,正如类的实例为对象classFoo:passt1=Foo() #t1是通过Foo类实例化的对象

print(type(f1))print(type(Foo))

所有的对象都是实例化或者说调用类而得到的(调用类的过程称为类的实例化),比如对象t1是调用FOO类得到的一个实例。

如果一切皆为对象,那么类Foo本质也是一个对象,既然所有的对象都是调用类得到的,那么Foo必然也是调用了一个类得到的,这个类称为元类。

于是可以推导出===>产生Foo的过程一定发生了:Foo=元类(...)print(type(Foo)) #结果为,证明是调用了type这个元类而产生的Foo,即默认的元类为type

Foo类就是type类的一个实例

我们基于python中一切皆为对象,字符串、列表、字典、函数是对象,类也是一个对象的概念分析出:我们用class关键字定义的类本身也是一个对象,负责产生该对象的类称之为元类(元类可以简称为类的类),内置的元类为type,type是Python的一个内建元类,用来直接控制生成类,Python中任何class定义的类其实都是type类实例化的对象。

class关键字在帮我们创建类时,必然帮我们调用了元类Foo=type(...),那调用type时传入的参数是什么呢?必然是类的关键组成部分,一个类有三大组成部分,分别是1、类名class_name='Foo'

2、基类们class_bases=(object,)   #继承新式类的父类object

3、类的名称空间class_dic,类的名称空间是执行类体代码而得到的

调用type时会依次传入以上三个参数

综上,class关键字帮我们创建一个类应该细分为以下四个过程

拿到类名:class_name='Foo'拿到类的基类们:class_bases=(object,)

执行类体代码,拿到类的名称空间:class_dic={......}

调用元类得到类Foo=type(class_name,class_bases,class_dic)

自定义元类

一个类没有声明自己的元类,默认他的元类就是type,除了使用元类type,用户也可以通过继承type来自定义元类1)最简单的情况

假设有下面的类:classFoo(object):pass现在,我们不使用class关键字来定义,而使用type,如下:

Foo= type('Foo', (object, ), {})    #使用 type 创建了一个类对象

上面两种方式是等价的。我们看到,type接收三个参数:

第1 个参数是字符串 'Foo',表示类名

第2个参数是元组 (object, ),表示所有的父类

第3个参数是字典,这里是一个空字典,表示没有定义属性和方法

在上面,我们使用type()创建了一个名为 Foo 的类,然后把它赋给了变量 Foo,我们当然可以把它赋给其他变量,但是,此刻没必要给自己找麻烦。

接着,我们看看使用:>>> printFoo

>>> printFoo()<__main__.foo object at>2)有属性和方法的情况

假设有下面的类:classFoo(object):

foo=Truedefgreet(self):print 'hello world'printself.foo

用type来创建这个类,如下:defgreet(self):print('hello world')print(self.foo)

Foo= type('Foo', (object, ), {'foo': True, 'greet': greet})

上面两种方式的效果是一样的,看下使用:>>> f =Foo()>>>f.foo

True>>>f.greet>

>>>f.greet()

hello world

True

把自定义函数名称写进底层字典里封存def __init__(self,name,age):

self.name=name

self.age=agedeftest(self):print('=====>')

FFo=type('FFo',(object,),{'x':1,'__init__':__init__,'test':test}) #用元类的方法把类方法里的属性按键值对形式写入到函数底层字典里封存

print(FFo)   #

print(FFo.__dict__)

f1=FFo('jamfiy',18)print(f1.name) #jamfiy

f1.test()#=====>

继承的情况

再来看看继承的情况,假设有如下的父类:classBase(object):pass一般我们用 Base 派生一个 Foo 类,如下:classFoo(Base):

foo=True

现在改用type来创建,如下:

Foo= type('Foo', (Base, ), {'foo': True})

f1=Foo()print(f1.foo)

在父类中声明继承元类,子类再继承是元类的父类

例:class MyType(type):  #声明继承元类type

def __init__(self,a,b,c):    #Foo实例化f1触发__init__方法

print('元类的构造函数执行')#print(a)   #打印self,Foo

#print(b)   #打印元组()的内容,来自*args传过来的参数

#print(c)   #打印字典{}的内容,来自**kwargs传过来的参数

def __call__(self, *args, **kwargs):   #调用Foo()方法触发__call__方法

#print('=-======>')

#print(self)  #Foo

#print(args,kwargs)

obj=object.__new__(self)  #调用新式类都继承的object基类,__new__方法生成一个对象引用,object.__new__(Foo)-->f1

self.__init__(obj,*args,**kwargs)  #相当于执行Foo.__init__(f1,*arg,**kwargs)

return obj   #返回结果给实例化对象f1

class Foo(metaclass=MyType):  #继承MyType元类,Foo=MyType(Foo,'Foo',(),{})  ---》 __init__

def __init__(self,name):

self.name=name   #相当于执行f1.name=name#print(Foo)

f1=Foo('alex')print(f1)print(f1.__dict__)

————————————————

版权声明:本文为CSDN博主「旅立の涯秸」的原创文章,遵循 CC4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。

原文链接:https://blog.csdn.net/jamfiy/java/article/details/88253058

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值