如何确保模块中的所有方法都具有相同的签名?
How do I ensure all methods in a module have the same signature?
模块中 class 中的所有函数都需要具有以下签名:
def func(i, x, y):
return ('done', (1,2) )
所有函数都是静态的。
我的 class 中的每个函数都应该有三个参数。
return 应该是一个元组。
可以吗?那里可以用metaclass吗?
您可以结合使用类型注释、静态类型检查和单元测试来强制执行此操作。
使用带有 inspect
的单元测试来遍历 class 中的所有方法并验证它们是否使用正确的签名进行注释:
https://docs.python.org/3/library/inspect.html
然后使用mypy
验证方法的实现是否与注释匹配:
所以,问题中缺少的关键,您作为评论完成了 - 您希望在导入时进行检查。
只需创建一个基础 class 并使用适当的 __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:
中所有已声明的函数,则可以改用 metaclass
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__
上的方法更改为静态方法——实际上不需要 metaclass):
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
最后,如问题评论中所述,无法仅使用函数来检查每个函数的 return 值类型 - 它们可以被注释,并且上面的代码可以检查但是注释(如果 return 值未正确注释,则会引发错误)。要验证注释不是“说谎”,唯一的方法是在 运行.
之前正确使用 Mypy 和静态类型检查
模块中 class 中的所有函数都需要具有以下签名:
def func(i, x, y):
return ('done', (1,2) )
所有函数都是静态的。 我的 class 中的每个函数都应该有三个参数。 return 应该是一个元组。
可以吗?那里可以用metaclass吗?
您可以结合使用类型注释、静态类型检查和单元测试来强制执行此操作。
使用带有 inspect
的单元测试来遍历 class 中的所有方法并验证它们是否使用正确的签名进行注释:
https://docs.python.org/3/library/inspect.html
然后使用mypy
验证方法的实现是否与注释匹配:
所以,问题中缺少的关键,您作为评论完成了 - 您希望在导入时进行检查。
只需创建一个基础 class 并使用适当的 __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:
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__
上的方法更改为静态方法——实际上不需要 metaclass):
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
最后,如问题评论中所述,无法仅使用函数来检查每个函数的 return 值类型 - 它们可以被注释,并且上面的代码可以检查但是注释(如果 return 值未正确注释,则会引发错误)。要验证注释不是“说谎”,唯一的方法是在 运行.
之前正确使用 Mypy 和静态类型检查