python. декоратор метода класса с параметром объекта.

Phoenix


import threading


def mutex_decorator(lock):
def wrapper(func,*args, **kwargs):
def resultfunc(*args, **kwargs):
e = None
lock.acquire
try:
ret = func(*args, **kwargs)
except Exception, ex:
e = ex
lock.release
if e:
raise e
return ret
return resultfunc
return wrapper



class MyClass(object):
def __init__(self):
self.mutex = threading.Lock

@mutex_decorator(self.mutex)
def do_something(self):
pass



def main:
c = MyClass



if __name__ == '__main__':
main

пишет

F:\igor\apps\stockgate\tmp>python dd.py
Traceback (most recent call last):
File "dd.py", line 22, in <module>
class MyClass(object):
File "dd.py", line 26, in MyClass
@mutex_decorator(self.mutex)
NameError: name 'self' is not defined

Почему так происходит - я понимаю.
Как поправить? сейчас вынес мутекс на уровень класса и в декоратор передаю без self, но тогда все экземпляры будут использовать один мутекс, что равносильно просто глобальному мутексу.
есть ещё вариант передавать имя мутекса строкой, потом из первого аргумента функции брать self, искать там это имя, но это уже какой-то совсем изврат.

pilot

есть ещё вариант передавать имя мутекса строкой, потом из первого аргумента функции брать self, искать там это имя, но это уже какой-то совсем изврат.
У тебя в примере mutex всегда self.mutex, зачем передавать имя, если и так знаешь?

Phoenix

в реальном приложении он не один.

pilot

Тогда
передавать имя мутекса строкой, потом из первого аргумента функции брать self, искать там это имя

— нормальный вариант.

Dmitriy82

Не по теме, но
        def resultfunc(*args, **kwargs):
lock.acquire
try:
return func(*args, **kwargs)
finally:
lock.release

Dmitriy82

or even better
with lock:
return func(...)

И тогда зачем тебе вообще этот декоратор нужен?

Phoenix

А вот это симпатично.
до этого try-finally использовал, но в двух местах (лочим, размлочим) - и когда их 2-3разных мутексов уже сложно читать - поэтому решил найти что-нибудь поудобнее.
всем спасибо!

pilot

А вот это симпатично.
Блин, прочитай уже наконец доки хоть раз. :mad:

Phoenix

Да оно там в самом конце, я не увидел. :o

psihodog

 import threading

def mutex_decorator(lock):
    def wrapper(func,*args, **kwargs):
     def resultfunc(*args, **kwargs):
     e = None
     lock.acquire
     try:
     ret = func(*args, **kwargs)
     except Exception, ex:
     e = ex
     lock.release
     if e:
     raise e
     return ret
     return resultfunc
    return wrapper
    
    
    
class MyClass(object):
    def __init__(self):
     self.mutex = threading.Lock
    
    @mutex_decorator(self.mutex)
    def do_something(self):
     pass
    
    
    
def main:
    c = MyClass
    
    
    
if __name__ == '__main__':
    main
это всё жуткий бред (не сочти за грубость :) )
этот код показывает, что ты не понимаешь как создаются классы в питоне и как работают декораторы.
разберись с этим! (если, конечно, тебе нужно писать на питоне)

Phoenix




import threading

def mutex_decorator(lock):
def wrapper(func,*args, **kwargs):
def resultfunc(*args, **kwargs):
e = None
lock.acquire
try:
ret = func(*args, **kwargs)
except Exception, ex:
e = ex
lock.release
if e:
raise e
return ret
return resultfunc
return wrapper



class MyClass(object):
mutex = threading.Lock

def __init__(self):

@mutex_decorator(mutex)
def do_something(self):
pass



def main:
c = MyClass



if __name__ == '__main__':
main


Вот так, если без ошибки - что тут не нравится? Ошибка там специально сделана, чтобы показать, что я хочу.

psihodog

если специально, то беру свои слова назад :)

rosali

Почему так происходит - я понимаю.
уверен? :p
декоратор это не более чем функция которая принимаем функцию на вход и возвращает функцию на выход, никакой магии. тебе её нужно параметризовать не полем self-а, а тем что в С++ называется member-pointer, то есть штучкой, которая задает отображение объектов в какое-то их поле. если у вас в питоне в качестве member-pointer-а нет ничего лучшего чем просто строка-имя-поля, ну значит да, придется через строку, что такого.

Phoenix

Да. всё имено так я и понимаю.
и меня уже ткнули в моё незнание stdlib и более красивое использование Lock без декоратора конструкцией в одну строку :)
Ведь проблема ставилась чуть шире.
Когда много мутексов, можно случайно какой-нибудь не разлочить и если это какая-нибудь редкая ветвь - получить когда-нибудь в будущем дедлок или геморой с поиском на этапе отладки

rosali

я питон совсем чуть чуть знаю, но наверняка там можно написать функцию lock(mutext) которая бы возвращала объект, который в деструкторе бы разлочивал этот мутекс. тогда забыть разлочить было бы невозможно. или в питоне трудно контролировать момент деструктора как в яве? в с++ и в перле с этим всё просто, вышла переменная из скопа - вызывается деструктор.
Оставить комментарий
Имя или ник:
Комментарий: