如何确保模块中的所有方法具有相同的签名?



模块内类中的所有函数都需要具有以下签名:

def func(i, x, y):
return ('done', (1,2) ) 

所有函数都是静态的。 我的类中的每个函数都应该有三个参数。 返回值应为元组。

这可能做到吗?元类可以在那里使用吗?

因此,问题中缺少的键,您作为注释完成 - 您希望在导入时进行检查。

只需创建一个具有适当__init_subclass__的基类即可进行检查。

class Base:
def __init_subclass__(cls, **kw):
super().__init_subclass__(**kw)
for name, obj in cls.__dict__.items():
if callable(obj) or isinstance(obj, classmethod):
raise TypeError(f"All methods in class {cls.__name__} should be declared static")
if isinstance(obj, staticmethod) and len(inspect.signature(obj.__get__(None, cls)).parameters) != 3:
raise TypeError(f"All functions inside class {cls.__name__} must accept exactly 3 parameters")
# class attributes that are not methods are ignored

如果您想将staticmethod装饰器自动应用于类内所有声明的函数,则可以改用元类:

class CheckPlugin(type):
def __new__(mcls, name, bases, namespace, **kw):
for attr_name, obj in namespace.items():
if callable(obj):
obj = staticmethod(obj)
namespace[attr_name] = obj
if isinstance(obj, classmethod):
raise TypeError(f"All methods in class {name} should be written as static methods")
if isinstance(obj, staticmethod) and len(inspect.signature(obj.__get__(None, cls)).parameters) != 3:
raise TypeError(f"All functions inside class {name} must accept exactly 3 parameters")
# class attributes that are not methods are ignored
return super().__new__(mcls, name, bases, namespace, **kw)

(再三考虑,没有什么可以阻止您将方法更改为__init_subclass__上的静态方法 - 真的不需要元类(:

class Base:
def __init_subclass__(cls, **kw):
super().__init_subclass__(**kw)
for name, obj in list(cls.__dict__.items()):  # the list() call iterates on a static copy of the class's proxy dict, as it will be modified in interation
if callable(obj):
obj = staticmethod(obj)
setattr(cls, name, obj)

if isinstance(obj, classmethod):
raise TypeError(f"All methods in class {cls.__name__} should be declared static")
if isinstance(obj, staticmethod) and len(inspect.signature(obj.__get__(None, cls)).parameters) != 3:
raise TypeError(f"All functions inside class {cls.__name__} must accept exactly 3 parameters")
# class attributes that are not methods are ignored

最后,如问题注释中所述,仅使用函数无法检查每个函数的返回值类型 - 它们可以被注释,上面的代码可以检查注释(如果返回值未正确注释,则会引发错误(。要验证注释没有"撒谎",唯一的方法是在运行之前正确使用 Mypy 和静态类型检查。

可以使用类型注释、静态类型检查和单元测试的组合来强制执行此操作。

使用带有inspect的单元测试循环访问类中的所有方法,并验证它们是否使用正确的签名进行批注:

https://docs.python.org/3/library/inspect.html

然后使用mypy验证方法的实现是否与注释匹配:

https://mypy.readthedocs.io/en/stable/

最新更新