KDTTAH #1: decorator magic

  1. От една страна, не е твърде трудно да се съобрази, че това, което се подава на един декоратор, съвсем не е нужно да бъде функция:

    def snoop(func):
        def snooping(*args, **kwargs):
            print("Now look who's {0}ing with {1} and {2}!".format(func.__name__, args, kwargs))
            return func(*args, **kwargs)
        return snooping
    
    @snoop
    def add(x, y): return x + y
    
    @snoop
    class hushhush:
        def __init__(self, secret):
            print("No one knows that we are hush-hushing, right?")
            self._secret = secret
        def tellmetellmetellme(self):
            return self._secret
    

    А като се замислиш, това може да доведе до... забавни ефекти :)

    def evil(func):
        def returnnone(*args, **kwargs):
            print('Ia!  Ia!  Shub-Niggurath!')
            return None
        return returnnone
    
    @evil
    class victim:
        def __init__(self, foo):
            print('Initializing a', self.__class__.__name__, 'object with', foo)
            self._something = foo
        def __call__(self):
            return self._something
    

    А кой питаше за това дали един декоратор може да бъде приложен към самия себе си? :)

    def muenchhausen(func):
        print('Trying to pull', func.__name__, 'out by its hair...')
        return func(func)
    
    @muenchhausen
    def improve(func):
        def improved(*args, **kwargs):
            print("Hey now, don't you just love the new and improved {0}!".format(func.__name__))
            return func(*args, **kwargs)
        print('Improving', func.__name__)
        return improved
    

    Но, както си пише и в заглавието на темата, не опитвайте това вкъщи!... а на работа - още по-малко! :P

    ...а може би е добре да си лягам да спя, преди да ми е хрумнала още някоя простотия...

    Публикувано преди
  2. Мняяяяяя, не се получи това със заспиването веднага и това си е - просто преди да изключа компютъра успя да ми хрумне още една простотия :)

    def snoop(func):
        def snooping(*args, **kwargs):
            print("Now look who's {0}ing with {1} and {2}!".format(func.__name__, args, kwargs))
            return func(*args, **kwargs)
        print('Trying to snoop on', func, 'of class', func.__class__.__name__)
        if func.__class__.__name__ == 'type':
            print("Whee, it's a class!")
            for (name, value) in func.__dict__.items():
                print('- class', func.__name__, '- examining', name, 'of type', value.__class__.__name__)
                if value.__class__.__name__ == 'function':
                    print('- class', func.__name__, '- need to replace', name)
                    func.__class__.__setattr__(func, name, snoop(value))
        return snooping
    

    Естествено, опитах да го направя напълно - с if value.__class__.__name__ in ('function', type') :) Е, оказа се, че е проблем, когато в класа, върху който snoop–вам, има дефинирани подкласове - те биват заместени с функции и съответно опита да инстанциирам обект от този тип (опит, който snoop-ваният клас си прави, без да знае, че някой го snoop-ва), не минава съвсем. Разбира се, досещам се, че това вероятно може да се оправи, като самият декоратор snoop не е функция, а клас, който използва още един-два магически метода... но с любимата ми реплика на Скарлет О'Хара, "за това ще мисля утре!"

    Публикувано преди

Трябва да сте влезли в системата, за да може да отговаряте на теми.