Используйте Python-декораторы для методов класса и методов подкласса - PullRequest
2 голосов
/ 26 апреля 2010

Цель: сделать возможным оформление методов класса. Когда метод класса оформляется, он сохраняется в словаре, так что другие методы класса могут ссылаться на него по строковому имени.

Мотивация: я хочу реализовать эквивалент веб-методов ASP.Net. Я строю это поверх движка приложений Google, но это не влияет на сложность, с которой я сталкиваюсь.

Как бы это выглядело, если бы это работало:

class UsefulClass(WebmethodBaseClass):
    def someMethod(self, blah):
        print(blah)

    @webmethod
    def webby(self, blah):
        print(blah)

# the implementation of this class could be completely different, it does not matter
# the only important thing is having access to the web methods defined in sub classes
class WebmethodBaseClass():
    def post(self, methodName):
        webmethods[methodName]("kapow")

    ...    

a = UsefulClass()
a.post("someMethod") # should error
a.post("webby")  # prints "kapow"

Могут быть и другие способы сделать это. Я очень открыт для предложений

Ответы [ 3 ]

4 голосов
/ 26 апреля 2010

Это не нужно. Просто используйте getattr:

class WebmethodBaseClass():
    def post(self, methodName):
        getattr(self, methodName)("kapow")

Единственное предостережение в том, что вы должны убедиться, что только методы, предназначенные для использования в качестве веб-методов, могут использоваться таким образом. Самым простым решением, IMO, является принятие соглашения о том, что не-веб-методы начинаются с подчеркивания, а метод post отказывается обслуживать такие имена.

Если вы действительно хотите использовать декораторы, попробуйте это:

def webmethod(f):
    f.is_webmethod = True
    return f

и получите post для проверки существования атрибута is_webmethod перед вызовом метода.

1 голос
/ 26 апреля 2010

Казалось бы, это самый простой подход для удовлетворения ваших требований, как указано:

webmethods = {}

def webmethod(f):
    webmethods[f.__name__] = f
    return f

, а в WebmethodBaseClass,

def post(self, methodName):
    webmethods[methodName](self, "kapow")

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

0 голосов
/ 26 апреля 2010
class UsefulClass(WebmethodBaseClass):

    def someMethod(self, blah):
        print(blah)

    @webmethod
    def webby(self, blah):
        print(blah)

class WebmethodBaseClass():
    def post(self, methodName):
        method = getattr(self, methodName)
        if method.webmethod:
            method("kapow")

    ...

def webmethod(f):
    f.webmethod = True
    return f

a = UsefulClass()
a.post("someMethod") # should error
a.post("webby")  # prints "kapow"
...