модификаторы функций backport в python2.1 - PullRequest
3 голосов
/ 21 июля 2009

У меня есть некоторый код, который я разработал на 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, но я не нашел ни одного (я имею в виду: работа). Кто-нибудь успешно решил эту проблему?

Чтобы быть более конкретным, мне нужен способ запустить этот код 2.4 в python 2.1:

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 ]

2 голосов
/ 21 июля 2009

Так же, как в моем старом рецепте для статического метода 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 () волшебным образом получала этот класс.

Поскольку отсутствие синтаксиса @ в 2.1 неизбежно требует редактирования кода, использующего @classmethod, альтернативой является перемещение функциональности (декорируя некоторые методы как «классовые») вправо ПОСЛЕ конца class оператор (преимущество в том, что объект класса существует в то время).

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'])
1 голос
/ 21 июля 2009

Если нужно просто перенести @classmethod на Python 2.1.
Существует рецепт эмуляции Classmethod в python2.1
Надеюсь, что это поможет.

...