关于设计模式:python-我应该使用静态方法还是顶级函数

python - should I use static methods or top-level functions

我来自Java背景,我是Python的新手。我有几个脚本共享一些与读写文件相关的应用程序特有的助手函数。一些与阅读相关的功能,一些与写作相关。在寻找正确的方法时,我看到了:Python中的静态方法?

他在回答中提到:

Finally, use staticmethod sparingly! There are very few situations where static-methods are necessary in Python, and I've seen them used many times where a separate"top-level" function would have been clearer.

我不太了解顶级函数,我也不确定给出的这个简单示例哪个更好:1)为具有静态读卡器函数的读卡器创建一个类,为编写器创建一个类,或者2)将这些帮助器声明为全局函数,为什么?

编辑:关于这个主题的非常好的文章,我刚刚找到了http://tomayko.com/writing/the-static-method-thing


在爪哇,到处使用类(甚至是错误的)想法,甚至只是将不共享任何状态的静态函数分组在一起(因此此类类永远不会被实例化)。

Python在这里会有所不同;如果你有一些没有共享状态的函数(因此在Java中通常是EDCOX1,0个函数),并且与一个"真实"类(实际上是实例化的一个)并不紧密相关,那么你只需要使用一个模块内的自由函数。

这背后的原因是,只有当您真正想实例化一个类时,才需要它,因此将一个类作为几个不需要共享实例特定状态的函数的容器是没有用的。

实际上,您可以将一个模块想象成一个static类,即一个包含函数(=static方法)、模块变量(=static字段)和类型的容器。

在python中,好的一点是,拥有顶级函数不会带来全局名称空间污染问题,因为在python的顶级函数/对象中。仍在模块范围内。因此,您仍然可以按模块对功能进行分组,而不需要不必要的class税。

  • 实际上,它们可以有一些共享状态,以模块级变量的形式出现(所以,单例);同样,类比模块的静态类似乎可以容纳。

  • 来自Python禅(import this):

    1
    Namespaces are one honking great idea -- let's do more of those!

    在Java这样的语言中创建静态方法的主要原因之一是确保这些方法不会污染全局命名空间。(尽管Java完全禁止自己的命名空间约定,但完全禁止"包级"功能!)在python中,所有"顶级"函数都自动放置在包含这些函数的模块的名称空间中,因此不存在以这种方式污染全局名称空间的危险。

    换句话说,和许多其他语言一样,Python可以用几种不同的方式创建名称空间。在这种情况下,当一个模块提供相同的名称空间目的,而没有与定义一个类相关的混乱(或认知负载)时,几乎不需要创建只包含静态方法的类。


    这是一个名称空间污染的问题。如果您有一个具有多个类的模块和一些只对某个类及其子类有意义的函数,那么将其设置为静态方法。静态方法可以通过使用类名或使用类的对象来调用。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    >>> class A(object):
    ...     @staticmethod
    ...     def static_1():
    ...             print 'i am static'
    ...     def a(self):
    ...             self.static_1()
    ...
    >>> A.static_1()
    i am static
    >>> a=A()
    >>> a.a()
    i am static
    >>> a.static_1()
    i am static
    >>> class B(A):
    ...     pass
    ...
    >>> b=B()
    >>> b.static_1()
    i am static
    >>>


    如果函数与类相关,则将其设置为静态方法。例如:

    1
    2
    3
    4
    5
    6
    7
    8
    class DBobject():
        name = StringProperty()

        @staticmethod
        def get_by_name(name):
            return db.select('select * from DBobject where name ="%s"' % name)

    python = DBobject.get_by_name('python')

    也就是说,该方法完全与DBObject类相关,因此它应该是一个静态方法。


    python静态方法的另一个方面是,当调用实例时,尽管没有self的实例,但它们在所调用的变量类型上是多态的。

    例如:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    class BaseClass:
        @staticmethod
        def my_method():
            return 0


    class SubclassLeft:
        @staticmethod
        def my_method():
            return"left"


    class SubclassRight:
        @staticmethod
        def my_method():
            return"right"


    instances = [BaseClass(), SubclassLeft(), SubclassRight()]

    for i in instances:
        print(i.my_method())

    运行此结果

    1
    2
    3
    4
    $ python example.py
    0
    left
    right