স্ব-তর্ক নিয়ে ক্লাস মেথড ডেকরেটার?


154

আমি কীভাবে একটি আর্গুমেন্ট হিসাবে কোনও ক্লাস পদ্ধতিতে কোনও শ্রেণিকেন্দ্র একটি সজ্জাকারকে পাস করতে পারি? আমি যা করতে চাই তা হ'ল:

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

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

এটি অভিযোগ করে যে self.urlসাজসজ্জারের কাছে যাওয়ার জন্য স্বের অস্তিত্ব নেই । এই সমস্যা এড়ানোর একটি উপায় আছে কি?


এটি কি এমন একটি কাস্টম ডেকরেটার যা আপনার নিয়ন্ত্রণে আছে বা এমন একটি যা আপনি পরিবর্তন করতে পারবেন না?
জোয়েল করনেট

এটা আমার প্রসাধক, তাই আমি এটা উপর সম্পূর্ণ নিয়ন্ত্রণ আছে
মার্ক

এটি আমার মনে হয় সমস্যাটির আগে এটি কল হয়ে যায় ...
জোড়ান ব্যাসলি

7
সমস্যাটি হ'ল ফাংশন সংজ্ঞা সময়ে স্ব উপস্থিত নেই exist আপনি এটি একটি আংশিক ফাংশন করা প্রয়োজন।
এন্টিমোনি

উত্তর:


208

হ্যাঁ. ক্লাস সংজ্ঞা সময়ে ইভেন্ট অ্যাট্রিবিউটটি পাস করার পরিবর্তে এটি রানটাইমে পরীক্ষা করে দেখুন:

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

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

আউটপুট: my_rule2: ঠিক আছে


@raphael এই সেটআপে আমি _ লাম্বদা বা প্যাটার্ন অ্যাক্সেস করতে পারছি না। আমি কীভাবে প্রতিকার করব?
জোনাথন

1
@ রাফেল: আমি শ্রেণিবদ্ধের জন্য কীভাবে একই কাজ করতে পারি, যেহেতু এখানে সমস্ত পদ্ধতি উদাহরণ পদ্ধতি।
অপূর্ব কুঙ্কুলল

38

আরও সংক্ষিপ্ত উদাহরণ নিম্নলিখিত হিসাবে হতে পারে:

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

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

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

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

যা মুদ্রণ করবে:

kitty!

6

আরেকটি বিকল্প হ'ল সিনট্যাকটিক চিনি ছেড়ে দিয়ে __init__ক্লাসের মধ্যে সাজাইয়া রাখা ।

def countdown(number):
    def countdown_decorator(func):
        def func_wrapper():
            for index in reversed(range(1, number+1)):
                print("{}".format(index))
            func()
        return func_wrapper
    return countdown_decorator

class MySuperClass():
    def __init__(self, number):
        self.number = number
        self.do_thing = countdown(number)(self.do_thing)

    def do_thing(self):
        print('im doing stuff!')


myclass = MySuperClass(3)

myclass.do_thing()

যা মুদ্রণ করবে

3
2
1
im doing stuff!

4

আপনি পারবেন না। কোন ব্যাপার selfকারণ উদাহরণস্বরূপ বিদ্যমান, বর্গ শরীরে। আপনাকে এটি পাস করার প্রয়োজন হবে, বলুন, strউদাহরণটিতে অনুসন্ধানের জন্য বিশিষ্ট নাম সম্বলিত একটি বৈশিষ্ট্য, যা প্রত্যাবর্তিত ফাংশনটি পরে করতে পারে বা পুরোপুরি একটি আলাদা পদ্ধতি ব্যবহার করতে পারে।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.