PyPy中的extendabletype与pairtype解析

本文深入解析了PyPy中的extendabletype与pairtype,它们提供了类似C# partial关键字的功能,允许在不创建新类的情况下扩展类的行为,并通过pairtype将两个类组合成一个新的类,实现类间协作。
摘要由CSDN通过智能技术生成

# -*- coding: utf-8 -*- 

# 首发在 http://page.renren.com/601001752/note/775449636
''' 
PyPy中的extendabletype与pairtype解析 

玩过C#的同学都知道,C#中有一个partial关键字,可以将一个类的实现分在多个文件中,最后由编译器组合起来。这样可以实现多人协作,分离手写和自动生成的代码。 

可能有人会抱怨,为什么Python没有提供这种功能呢?其实是提供了的,只不过比较隐蔽而已——这种问题可以使用元类(metaclass)来解决~ 

什么是元类呢?用一句话来说,元类就是类的类,一般的类是元类的实例。Python下可以使用type(obj)来获得一个变量的类型。type(一个类的实例)会返回那个类,type(一个类)则会返回这个类的元类。在不指明元类的情况下,旧版类的元类是classobj,新版类的元类就是type。这里有一个很有趣的事实:type的元类还是type,type的基类是object,object的元类是type…… 

说了这么多不相关的,到底PyPy的代码是怎样实现partial class的呢? 请看pypy/tool/pairtype.py: 
''' 

class extendabletype(type): 
    """A type with a syntax trick: 'class __extend__(t)' actually extends 
the definition of 't' instead of creating a new subclass.""" 
    def __new__(cls, name, bases, dict): #当创建新类的时候,调用这个函数。此时cls相当与self,不过指的是当前的元类;name是新类的名字;bases是新类的基类;dict是新类的内容,也就是class定义后的那些东西,函数,类变量等等。 
        if name == '__extend__': 
            for cls in bases: 
                for key, value in dict.items(): 
                    if key == '__module__': 
                        continue 
                    # XXX do we need to provide something more for pickling? 
                    setattr(cls, key, value) 
            return None 
        else: 
            return super(extendabletype, cls).__new__(cls, name, bases, dict# 相当于type.__new__(xxxx) 
             
''' 
可以看出,这个元类实现的功能很简单:如果新类的名字是'__extend__',那么不创建新类,而是把新类的dict合并到基类中,这样就相当与扩充了基类! 
举个例子: 
''' 

class MyClass(object): 
    __metaclass__ = extendabletype 
     
    def myprint1(): 
        print "Proton rocks!" 

class __extend__(MyClass): 
    def myprint2(): 
        print "Proton really rocks!" 

#与 

class MyClass(object): 
     
    def myprint1(): 
        print "Proton rocks!" 

    def myprint2(): 
        print "Proton really rocks!" 
         
''' 
是完全一样的! 
知道了这些,就留个小的练习吧: C#中的sealed关键字(不能被继承)在Python中怎么实现呢?只要发现违规用法报错就可以。 

pairtype则是一个更有趣的东西:它的目的是将两个类组合在一起,来作为一个新的类。这么说很容易让人产生误解,还是看源码吧~ 
''' 

def pair(a, b): 
    """Return a pair object.""" 
    tp = pairtype(a.__class__, b.__class__) #根据a和b的类找到相应的pairtype 
    return tp((a, b)) # tp is a subclass of tuple, 根据a和b创建pairtype的实例 

pairtypecache = {} 

def pairtype(cls1, cls2):  
    """type(pair(a,b)) is pairtype(a.__class__, b.__class__).""" 
    try: 
        pair = pairtypecache[cls1, cls2] # 如果pairtype已经存在,就直接返回 
    except KeyError# 如果不存在,就创建一个相应的类 
        name = 'pairtype(%s%s)' % (cls1.__name__, cls2.__name__) 
        bases1 = [pairtype(base1, cls2) for base1 in cls1.__bases__] # 寻找所有的基类,比如pairtype(Human, Girl) 和 pairtype(Boy, Human)就应该是pairtype(Boy, Girl)的基类 
        bases2 = [pairtype(cls1, base2) for base2 in cls2.__bases__] 
        bases = tuple(bases1 + bases2) or (tuple,) # 'tuple': ultimate base 
        pair = pairtypecache[cls1, cls2] = extendabletype(name, bases, {}) # <- 注意是extendabletype,不是type哦 
    return pair 
''' 
恩 这个东西有什么好玩的呢? 在这里举个例子: 
''' 
class Human(object): 
    def __init__(self, name): 
       self.name = name 

class Boy(Human): pass 
class Girl(Human): pass 

class __extend__(pairtype(Human, Human)): 
    def talk((a, b)): # 注意pairtype的基类是tuple, 所以可以直接这样写 
        print "%s and %s are talking." % (a.name, b.name) 

class __extend__(pairtype(Boy, Boy)): 
    def duel((a, b)): 
        print "%s and %s try to prove they are real men, decided to duel." % (a.name, b.name) 

class __extend__(pairtype(Girl, Girl)): 
    def unlimited_talk((a, b)): 
        print "Girls are really scary, %s and %s kept talking for hours without drinking a single gulp of water." % (a.name, b.name) 

class __extend__(pairtype(Boy, Girl), pairtype(Girl, Boy)): 
    def makelove((a, b)): 
        print "%s and %s are... hey you knew it!" % (a.name, b.name) 

reimu = Girl("Reimu") 
marisa = Girl("Marisa") 
moku = Boy("Moku") 
rinnosuke = Boy("Rinnosuke") 

cp1 = pair(reimu, marisa) 
cp1.talk() 
cp1.unlimited_talk() 

cp2 = pair(moku, rinnosuke) 
cp2.talk() 
cp2.duel() 

cp3 = pair(rinnosuke, reimu) 
cp3.talk() 
cp3.makelove()

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值