Как проверить, является ли объект определением метода? - PullRequest
1 голос
/ 19 июня 2019

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

def cached(f):
    def _internal(*args, **kwargs):
        if ismethod(f):
            key = create_key(*args[1:], **kwargs) # ignore self from args
        else: # this is a regular function
            key = create_key(*args, **kwargs)
        return actual_cache_mechanism(key, f, *args, **kwargs)
    return _internal

class A:
    @cached
    def b(self, something):
       ...

@cached
def c(something):
    ...

проблема в том, что когда вызывается @cached, он не может различить методы и функции, поскольку оба имеют тип function.это вообще можно сделать?Размышляя об этом, я чувствую, что на самом деле методы не имеют представления о контексте, в котором они определяются в ...

Спасибо!

Ответы [ 2 ]

0 голосов
/ 20 июня 2019

Я думаю, что желательно избегать такого интроспективного декоратора во имя хорошего питонского стиля.

Вы всегда можете выделить кэшируемую функцию, чтобы принять только необходимые аргументы:

@cached
def func(something):
    return ...

class A:
    def b(self, something):
        self.bvalue = func(something)

Для случая, упомянутого в комментариях (для получения результата необходим объект, но его значение не влияет на него, например, сокет), обратитесь к следующим вопросам: Как игнорировать параметр в functools.lru_cache? и Заставить @lru_cache игнорировать некоторые аргументы функции

0 голосов
/ 19 июня 2019

Это своего рода уродливый хак, но вы можете использовать obj.__qualname__, чтобы увидеть, был ли obj определен в классе, проверив, имеет ли он период

if "." in obj.__qualname__":
   #obj is a member of an object, so it is a method

Я не уверен, будет ли это хорошо работать для декораторов, хотя, чтобы это работало, метод должен быть определен в классе.

...