सवाल आत्म तर्क के साथ पाइथन कक्षा विधि सजावट?


एक वर्ग विधि पर एक सजावट के रूप में एक कक्षा क्षेत्र को एक तर्क के रूप में कैसे पास करूं? मैं क्या करना चाहता हूं जैसे कुछ:

class Client(object):
    def __init__(self, url):
        self.url = url

    @check_authorization("some_attr", self.url)
    def get(self):
        do_work()

यह शिकायत करता है कि सजावटी को self.url पास करने के लिए स्वयं मौजूद नहीं है। क्या इसके चारों ओर एक रास्ता है?


76
2017-07-30 23:30


मूल


क्या यह एक कस्टम सजावट है जिस पर आपका नियंत्रण है, या एक जिसे आप बदल नहीं सकते? - Joel Cornett
यह मेरा सजावटी है, इसलिए मेरा पूरा नियंत्रण है - Mark
यह init से पहले बुलाया जाता है मुझे लगता है कि समस्या है ... - Joran Beasley
समस्या यह है कि फ़ंक्शन परिभाषा समय पर स्वयं मौजूद नहीं है। आपको इसे आंशिक कार्य में बनाना होगा। - Antimony


जवाब:


हाँ। कक्षा परिभाषा समय पर आवृत्ति विशेषता में गुजरने के बजाय, इसे रनटाइम पर जांचें:

def check_authorization(f):
    def wrapper(*args):
        print args[0].url
        return f(*args)
    return wrapper

class Client(object):
    def __init__(self, url):
        self.url = url

    @check_authorization
    def get(self):
        print 'get'

>>> Client('http://www.google.com').get()
http://www.google.com
get

सजावटी विधि तर्कों को रोकता है; पहला तर्क उदाहरण है, इसलिए यह उस विशेषता को पढ़ता है। आप विशेषता नाम में सजावट के लिए स्ट्रिंग के रूप में पास कर सकते हैं और उपयोग कर सकते हैं getattr यदि आप विशेषता नाम को हार्डकोड नहीं करना चाहते हैं:

def check_authorization(attribute):
    def _check_authorization(f):
        def wrapper(self, *args):
            print getattr(self, attribute)
            return f(self, *args)
        return wrapper
    return _check_authorization

113
2017-07-30 23:38





from re import search
from functools import wraps

def is_match(_lambda, pattern):
    def wrapper(f):
        @wraps(f)
        def wrapped(self, *f_args, **f_kwargs):
            if callable(_lambda) and search(pattern, (_lambda(self) or '')): 
                f(self, *f_args, **f_kwargs)
        return wrapped
    return wrapper

class MyTest(object):

    def __init__(self):
        self.name = 'foo'
        self.surname = 'bar'

    @is_match(lambda x: x.name, 'foo')
    @is_match(lambda x: x.surname, 'foo')
    def my_rule(self):
        print 'my_rule : ok'

    @is_match(lambda x: x.name, 'foo')
    @is_match(lambda x: x.surname, 'bar')
    def my_rule2(self):
        print 'my_rule2 : ok'



test = MyTest()
test.my_rule()
test.my_rule2()

ouput:   my_rule2: ठीक है


21
2018-05-03 11:52



आपको बहुत - बहुत धन्यवाद! यह स्वीकार्य उत्तर होना चाहिए। मैं कक्षा के तरीकों के लिए सजावटी को समझने की कोशिश कर अपने बालों को फाड़ रहा था। - benshepherd
@raphael इस सेटअप में मैं _lambda या पैटर्न तक नहीं पहुंच सकता। मैं इसका समाधान कैसे कर सकता हूं। - Jonathan
@ राफेल: मैं क्लासमेड के लिए ऐसा कैसे कर सकता हूं, क्योंकि यहां सभी विधियां उदाहरण विधियां हैं। - Apurva Kunkulol


निम्नानुसार एक संक्षिप्त उदाहरण हो सकता है:

#/usr/bin/env python3
from functools import wraps

def wrapper(method):
    @wraps(method)
    def _impl(self, *method_args, **method_kwargs):
        return method(self, *method_args, **method_kwargs) + "!"
    return _impl

class Foo:
    @wrapper
    def bar(self, word):
        return word

f = Foo()
result = f.bar("kitty")
print(result)

कौन सा प्रिंट करेगा:

kitty!

15
2018-04-29 18:13





आप नहीं कर सकते वहाँ कोई नहीं self कक्षा के शरीर में, क्योंकि कोई उदाहरण मौजूद नहीं है। आपको इसे पास करने की आवश्यकता होगी, कहें, ए str उदाहरण पर लुकअप करने के लिए विशेषता नाम शामिल है, जो लौटाया गया कार्य तब कर सकता है, या पूरी तरह से एक अलग विधि का उपयोग कर सकते हैं।


2
2017-07-30 23:38