向python2.1的backport函数修饰符

我有一些我在python 2.4中开发的代码,您敢打赌,我必须将其反向移植到python 2.1!

函数装饰器是如此吸引人,以至于我在几个地方都使用过@classmethod,而没有注意到它仅在2.4版开始可用.函数修饰符提供了相同的功能,但它们出现在python 2.2中. CFR:http://www.python.org/dev/peps/pep-0318/

现在我们的一些客户似乎仍然依赖python 2.1(ArcGIS 9.1附带了它并使其无法升级),甚至连功能修饰符都不可用…

我一直在python 2.1中寻找一些函数修饰符定义,但没有找到任何(我的意思是:正在工作).有人成功解决了这个问题吗?

更具体地说,我需要一种在python 2.1中运行此2.4代码的方法:

Python 2.4.6 (#2, Mar 19 2009, 10:00:53) 
[GCC 4.3.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> class sic:
...   def f(cls):
...     print cls.__name__
...   f = classmethod(f)
... 
>>> sic().f()
sic
>>> sic.f()
sic
>>> 

解决方法:

就像在我的2.1静态方法的旧食谱中一样:

class staticmethod:
    def __init__(self, thefunc): self.f = thefunc
    def __call__(self, *a, **k): return self.f(*a, **k)

您应该能够执行2.1类方法:

class classmethod:
    def __init__(self, thefunc): self.f = thefunc
    def __call__(self, obj, *a, **k): return self.f(obj.__class__, *a, **k)

当然,没有@语法,而是旧方法(例如2.2中的方法):

class sic:
  def f(cls): ...
  f = classmethod(f)

如果这不起作用(很抱歉,自从我有Python 2.1进行测试以来已经有很多年了),则需要更明确地提供该类-并且由于您在类对象存在之前调用了classmethod,因此它需要名列前茅-假设是全球班级,

class classmethod2:
    def __init__(self, thefunc, clsnam):
        self.f = thefunc
        self.clsnam = clsnam
    def __call__(self, *a, **k):
        klass = globals()[self.clsnam]
        return self.f(klass, *a, **k)

class sic2:
  def f(cls): ...
  f = classmethod2(f, 'sic2')

很难找到优雅的方法来获取类对象(抑制对self的需求是最容易的部分,并且满足staticmethod的需要:您只需要将函数包装为非函数可调用即可),因为2.1仅具有旧版(旧的样式类),没有可用的元类,因此没有真正好的方法让sic2.f()神奇地获得该cls.

由于2.1中缺少@语法,因此不可避免地需要编辑使用@classmethod的代码,因此,另一种方法是在类语句结束后将功能(将某些方法装饰为“类”方法)移到右边(优点是该类对象当时确实存在).

class classmethod3:
    def __init__(self, thefunc, klass):
        self.f = thefunc
        self.klass = klass
    def __call__(self, *a, **k):
        return self.f(self.klass, *a, **k)

def decorate(klass, klassmethodnames):
  for n in klassmethodnames:
    thefunc = klass.__dict__[n]
    setattr(klass, n, classmethod3(thefunc, klass))

class sic2:
  def f(cls): ...
  def g(self): ...
  def h(cls): ...
decorate(sic2, ['f', 'h'])
上一篇:是否可以以编程方式捕获JavaScript SyntaxErrors?


下一篇:python-NoneType没有属性追加