模块函数、静态方法、类方法、无装饰器:哪个习惯用法更Pythonic?

2024-03-13

我是一名 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(使用前将#替换为@)

模块函数、静态方法、类方法、无装饰器:哪个习惯用法更Pythonic? 的相关文章

随机推荐

  • 转换 LOG4J >> SLF4J + logback

    我目前的任务是将所有出现的 LOG4J 更改为 SLF4J 包括必要时的 logback 我已经设法将所有旧的 log4j xml 转换为 logback xml 并强制使用 logback 附加程序 但是 我刚刚发现代码中的一行还无法转换
  • 加载共享库 libresolv.so.2 时出错:没有这样的文件或目录(/lib/libclntsh.so 需要)

    每次我尝试连接到 Oracle DB 时都会收到此错误 DPI 1047 Cannot locate a 64 bit Oracle Client library Error loading shared library libnsl so
  • 关于代码密度作为编程语言能力衡量标准的文章[关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 我记得看过一篇文章说这样的话 不同的编程语言引入的错误数量差异不大 但很大程度上取决于 SLOC 源代
  • 如何防止 React-native-device-info 导致我的设置出现 React 歧义?

    我在安装时遇到问题react native device info进入现有的反应本机项目 使用创建create react native app然后弹出 I run yarn add react native device info yar
  • Visual Studio 2010 不断改变我的 winforms 控件

    我在 VS 2010 中的用户控件遇到了奇怪的情况 表单设计者不断更改我的条目 然后告诉我它不存在 它第一次编译并运行 然后如果我更改一些不相关的内容 它会在 Designer cs 文件中给出错误 无法解析符号 SomeEntry pri
  • Android 位图、回收和堆碎片

    我有一个应用程序大量使用从 SD 卡读取的位图 我 99 确信如果不回收这些 我的应用程序永远不会被破坏 它们都被分配到 LRU 缓存 公共集合 中 当它们从 LRU 缓存中清除时 该缓存会回收它们 并且我回收剩余的onDestroy 尽管
  • 脚本输出中日期更改的奇怪问题

    我的一位同事编写了一个 Google Apps 脚本来自动化工作流程 批准酒店的客房补偿请求 总的来说 该脚本似乎按预期运行 脚本中有一个按自动计划运行的函数 基于时间 而不是事件驱动 曾有过几次因入住日期晚了一位而导致预订错误的情况 不幸
  • 使用 Xceed PropertyGrid

    我是 C WPF 的初学者 正在尝试使用 Xceed PropertyGrid 他们在他们的网站上展示了一个示例
  • 删除 Woocommerce 中特定产品类别的添加购物车按钮

    我遇到如何从类别产品中删除购物车的问题 如果我将它应用于特定的 ID 或一般情况下的所有 ID 它就可以正常工作 但我无法对类别执行此操作 下面是我对此所做的代码 另外 我正在努力将相同的模式应用到相关文章部分 因此任何帮助将不胜感激 谢谢
  • 如何使用 opencv 和 Python 找到 ROI 内的轮廓?

    我试图找到图像特定区域的轮廓 是否可以只显示 ROI 内的轮廓 而不显示图像其余部分的轮廓 我在另一篇类似的文章中读到我应该使用面具 但我认为我使用得不正确 我对 openCV 和 Python 很陌生 所以非常感谢任何帮助 import
  • 检测网络下拉菜单是否将显示在屏幕外

    我有一个基于 CSS 的简单多级下拉菜单 第二或第三级可能会超出可见窗口 具有某些分辨率和窗口大小的组合 如果某些预构建的菜单控件检测到这种情况 它们只会向左而不是向右打开下拉菜单 我如何测试 使用 JS jQuery 这种情况 您可以使用
  • Playbook 位于子目录中,而不是紧邻 group_vars

    有谁知道如何将剧本放入文件夹中 但共享相同的角色 group vars 以及通常位于根目录的其他内容 这就是我想要的 root dir group vars roles inventory playbooks my playbook yml
  • 如何强制 Jackson 将字段值反序列化为小写

    我有一个公开 REST 端点的 spring 应用程序 让我们将其命名为 doAction 作为请求 它消耗对象 class Person private String name private String email 一些客户端可以通过
  • matplotlib 获取轴相对刻度位置

    我知道我可以通过以下方式获得 y 刻度的位置ax get yticks 顺便说一句 这是获得它们的最佳 正确方法吗 但我需要相对于轴限制的刻度位置 即在 0 和 1 之间 获得这个的最好方法是什么 我试过ax get yticks tran
  • 通过引用传递 int 与通过值传递 int 的好处?

    通过引用而不是值传递整数是否有性能优势 我这样说是因为如果您通过引用传递 您将创建一个 4 字节指针 但如果您通过值传递 您无论如何都会创建该值的 4 字节副本 那么它们都多占用了 4 个字节 对吗 是否可以使用强制转换通过引用传递 int
  • AttributeRouting - 从 RouteData 获取操作名称的正确方法

    我最近开始为我的操作方法使用属性路由 并且正在努力从 RouteData 获取操作名称 和 或 id 下面是我如何使用属性的示例 Route Edit id int public ActionResult Edit int id 之前我使用
  • ReSharper PdbNavigator 在符号服务器上找不到调试信息

    我们设置了 TeamCity 来为内部组件创建 NuGet 包和符号源包 符号源包正确包含 dll pdb 和源代码 一旦 TeamCity 创建了包 它们就会发布到我们的 NuGet SymbolSource 服务器 在 ReSharpe
  • 如何使用 POI SS 打开 .xlsx 文件?

    我正在尝试使用 POI SS 使用此代码打开 xlsx 文件 取自http poi apache org spreadsheet quick guide html ReadWriteWorkbook http poi apache org
  • 如何在Java中从sql模式生成orm映射类

    我有一个现有的 db sql 模式文件 是否可以在需要时生成并重新生成 DAO 实体以及访问它所需的所有其他帮助程序 客户端类 我不介意它会是什么 hibernate 其他 jpa 或其他东西 假设您 其他人仍在寻找解决方案 我刚刚遇到了同
  • 模块函数、静态方法、类方法、无装饰器:哪个习惯用法更Pythonic?

    我是一名 Java 开发人员 时常使用 Python 我最近偶然发现本文 http dirtsimple org 2004 12 python is not java html其中提到了 Java 程序员在学习 Python 时常犯的错误