python - 在 Python 中创建静态类

标签 python python-3.x pep8

我喜欢创建可以被其他类使用并且所有方法都是静态的 (staticmethod) 的辅助类。我需要用装饰器 @staticmethod 包装每个方法,但这个解决方案在我看来不太美观。我决定为这样的类创建一个元类——工具,这里是一个抽象的实现示例:

import types
import math


class StaticClass(type):
    def __new__(mcs, name, bases, attr):
        for name, value in attr.items():
            if type(value) is types.MethodType:
                attr[name] = staticmethod(value)
        return super().__new__(mcs, name, bases, attr)


class Tool(metaclass=StaticClass):

    def get_radius_from_area(area):
        return math.sqrt(area/Tool.get_pi())

    def get_pi():
        return math.pi


class CalcRadius:
    def __init__(self, area):
        self.__area = area

    def __call__(self):
        return Tool.get_radius_from_area(self.__area)


if __name__ == '__main__':
    get_it = CalcRadius(100)
    print(get_it())  # 5.641895835477563

一切正常并给出正确的结果,但 IDE 中的代码检查存在可理解和可预测的问题(我使用 Pycharm 2019.2)。

  • 对于 def get_radius_from_area(area): 通常是名为“self”的方法的第一个参数。 “区域”在方法的返回中以黄色突出显示。

  • 对于 get_pi(): 方法必须有第一个参数,通常称为“self” 没有参数的括号中的 Void 带有红色下划线。

如果我在类上方添加行“# noinspection PyMethodParameters”,这部分解决了问题,但它看起来比几十个@staticmethods 还要糟糕。

我理解为什么会这样,以及为什么 JetBrains 的开发人员专门为 Django 改编了他们 IDE 中的部分代码。

但是我能否以某种方式漂亮地创建一个纯静态类,其中所有方法都是静态的? 也许元类不是最佳选择,是否有某种替代解决方案?

最佳答案

您的元类实际上没有做任何事情,因为 types.MethodType 只匹配绑定(bind)的方法对象。当您浏览 __new__ 中的类命名空间时,您不会获得任何这些内容,因此您永远不会在 staticmethod 中包装任何内容。

您可以通过将检查更改为 types.FunctionType 来修复它(这可能会满足能够正确看到方法类型的自动化工具):

class StaticClass(type):
    def __new__(mcs, name, bases, attr):
        for name, value in attr.items():
            if type(value) is types.FunctionType:
                attr[name] = staticmethod(value)
        return super().__new__(mcs, name, bases, attr)

但我建议直接取消类并直接使用函数。函数是 Python 中的一流对象,您可以根据需要在对象之间传递它们。如果你想对它们进行方便的分组,你可以将它们放在列表或字典中,或者使用模块将它们的代码收集在各种分组中(并使用包来对模块进行分组)。我还建议您避免使用前导双下划线 __names 来尝试通过调用名称修改来保护您的属性。它实际上并没有保护您的数据不受任何影响(外部代码仍然可以获取它),并且它使调试变得更加困难。它包含在 Python 中是为了帮助您避免意外的名称冲突,而不是理所当然地保护成员变量。

关于python - 在 Python 中创建静态类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57931486/

相关文章:

python - RuntimeError:OrderedDict在迭代过程中发生了突变(Python3)

python - 我应该在 Python 中使用 "camel case"还是下划线?

python pep8缩进 Jenkins

python - 如何创建自定义 scrapy URL 过滤器以避免重复?

android - 最终用户是否需要安装 sl4a 才能使用 python-android 应用程序?

python - Tkinter 框架调整大小

python - PEP 8 中命名约定的首要原则是什么?

python - Pandas dropna() 不删除整行

python - 子类别 Django 商店

Python - 解析命令行输出 (Linux)