Python:细说元类

编辑:光环大数据 来源: 互联网 时间: 2017-10-31 13:18 阅读:

  Python:细说元类.Python编程语言的一个重要特征是,所有事物都是一个对象。这些对象都是类的实例。

classMyClass:

pass

a=int('5')

b=MyClass()

print(type(a))

print(type(b))

但是,类不也是对象吗?是的,他们也是对象。

classMyClass:

pass

print(type(MyClass))

因此我们定义的类都具有type类型。所以称作是元!但是类是如何通过type类来创建的呢?而且刚才我们也看到type是一个函数,且返回一个对象的类型。

没错,当我们只是传递一个对象给type的时候,它就返回这个对象的类型给我们。但是如果我们传递跟多信息给它,它就会创建一个类给我们。比如这个:

MyClass=type('MyClass',(),{})

instance=MyClass()

print(type(instance))

我们可以name,bases作为元组传递给type,并且将attributes作为字典传给type,那么我们就会得到一个类。这个类扩展了刚才所给的bases并包含了我们所给的attributes。

当我们按如下定义一个类的时候:

classMyClass(int):

name="MyClass"

在它内部就等价于MyClass=type("MyClass",(int,),{"name":"MyClass"})。这里的type就是MyClass的元类了。

对象都是类的实例,而且类是元类的实例。

因此基本上说,这就是基本的东西了----我们由类来创建对象,然后我们由元类来创建类。在Python中,type是所有类的一个默认的元类,但是这个是可以由我们自己按需定制的。

元类钩子

如果我们不想要type作为我们的类的元类,应该怎么办呢?我们需要定制所需要创建的类的方式,并且我们不会有其他更好的方法来修改type元类的工作方式。因此我们如何做到并使用我们定制的类呢?

一个相当显然的方法是使用这个方式:MyClass=MyMetaClass(name,bases,attrs)。但是还有其他方法将一个类放置于一个定制的元类里面。在Python2中,所有类都可以定义一个__metaclass__方法,它可以用来创建一个类。在Python3中,我们将这个可调用的元类作为关键词参数传递给类的参数列表中:

#Python3

classMyClass(metaclass=MetaClass):

pass

#Python2

classMyClass():

__metaclass__=MetaClass

这个种元类参数必须是可调用的,也就是它带有name,bases和attributes,因为它有参数并且返回一个类的对象实例。请注意的是,元类参数本身并不必须是一个元类,只要它是一个类似于可调用的,并能由元类创建对象的工厂(factory)那样就行。

deffunc_metaclass(name,bases,attrs):

attrs['is_meta']=True

returntype(name,bases,attrs)

classMyClass(metaclass=func_metaclass):

pass

这是关于函数被用作可调用的元类的一个很简单的例子。现在让我们来使用这些类吧。

classMetaClass(type):

def__init__(cls,name,bases,attrs):

super().__init__(name,bases,attrs)

cls.is_meta=True

classMyClass(metaclass=MetaClass):

pass

print(MyClass.is_meta)

这里,元类被调用了并带有一些参数,这些参数都被传给了它的__new__方法,并且我们得到了一个类。我们从type得到了一个子类,因此我们不需要提供我们自己对__new__方法的实现方式。在__new__被调用之后,__init__方法也会被调用作为初始化。我们给我们的__init__方法也加入了额外的属性。

在我们的函数例子中,我们直接使用了type元类。因此所有从这个函数产生的类都会还有type类型。换句话说,我们在我们刚才这个类的例子中扩展了type。因此所产生的类的类型将是我们定义的元类。因此看来使用基于类的方法(来创建类)是有好处的。

使用案例

我们再来在看看子类:

classTrackSubclasses(type):

subclasses={}

def__init__(cls,name,bases,attrs):

forbaseinbases:

cls.subclasses[base]=cls.subclasses.get(base,0)+1

super().__init__(name,bases,attrs)

classA(metaclass=TrackSubclasses):

pass

classB(A):

pass

classC(A):

pass

classD(B):

pass

print(TrackSubclasses.subclasses)

或者写一个final类:

classFinal(type):

def__init__(cls,name,bases,attrs):

super().__init__(name,bases,attrs)

forklassinbases:

ifisinstance(klass,Final):

raiseTypeError("{}isfinal".format(klass.__name__))

classFinalClass(metaclass=Final):

pass

classChildClass(FinalClass):

pass

 

  Python培训Python培训班Python培训机构,就选光环大数据!

  还不够过瘾?想学习更多?点击 http://hadoop.aura.cn/python/ 进行Python学习!


大数据培训、人工智能培训、Python培训、大数据培训机构、大数据培训班、数据分析培训、大数据可视化培训,就选光环大数据!光环大数据,聘请专业的大数据领域知名讲师,确保教学的整体质量与教学水准。讲师团及时掌握时代潮流技术,将前沿技能融入教学中,确保学生所学知识顺应时代所需。通过深入浅出、通俗易懂的教学方式,指导学生更快的掌握技能知识,成就上万个高薪就业学子。 更多问题咨询,欢迎点击------>>>>在线客服

你可能也喜欢这些

在线客服咨询

领取资料

X
立即免费领取

请准确填写您的信息

点击领取
#第三方统计代码(模版变量) '); })();
'); })();