博客
关于我
元类(metaclass)
阅读量:441 次
发布时间:2019-03-06

本文共 4096 字,大约阅读时间需要 13 分钟。

Python元类入门到放弃:完整教程

引言

元类(Metaclass)是Python面向对象编程的核心机制之一。它决定了类如何创建和行为,99%的开发者无法深入理解,甚至有些自以为了解的人也只是停留在表面。今天,我们将带你深入探索Python元类的核心原理。

元类是什么?

在Python中,所有事物都是对象。用class关键字定义的类本身也是一个对象,而定义这个类的元类就是我们常说的meta class。简单来说,元类是类的类,它决定了类的创建方式。

class Foo:  # Foo的元类是type
pass

为什么用元类?

元类的主要作用是控制类的创建过程。通过自定义元类,我们可以掌控类的产生规则,甚至可以修改对象的行为。这种能力在开发框架和插件系统中非常有用。

内置函数exec的应用

exec函数可以执行字符串代码,适用于动态代码执行。以下是一个示例:

cmd = """x=1
print('exec函数运行了')
def func(self):
pass"""
class_dic = {}
exec(cmd, {}, class_dic)

执行后,class_dic会包含xfunc两个键:

print(class_dic)
#输出:
{'x': 1, 'func':
}

类的创建过程

类的创建过程实际上是一个实例化的过程,而实例化是通过元类完成的。默认情况下,Python使用type作为元类。

class People:
country = 'China'
def __init__(self, name, age):
self.name = name
self.age = age
def eat(self):
print('%s is eating' % self.name)
print(type(People))  # 输出: 

type元类的实现

type元类负责创建类,接受三个参数:类名、基类和名称空间。

class_name = 'People'
class_bases = (object,)
class_dic = {}
class_body = """
country='China'
def __init__(self, name, age):
self.name = name
self.age = age
def eat(self):
print('%s is eating' % self.name)
"""
exec(class_body, {}, class_dic)
print(class_name)  # 输出: People
print(class_bases) # 输出: (
,)
print(class_dic) # 输出: {'country': 'China', '__init__':
, 'eat':
}

自定义元类控制类创建

要使用自定义元类,我们需要继承type

class Mymeta(type):
def __init__(self, class_name, class_bases, class_dic):
print('self:', self)
print('class_name:', class_name)
print('class_bases:', class_bases)
print('class_dic:', class_dic)
super(Mymeta, self).__init__(class_name, class_bases, class_dic)
class People(object, metaclass=Mymeta):
country = 'China'
def __init__(self, name, age):
self.name = name
self.age = age
def eat(self):
print('%s is eating' % self.name)

__call__方法

__call__方法使类成为可调用对象。例如:

class Foo:
def __call__(self, *args, **kwargs):
print(args)
print(kwargs)
print('__call__实现了,实例化对象可以加括号调用了')
obj = Foo()
obj('nick', age=18)

输出结果:

('nick',)
{'age': 18}
__call__实现了,实例化对象可以加括号调用了

__new__方法

__new__方法是类实例化的关键:

class A:
pass
class B(A):
def __new__(cls):
print("__new__方法被执行")
return cls.__new__(cls)
def __init__(self):
print("__init__方法被执行")
b = B()

输出结果:

__new__方法被执行
__init__方法被执行

自定义元类控制实例化

通过自定义元类,我们可以控制实例化过程:

class Mymeta(type):
def __call__(self, *args, **kwargs):
print(self)
print(args)
print(kwargs)
obj = self.__new__(self)
self.__init__(obj, *args, **kwargs)
return obj
class People(object, metaclass=Mymeta):
country = 'China'
def __init__(self, name, age):
self.name = name
self.age = age
def eat(self):
print('%s is eating' % self.name)
obj = People('nick', 18)
print(obj.__dict__)
# 输出:
{'name': 'nick', 'age': 18}

元类控制属性查找顺序

在自定义元类环境下,属性查找顺序会受到影响。例如:

class Mymeta(type):
pass
class Bar(object):
n = 333
class Foo(Bar):
n = 222
class OldboyTeacher(Foo, metaclass=Mymeta):
n = 111
school = 'oldboy'
def __init__(self, name, age):
self.name = name
self.age = age
def say(self):
print('%s says welcome to the oldboy to learn Python' % self.name)
print(OldboyTeacher.n)  # 输出: 111

查找顺序为:

OldboyTeacher -> Foo -> Bar -> object -> Mymeta -> type

练习:使用元类隐藏属性

需求:通过自定义元类,修改类的属性为隐藏属性。

class Mymeta(type):
def __init__(self, class_name, class_bases, class_dic):
super(Mymeta, self).__init__(class_name, class_bases, class_dic)
def __call__(self, *args, **kwargs):
obj = self.__new__(self)
self.__init__(obj, *args, **kwargs)
obj.__dict__ = {
'_%s__%s' % (self.__name__, k): v
for k, v in obj.__dict__.items()
}
return obj
class Foo(object, metaclass=Mymeta):
def __init__(self, name, age, sex):
self.name = name
self.age = age
self.sex = sex
obj = Foo('nick', 18, 'male')
print(obj.__dict__)
# 输出:
{'_Foo__name': 'nick', '_Foo__age': 18, '_Foo__sex': 'male'}

这就是通过自定义元类隐藏类属性的实现方法。

转载地址:http://pfgyz.baihongyu.com/

你可能感兴趣的文章
Objective-C实现内存泄露检查(附完整源码)
查看>>
Objective-C实现内核中的自旋锁结构(附完整源码)
查看>>
Objective-C实现内格尔·施雷肯伯格算法(附完整源码)
查看>>
Objective-C实现冒泡排序(附完整源码)
查看>>
Objective-C实现农历与公历转换 (附完整源码)
查看>>
Objective-C实现几何级数的总和算法 (附完整源码)
查看>>
Objective-C实现凯撒密码算法(附完整源码)
查看>>
Objective-C实现凸多边形的凸包问题算法(附完整源码)
查看>>
Objective-C实现分块查找算法(附完整源码)
查看>>
Objective-C实现分块查找算法(附完整源码)
查看>>
Objective-C实现分层聚类算法(附完整源码)
查看>>
Objective-C实现分水岭算法(附完整源码)
查看>>
Objective-C实现分而治之算法(附完整源码)
查看>>
Objective-C实现分解质因数(附完整源码)
查看>>
Objective-C实现切换数字的符号switchSign算法(附完整源码)
查看>>
Objective-C实现列主元Gauss消去法(附完整源码)
查看>>
Objective-C实现列主元高斯消去法(附完整源码)
查看>>
Objective-C实现创建一个链表和打印该链表算法(附完整源码)
查看>>
Objective-C实现创建多级目录(附完整源码)
查看>>
Objective-C实现删除文件中的指定内容(附完整源码)
查看>>