2011-06-24 38 views
8

Mam obsługi życzenie i dekorator, chciałbym pracować z przedmiotem samodzielnego wewnątrz dekoratoraDostęp argumenty funkcji od dekoratora

class MyHandler(webapp.RequestHandler): 

    @myDecorator 
     def get(self): 
      #code 

UPDATE: Proszę zauważyć różnicę między pierwszym a drugim ja

class myDecorator(object): 

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

    def __call__(self): 
     #work with self 
  1. MyHandler>get (funkcja)>self (argumentu)
  2. myDecorator>__call__ (funkcja)>self (argumentu)

argumenty własny wymienione powyżej są różne. Moją intencją jest uzyskanie dostępu do pierwszego siebie z poziomu funkcji __call__ lub znalezienie sposobu na zrobienie czegoś podobnego.

Witam mogę uzyskać dostęp do argumentu MyHandlers z funkcji get wewnątrz dekoratora?

Update2: Chcę zaimplementować dekorator do pracy z niestandardowego logowania w Google App Engine:

Mam klasy (requestHandler):

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

I chcę do dekoracji dostać funkcji w celu sprawdzenia, czy użytkownik jest zalogowany czy nie:

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 

wiem, czy stosowanie r jest zalogowany, jeśli ma właściwość 'user_key' w obiekcie sesji.

To główny cel jestem zainteresowany w tym konkretnym przypadku

Daj mi znać swoje sugestie/opinie jeśli robię coś złego!

Dzięki!

+0

Również oddanie „Google App Engine” przed pytaniem, które jest tylko o dekoratorów może uczynią Twoje pytanie dostać mniej widoki. Ogólne przedmioty są często oglądane, pytania o określone platformy są oglądane i wolniej odpowiedział. – marr75

+0

Poprawione, dziękuję @ marr75 –

+1

Nie ma problemu, jeśli twoje pytanie zostanie wyświetlone więcej, moja odpowiedź może uzyskać więcej głosów. To wygrana. – marr75

Odpowiedz

9

Nie jestem do końca pewien, czego chcesz, ale jeśli chcesz użyć argumentów zdobionej funkcji, to właśnie to robi podstawowy dekorator. Tak, aby uzyskać dostęp powiedzmy self.request z dekorator można zrobić:

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') 

Jeśli próbujesz uzyskać dostęp do klasy funkcja urządzony jest dołączony do, to jest nieco tricker i będziesz musiał oszukiwać trochę używając moduł inspect.

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 

W powyższym przykładzie pobrać nazwę klasy z currentFrame (w trakcie wykonywania dekoratora), a następnie przechowywać, że w zależności wystroju.Tutaj właśnie dodajemy nazwę klasy do dowolnej zmiennej msg przed przekazaniem jej do oryginalnej funkcji say, ale możesz użyć swojej wyobraźni, aby zrobić to, co chcesz, kiedy już masz nazwę klasy.

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

Właśnie zaktualizowałem problem, aby było bardziej zrozumiałe, widzę, że mogę użyć inspekcji dla klasy, ale chciałbym użyć argumentu udekorowanej funkcji. Czy to jest możliwe? thx @Chris –

+0

Niestety nadal nie jest jasne, co próbujesz osiągnąć ... ale i tak zaktualizowałem odpowiedź, dodając trochę więcej informacji. –

+0

Dodałem nową aktualizację (2) do konkretnego przypadku, proszę dać mi znać. Wielkie dzięki! –

0

self argument __call__ zostanie wypełniona przykład zdobione metoda jest nazywany dalej. Nie ma sposobu, aby uzyskać dostęp do obiektu dekoratora stąd - __call__ jest metodą związaną, a to, o co prosisz, wymagałoby w rzeczywistości, aby była "podwójnie związana". Python tego nie obsługuje, więc instancja dekoratora zostaje zastąpiona pierwszym argumentem funkcji dekorowanej.

Najprostszym sposobem obejścia tego problemu jest użycie funkcji zagnieżdżonych, jak zaleca @Chris.

1
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() 
1

source

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>