2

When using classmethod to dynamic change the method in subclass, how to dynamic change signatures of method?

example

import inspect class ModelBase(object): @classmethod def method_one(cls, *args): raise NotImplementedError @classmethod def method_two(cls, *args): return cls.method_one(*args) + 1 class SubClass(ModelBase): @staticmethod def method_one(a, b): return a + b test = SubClass() try: print(inspect.signature(test.method_two)) except AttributeError: print(inspect.getargspec(test.method_two).args) 

I want test.method_two to get the signatures of test.method_one. How to rewrite parent class ModelBase?

I have read about Preserving signatures of decorated functions. In python3.4 +, functools.wraps helps to preserve signatures of decorated functions. I want to apply it to class method.

when uses functools.wraps, I need to assign decorated method's name. But how to access decorated method outside classmethod in this situation?

from functools import wraps class ModelBase(object): @classmethod def method_one(cls, *args): raise NotImplementedError @classmethod def method_two(cls): @wraps(cls.method_one) def fun(*args): return cls.method_one(*args) + 1 return fun 

method_two returns a wrapped function, but I must use it with test.method_two()(*arg). This method is not directly.

1 Answer 1

1

If this is only for introspection purpose you could override __getattribute__ on ModelBase and every time method_two is accessed we return a function that has the signature of method_one.

import inspect def copy_signature(frm, to): def wrapper(*args, **kwargs): return to(*args, **kwargs) wrapper.__signature__ = inspect.signature(frm) return wrapper class ModelBase(object): @classmethod def method_one(cls, *args): raise NotImplementedError @classmethod def method_two(cls, *args): return cls.method_one(*args) + 1 def __getattribute__(self, attr): value = object.__getattribute__(self, attr) if attr == 'method_two': value = copy_signature(frm=self.method_one, to=value) return value class SubClass(ModelBase): @staticmethod def method_one(a, b): return a + b class SubClass2(ModelBase): @staticmethod def method_one(a, b, c, *arg): return a + b 

Demo:

>>> test1 = SubClass() >>> print(inspect.signature(test1.method_two)) (a, b) >>> test2 = SubClass2() >>> print(inspect.signature(test2.method_two)) (a, b, c, *arg) 
Sign up to request clarification or add additional context in comments.

1 Comment

Thank you! It's for CodeGen. To do codegen for method_two, it need the signatures of method_one.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.