设为首页 收藏本站
查看: 922|回复: 0

[经验分享] metaclass in python (part 2)

[复制链接]

尚未签到

发表于 2017-4-27 11:50:25 | 显示全部楼层 |阅读模式
接着上一篇的讲。
现在我们知道了,metaclass 生 class,class 生 instance。
但是 metaclass 还可以有它的 metametaclass,metametaclass 还可以有... 如果反复,永无止境。这样想起来,脑袋就有点晕了。
其实在 python 中万物皆对象而已,所有对象皆有其类型,对象的类型也还是对象!而类型对象的类型就是它自己。
而前面说过的所谓 instance、class、metaclass 等东西,都只是不同种类的对象而已。
判断对象是什么对象的唯一方法就是通过其提供的“接口”,这就是所谓的 duck type!只要一个对象实现了成为一个 class 所需的接口,它就是 class !metaclass 亦然。
那么我们不如先来讨论讨论 metaclass 的接口吧,看看究竟需要实现哪些接口能使一个对象成为一个 metaclass。
先来看一些等价关系:
class Temp(object):
   __metaclass__ = Meta
   a = 1
   def __init__(self, a):
       self.a = a

上面代码其实等价于:
Temp = Meta('Temp', (object,),
  {'a':1, '__module__':'current module name', '__metaclass__':the object Meta, '__init__':function object __init__})

(class的语法原来只是个语法糖而已,汗!)
由此可见 Meta 首先应该是个 callable,并且应该接受如上所示的三个参数。
t = Temp(2) # 构建 Temp 的 instance

从这一句我们可以看出 Temp 也应该是个 callable 对象。
而我们知道 Temp 对象其实是调用 Meta 所返回的,也就是说 Meta 这个 callable 对象返回的还应该是一个 callable 对象。
典型地,如果 Meta 是一个 class,意味着它应该实现一个 __call__ 方法。这样的话,那么上面那句就可以等价为:
t = Temp.__call__(2)
上面说的这几点基本上可以作为判断一个对象能否成为 metaclass 的标准了:一个接受三个参数并返回另一个 callable 对象的 callable 对象!
不急,在继续分析之前我们不妨利用刚才发现的这一点搞点小怪先,呵呵。
def Meta(name, bases, attrs):
   def _class(a):
       return a
   return _class
class Temp(object):
   '''
   >>> Temp(1)
   1
   >>> Temp('hello')
   'hello'
   '''
   __metaclass__ = Meta

继续分析,虽然可以像上面那样恶搞,不过要想写个有点实际用处的 metaclass ,还是通过 class 来实现比较方便。
最典型的方法便是直接继承 type 了,毕竟那是所有 new-style class 的 metaclass,在 python3000 里就要成为所有 class 默认的 metaclass 了。
可以说大部分 metaclass 的实现都是这么做的,不过下面要分析的这一例却是个例外,虽然不像上面我们写的那个 metaclass 那么奇怪,不过分析起来也不是那么容易的。
不过我们还需要继续澄清一些事实,先看这个例子:
class Temp(object):
   @staticmethod  # 这一句可以忽略,不管有没有这句,__new__ 都是静态方法
   def __new__(cls, a):
       return object.__new__(cls, a)
   def __init__(self, a):
       self.a = a
   def __getattribute__(self, name):
       return super(Temp, self).__getattribute__(name)
   def __getattr__(self, name):
       return super(Temp, self).__getattr__(name)
t = Temp(2)
print t.a

在默认的 metaclass type 的实现中,上面这句,也就是 type 的 __call__ 方法,其实是分以下两步完成的:
t = Temp.__new__(Temp, 2) # 调用 staticmethod __new__,创建 instance
t.__init__(2) # 调用该 instance 的构造函数,初始化 instance

另外,既然 Temp 实现了 __getattribute__, t.a 实际上等价于:
try:
   t.__getattribute__(self, 'a')
except AttributeError:
   t.__getattr__(self, 'a')

到这里基本上一些概念问题已经搞清楚了,下一篇终于可以正式开始研究这里的代码了。
参考:
Unifying types and classes in Python 2.2 这是老大对 python2.2 以后的“python对象模型”的深刻的描述
The Python 2.3 Mehod Resolution Order 这也是今天碰巧看到的好文,虽然与本文没有什么联系,不过,此文深入讲解了 python2.3 以后对多继承的实现, 我也是看完这篇才知道实现个多继承是如此的复杂,不过幸好他们找到了合适的算法。 另外对于平时不经常接触算法的人(比如我)来说,偶尔用数学的思维思考思考还有很有好处的。
New-style Classes 这里是 new-style class 相关的文献的集合。
另外想找这方面中文资料的兄弟可以去啄木鸟:python中的新型类及其实例详解 Metaclasses(元类)

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-369969-1-1.html 上篇帖子: metaclass in python (part 2) 下篇帖子: Python 字符串方法详解
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表