Доступ к аргументам функции из decorator

у меня есть обработчик запросов и декоратор, я хотел бы работать с объектом self внутри декоратора

class MyHandler(webapp.RequestHandler):

    @myDecorator
        def get(self):
            #code

обновление: Пожалуйста, обратите внимание на разницу между первым и вторым я

class myDecorator(object):

    def __init__(self, f):
        self.f = f

    def __call__(self):
        #work with self
  1. MyHandler>get ( функция ) > self ( рассуждение )
  2. myDecorator>__call__ ( функция ) > self ( рассуждение )

аргументы "я", упомянутые выше, различны. Мой намерение открыть первый самостоятельный изнутри __call__ функции, или найти способ сделать что-то подобное.

Привет могу ли я получить доступ к аргументу myhandlers self из функции get внутри декоратора?

Update2: я хочу реализовать декоратор для работы с пользовательским логином в Google app engine:

у меня есть класс ( requestHandler ):

class SomeHandler(webapp.RequestHandler):
    @only_registered_users
    def get(self):
        #do stuff here

и я хочу украсить функцию get, чтобы проверить, является ли пользователь вошел в систему или нет:

from util.sessions import Session
import logging

class only_registered_users(object):

    def __init__(self, f):
        self.f = f

    def __call__(self):
        def decorated_get(self):
        logging.debug("request object:", self.request)
        session = Session()

        if hasattr(session, 'user_key'):
            return self.f(self)
        else:
            self.request.redirect("/login")


    return decorated_get

я знаю, если пользователь вошел в систему, если имеет свойство "user_key" в объекте сеанса.

это главная цель, которая меня интересует в этом конкретном случае

Дайте мне знать ваши предложения / мнения, если я делаю что-то неправильно!

спасибо!

5 ответов


Я не совсем понимаю, чего вы хотите, но если вы просто хотите использовать аргументы украшенной функции, то это именно то, что делает основной декоратор. Итак, чтобы открыть, скажем, self.request от декоратора вы могли бы сделать:

def log_request(fn):
    def decorated_get(self):
        logging.debug("request object:", self.request)
        return fn(self)
    return decorated_get

class MyHandler(webapp. RequestHandler):
    @log_request
    def get(self):
        self.response.out.write('hello world')

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

import inspect

def class_printer(fn):
    cls = inspect.getouterframes(inspect.currentframe())[1][3]
    def decorated_fn(self, msg):
        fn(self,cls+" says: "+msg)
    return decorated_fn

class MyClass():
    @class_printer
    def say(self, msg):
        print msg

в приведенном выше примере мы получаем имя класс из currentframe (во время выполнения декоратора), а затем сохраните его в функции decorated. Здесь мы просто добавляем имя класса к тому, что msg переменная перед передачей ее в исходное say функция, но вы можете использовать свое воображение, чтобы делать то, что вам нравится, когда у вас есть имя класса.

>>> MyClass().say('hello')
MyClass says: hello

попробуйте этот подход:может ли декоратор Python метода экземпляра получить доступ к классу?

Не тот же самый вопрос, но вы должны иметь возможность использовать тот же подход для создания ссылки на себя или ссылки на словарь с объектами определенного класса в нем, которые вы можете получить в своем декораторе.


import random

#decorator to the get function in order to check out if the user is logged in or not
def only_registered_users(func):
    def wrapper(handler):
        print 'Checking if user is logged in'
        if random.randint(0, 1):
            print 'User is logged in. Calling the original function.'
            func(handler)
        else:
            print 'User is NOT logged in. Redirecting...'
            # redirect code here
    return wrapper


class MyHandler(object):

    @only_registered_users
    def get(self):
        print 'Get function called'



m = MyHandler()
m.get()

источник

def p_decorate(func):
   def func_wrapper(name):
       return "<p>{0}</p>".format(func(name))
   return func_wrapper

@p_decorate
def get_text(name):
   return "lorem ipsum, {0} dolor sit amet".format(name)

print get_text("John")

# Outputs <p>lorem ipsum, John dolor sit amet</p>

на