# -*- 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()
分享到:
相关推荐
- **环境变量配置**: 安装完成后,可能需要将 PyPy 的 bin 目录添加到系统环境变量 PATH 中,以便在命令行中直接运行 PyPy。 - **测试运行**: 可以通过运行 `pypy.exe` 文件来启动 PyPy 解释器,并输入简单的 ...
这种动态编译技术可以优化掉许多Python解释器中的开销,如动态类型检查和运行时的字节码解析。 **PyPy的RPython** PyPy的实现基于一种称为“Restricted Python”或RPython的子集。RPython是一种受到限制的Python...
- 一旦安装完成并配置了 PATH,用户可以在命令行中输入 `pypy` 来启动 PyPy 解释器,与使用 CPython 的 `python` 命令类似。 - PyPy 支持大部分 Python 2.7 的语法和库,因此已有的 Python 2.7 代码通常可以直接在...
与CPython的区别可以去看它的兼容性页面. PyPy还提供了JIT编译器和沙盒功能,因此运行速度比CPython要快,以及可以安全的运行一些不被信任的代码。PyPy还有一个单独的支持微线程的版本。 另外,PyPy 也有 每夜构建 ...
标题 "pypy_get_pip-master.zip" 暗示了这是一个与PyPy和pip相关的项目,主要用于在PyPy环境中安装pip。PyPy是Python的一个替代实现,它具有自己的JIT(Just-In-Time)编译器,以提高代码执行速度。而pip是Python的...
1. **PyPy与CPython的区别**:PyPy 是一个使用RPython语言编写,具有JIT编译器的Python实现,其目标是速度和兼容性。与CPython相比,PyPy通常在执行速度上有显著提升,特别是在处理循环和大量数据时。 2. **JIT...
本文将深入讨论`jitpy`库,它是如何在CPython(Python的标准实现)中嵌入PyPy(一个优化的Python解释器),以及如何通过这种方式实现性能的显著提升。 `jitpy`是一个开源库,它的主要目标是让开发者能够在CPython...
将该文件所在的目录添加到系统的PATH环境变量中,即可在命令行中直接运行PyPy。例如,通过命令`pypy3 your_script.py`来执行Python脚本。 **适用场景** 1. **性能敏感的项目**:当需要在Python环境中执行大量计算...
与传统的解释器不同,Pypy的JIT不是在程序运行前进行静态编译,而是在运行时动态编译经常执行的代码片段。这种技术可以显著提高代码的执行效率,尤其是在循环和递归等复杂计算场景下,使得Python代码的运行速度接近...
与CPython不同,Pypy使用了一种称为“轻量级虚拟机”的技术,这种技术允许更快的代码解析和执行。Pypy还使用了一种称为“垃圾回收”的内存管理策略,该策略比CPython的垃圾回收更高效,减少了内存占用和延迟。 Pypy...
3. **src** 目录:包含了PyPy解释器的主要源代码,包括Python解释器的实现、JIT编译器以及CFFI(C Foreign Function Interface),用于与C库交互。 4. **rpython** 目录:RPython是PyPy使用的特殊编程子集,用于...
Python官方的解释器是CPython,执行速度较慢,网上目前有许多PyPy和CPython的性能对比,PyPy比CPython快近25倍。原因是PyPy采用了先进的JIT编译器优化。 官网上的对比图: 先不扯淡了,知道你们可能听不懂。拐入...
1. **CFFI(C Foreign Function Interface)**: Pypy提供了CFFI,使得在Python中调用C库变得非常方便,进一步增强了Pypy的扩展性。 2. **垃圾收集**:Pypy采用了一种名为“混合垃圾收集”的策略,结合了引用计数和...
PyPy的实现与原理 PyPy的第一部分:用Python实现的Python 其实这么说并不准确,准确得说应该是用rPython实现的Python,rPython是Python的一个子集,虽然rPython不是完整的Python,但用rPython写的这个Python实现却是...
安装和使用PyPy3.6-v7.3.2-win32时,你需要解压这个压缩包到一个适当的目录,然后可以通过解压目录下的`bin`目录中的`pypy3.exe`或`pypy3`命令行脚本来启动PyPy解释器。这允许你像使用常规Python那样运行Python程序...
numpy-2.1.0rc1-pp310-pypy310_pp73-win_amd64.whl numpy-2.1.0rc1-pp310-pypy310_pp73-win_amd64.whl numpy-2.1.0rc1-pp310-pypy310_pp73-win_amd64.whl numpy-2.1.0rc1-pp310-pypy310_pp73-win_amd64.whl numpy-...
《GDAL库在Python环境中的应用与安装》 GDAL(Geospatial Data Abstraction Library)是一个开源的地理空间数据处理库,它提供了对多种遥感和地图数据格式的读取、写入和转换功能。在给定的文件“GDAL-3.8.2-pp310-...
PyPy 是用 Python 实现的 Python 解释器。PyPy 是 Python开发者为了更好的Hack Python创建的项目。此外,PyPy比CPython是更加灵活,易于使用和试验,以制定具体的功能在不同情况的实现方法,可以很容易实施。 该项目...
pypy2-v6.0.0,pypy最新版压缩包,是Python2.7替代产品,支持大多数的常用python标准包