【问题标题】:Python convention: function constructor for a private classPython约定:私有类的函数构造函数
【发布时间】:2011-01-21 18:26:15
【问题描述】:

我在 Python 的线程模块源码中注意到了这一点:

def Event(*args, **kwargs):
  return _Event(*args, **kwargs)

class _Event(_Verbose):
  ...

假设这是在尝试模仿其他语言中的“密封”类 (c#) 或“最终”类 (java),我是否正确?这是 Python 中的常见模式吗?在 Python 中有没有其他方法可以解决这个问题?

【问题讨论】:

    标签: python design-patterns


    【解决方案1】:

    我认为我不喜欢这种标识符选择。按照惯例,类名以大写字母开头,因此您认为可以说 isinstance(x, Event),但实际上不能。我认为像make_event 这样明确地将函数标识为函数的名称会更好。

    这个问题已经在邮件列表中discussed,其中BDFL states

    这最初是作为 API 中的一个实验 设计,我试图让事物看起来很相似 尽可能使用 Java API(我不想再发明另一个摇摇晃晃的 车轮)。我特别希望这些不是成为类,以便人们 不会开始对它们进行子类化。当时 PEP-8 并不好 建立(如果有的话),我希望工厂功能看起来 喜欢上课。我认为在 2.7 / 3.1 我们可以更改工厂功能 符合 PEP-8(保留旧名称 释放)。

    他提到的改变还没有完成,但我认为现在可以肯定地说,现在的命名方案被认为是错误的,不应该扩散。

    当您说这些工厂函数被引入以模仿密封类时,您是对的。 BDFLsays

    允许它们被子类化使得在某些情况下替换它们变得更加困难 具有等效但更快实现的平台。

    我认为这种方案不太常见。大多数时候,没有动机用等效的实现替换类,如果一个类不是为子类设计的,您可以在文档中提及。

    【讨论】:

    • 谢谢,这正是我想要的。我应该在问之前更努力地搜索。
    【解决方案2】:

    这似乎是这个想法,但显然,如果你愿意,它仍然完全可以从类继承(即使它们在单独的模块中,你也可以通过 type(Event()) 获取参考。大概只是旨在让人们在子类化之前进行思考。

    这不是 Python 中的常见模式。我们特别不鼓励继承的东西很少。

    【讨论】:

    • 我注意到在 Python 中实际上不可能访问特定对象。如果一个对象引用了另一个对象,您可以遵循一些访问路径来获取该引用。
    • 通常建议子类化应该是明确的,只有当该类打算被子类化时,因为创建一个容器通常更合适,否则子类化是可能的(但不是有意的)。由于在上述语言中,这可以通过单个关键字来实现,因此似乎更经常遵循这种模式。然而在 Python 中没有这样的等价物,像这样的技巧是最接近的。我想知道这是否是适当的复制约定,是否有其他方式明确说明通过其他方式遵循。
    • PEP 8 说:“Python 库的命名约定有点乱”和“函数名应该小写”。由于Event 无疑是一个函数,它的名字打破了风格指南。它不是那么有害(文档清楚地表明它是一个函数),但我认为你不应该复制这个命名方案。另见mail.python.org/pipermail/python-dev/2008-September/082117.html
    • @mosmbelly:Python 中的约定是不阻止子类化。毕竟,也许将来有人会对如何扩展您的课程有一个绝妙的主意。如果有充分的理由说明子类化是一个坏主意,请在文档中提及。
    • 通常是这样,但在这种情况下,该模块是由 GvR 设计的,不允许子类,请参阅我的答案中的引号
    猜你喜欢
    • 1970-01-01
    • 2018-10-20
    • 2012-01-02
    • 2011-04-20
    • 2013-02-09
    • 2021-09-19
    • 2019-10-16
    相关资源
    最近更新 更多