Python - staticmethod vs classmethod

时间:2017-09-28 14:05:26

标签: python

我有一个类,它返回机器的运行状况统计信息。

class HealthMonitor(object):
    """Various HealthMonitor methods."""

    @classmethod
    def get_uptime(cls):
        """Get the uptime of the system."""
        return uptime()

    @classmethod
    def detect_platform(cls):
        """Platform detection."""
        return platform.system()

    @classmethod
    def get_cpu_usage(cls):
        """Return CPU percentage of each core."""
        return psutil.cpu_percent(interval=1, percpu=True)

    @classmethod
    def get_memory_usage(cls):
        """Return current memory usage of a machine."""
        memory = psutil.virtual_memory()
        return {
            'used': memory.used,
            'total': memory.total,
            'available': memory.available,
            'free': memory.free,
            'percentage': memory.percentage
        }

    @classmethod
    def get_stats(cls):
        return {
            'memory_usage': cls.get_memory_usage(),
            'uptime': cls.uptime(),
            'cpu_usage': cls.get_cpu_usage(),
            'security_logs': cls.get_windows_security_logs()
        }

方法get_stats将从课外调用。这是定义相关功能的正确方法。使用classmethodsstaticmethods或制作班级的对象,然后调用get_stats

我已经阅读了足够的差异,但仍希望通过一个例子来清楚我的理解。哪个是pythonic方法呢?

2 个答案:

答案 0 :(得分:5)

当方法需要类信息时使用@classmethod,即访问类属性。 (假设 health_monitor 类具有 OS 属性,这将影响您执行的命令)

当方法不需要声明它的类的任何数据时,使用@staticmethod;像你所有的功能一样。

我经常发现自己使用staticmethod来放置一个类以简化的函数,因为它们在我的类中运行在上下文中,但不是中继在它上面。

至于:当您的所有方法都是classmethodsstaticmethods时,您应该考虑将代码驻留在模块范围内,不是一个班级。为什么?好吧,如果他们不在他们之间共享任何数据,没有理由将他们分组。这会更简单:

# health_monitor.py
def get_uptime(cls):
    """Get the uptime of the system."""
    return uptime()

# main.py
health_monitor.get_uptime()

答案 1 :(得分:3)

嗯,classes基本上提供了对数据的封装,即对标识该对象的某些数据的一组行为。现在,您定义的方法都没有与该类有任何关系。

因此,只要您不需要在这些方法之间共享数据,使用classmethods就没有意义了。虽然你最好不要使用static methods,但他们所做的只是提供命名空间。如何将所有方法定义为名为health_monitor.py的文件中的简单函数,然后按如下方式使用它 -

import health_monitor

uptime = health_monitor.get_uptime()

这种方法的唯一之处在于您必须通过模块名称强制执行此导入约定而不是函数。