python - 我应该使用静态方法还是顶级函数

Bra*_*rad 39 python static design-patterns

我来自Java背景,我是python的新手.我有几个脚本共享一些与读取和写入文件相关的应用程序独有的辅助函数.一些与阅读相关的功能,一些与写作相关.在搜索正确的方法时,我看到了这一点:Python中的静态方法?

他在回答中提到:

最后,谨慎使用static方法!在Python中很少需要使用静态方法,并且我已经看到它们多次使用,其中单独的"顶级"函数会更清晰.

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

编辑:关于这个主题的真正好文章我刚刚找到http://tomayko.com/writings/the-static-method-thing

Mat*_*lia 46

在Java中,(IMHO错误的)想法是在任何地方使用类,甚至只是将不共享任何状态的静态函数组合在一起(因此这些类永远不会被实例化).

Python在这里要求不同; 如果你有没有某些共享状态1的函数(因此在Java中通常是static函数)并且与"真正的"类(=实际实例化的类)没有紧密相关,你只需要在一个内部使用自由函数模块.

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

其实,你可以有点觉得模块作为的static类-即功能(=静态方法),模块变量(=静态字段)和类型的容器.

Python中的好处是拥有顶级函数不会产生全局命名空间污染问题,因为在Python中,顶层函数/ objects/...仍然是模块范围的.因此,您仍然可以按模块对函数进行分组,而不必使用不必要的class-tax.


  1. 实际上,它们可以以模块级变量的形式存在一些共享状态(因此,单例); 再次,类比模块 - 静态类似乎成立.

  • @Brad:恩,我应该说明什么?你只是不写一个类,并将自由函数定义(`def foo():...`)放在文件中... (2认同)

lmj*_*ns3 13

来自Python的Zen(import this):

Namespaces are one honking great idea -- let's do more of those!
Run Code Online (Sandbox Code Playgroud)

在像Java这样的语言中创建静态方法的主要原因之一是确保这些方法不会污染全局命名空间.(尽管Java通过完全禁止"包级"函数来强制执行其自己的命名空间约定!)在Python中,所有"顶级"函数都自动放置在包含这些函数的模块的命名空间内,因此不存在污染全局的危险命名空间这样.

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


Bre*_*rne 5

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

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')
Run Code Online (Sandbox Code Playgroud)

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


tde*_*ney 5

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

>>> 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
>>>
Run Code Online (Sandbox Code Playgroud)