Как автоматически выставлять и украшать версии функций методов в Python? - PullRequest
2 голосов
/ 29 февраля 2012

Я хотел бы представить методы класса как функции (после оформления) в моей локальной области видимости.Например, если бы у меня был класс и декоратор:

def some_decorator(f):
    ...transform f...
    return decorated_f

class C(object):
    def __init__(self,x):
        self.x = x
    def f(self,y):
        "Some doc string"
        return self.x + y
    def g(self,y,z):
        "Some other doc string"
        return self.x + y + z

и если я не заботился об автоматизации процесса, я мог бы добавить следующий код в мой модуль:

@some_decorator
def f(C_instance,x):
    "Some doc string."
    return C_instance.f(x)

@some_decorator
def g(C_instance,x,y):
    "Some other doc string."
    return C_instance.g(x,y)    

для того, чтобы следующее значение оценивалось как True

c = C(0)
f(c,1) == c.f(1)

Но я бы хотел сделать это автоматически.Что-то вроде:

my_funs = expose_methods(MyClass)
for funname, fun in my_funs.iteritems():
    locals()[funname] = some_decorator(fun)

foo = MyClass(data)
some_functionality(foo,*args) == foo.some_functionality(*args)

сделает свое дело (хотя он чувствует себя немного неправильно, объявляя локальные переменные таким образом).Как я могу сделать это таким образом, чтобы все соответствующие атрибуты метода правильно преобразовывались в версии функций?Буду признателен за любые предложения.

PS

Я знаю, что могу украсить методы экземпляров классов, но на самом деле это не то, что мне нужно.Это больше касается (1) предпочтения синтаксиса версии функции (2) того факта, что мои декораторы заставляют функции отображать коллекции объектов причудливыми и оптимизированными способами.Получение поведения (2) путем декорирования методов потребовало бы, чтобы классы моих коллекций наследовали атрибуты от содержащихся в них объектов, что ортогонально семантике коллекции.

Ответы [ 2 ]

3 голосов
/ 29 февраля 2012

Знаете ли вы, что вы можете напрямую использовать несвязанные методы?

obj.foo(arg) эквивалентно ObjClass.foo(obj, arg)

class MyClass(object):
    def foo(self, arg):
        ...

obj = MyClass()
print obj.foo(3) == MyClass.foo(obj, 3) # True

См. Также Различия методов класса в Python:связанный, несвязанный и статический и документация .

0 голосов
/ 01 марта 2012

Вы говорите, что предпочитаете синтаксис функции. Вместо этого вы можете просто определить все свои методы вне класса, и они будут работать именно так, как вы хотите.

class C(object):
    def __init__(self,x):
        self.x = x

def f(c,y):
    "Some doc string"
    return c.x + y
def g(c,y,z):
    "Some other doc string"
    return c.x + y + z

Если вы хотите, чтобы они тоже были в классе, вы всегда можете:

for func in f, g:
    setattr(C, func.__name__, func)

Или с внутренним самоанализом вместо интроспекции имени функции:

for name in 'f', 'g':
    setattr(C, name, locals()[name])

Или без самоанализа, который, возможно, намного проще и проще в управлении, если у вас не достаточно много этих методов / функций:

C.f = f
C.g = g

Это также позволяет избежать потенциальной проблемы, упомянутой в комментариях к ответу codeape о проверке Python, что первый аргумент несвязанного метода является экземпляром класса.

...