我是一名 Java 开发人员,时常使用 Python。我最近偶然发现本文 http://dirtsimple.org/2004/12/python-is-not-java.html其中提到了 Java 程序员在学习 Python 时常犯的错误。第一个引起了我的注意:
Java 中的静态方法不会转换为 Python 类方法。哦,当然,它会产生或多或少相同的效果,但类方法的目标实际上是做一些在 Java 中通常不可能实现的事情(比如继承非默认构造函数)。 Java 静态方法的惯用翻译通常是模块级函数,而不是类方法或静态方法。 (静态最终字段应转换为模块级常量。)
这并不是什么太大的性能问题,但是必须使用像这样的 Java 习惯代码的 Python 程序员会因为键入 Foo.Foo.someMethod 而感到相当恼火,而实际上它应该是 Foo.someFunction。但请注意,调用类方法涉及额外的内存分配,而调用静态方法或函数则不会。
哦,所有这些 Foo.Bar.Baz 属性链也不是免费的。在 Java 中,这些点名称由编译器查找,因此在运行时,有多少个点名称并不重要。在 Python 中,查找发生在运行时,因此每个点都很重要。 (请记住,在 Python 中,“扁平优于嵌套”,尽管它更多地与“可读性重要”和“简单优于复杂”相关,而不是与性能相关。)
我发现这有点奇怪,因为文档静态法 http://docs.python.org/py3k/library/functions.html#staticmethod says:
Python 中的静态方法与 Java 或 C++ 中的静态方法类似。另请参阅 classmethod() 了解可用于创建备用类构造函数的变体。
更令人费解的是这段代码:
class A:
def foo(x):
print(x)
A.foo(5)
在 Python 2.7.3 中按预期失败,但在 3.2.3 中工作正常(尽管您不能在 A 的实例上调用该方法,只能在类上调用。)
因此,有三种方法可以实现静态方法(如果使用类方法算的话有四种),每种方法都有细微的差别,其中一种似乎没有文档记录。这似乎与 Python 的口头禅“应该有一种——最好只有一种——明显的方法来做到这一点”相矛盾。哪种习惯用法最符合 Python 风格?各自的优点和缺点是什么?
到目前为止我的理解是:
模块功能:
- 避免 Foo.Foo.f() 问题
- 比其他替代方案更污染模块的命名空间
- 无继承权
静态方法:
- 将与类相关的函数保留在类内部并保留在模块命名空间之外。
- 允许在类的实例上调用该函数。
- 子类可以重写该方法。
类方法:
- 与 staticmethod 相同,但也将类作为第一个参数传递。
常规方法(仅限 Python 3):
- 与 staticmethod 相同,但不能在类的实例上调用该方法。
我是不是想太多了?这不是问题吗?请帮忙!
最直接的思考方法是考虑该方法需要什么类型的对象才能完成其工作。如果您的方法需要访问实例,请将其设为常规方法。如果它需要访问该类,请将其设为类方法。如果不需要访问类或实例,请将其设为函数。很少需要将某些东西设为静态方法,但是如果您发现您希望将一个函数与一个类“分组”(例如,这样它就可以被覆盖),即使它不需要访问该类,我想你可以将其设为静态方法。
我想补充一点,将函数放在模块级别不会“污染”名称空间。如果这些函数是要使用的,它们就不会污染命名空间,它们只是按照应该使用的方式使用它。函数是模块中的合法对象,就像类或其他任何东西一样。如果函数没有任何理由存在,就没有理由在类中隐藏该函数。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)