Python规范:私有类的函数构造器

9
我注意到这个问题出现在Python的线程模块源代码中:
def Event(*args, **kwargs):
  return _Event(*args, **kwargs)

class _Event(_Verbose):
  ...

我猜想这是在模仿"c#"中的"sealed"类或者"java"中的"final"类,这种方式在Python中常见吗?还有其他解决这个问题的方法吗?

2个回答

5
我不认为我喜欢这些标识符的选择。按照惯例,类名应以大写字母开头,因此您可能会认为可以说isinstance(x, Event),但实际上不行。我认为一个名称,例如make_event,可以明确地将函数标识为函数,这将更好。
这个问题已经在邮件列表上讨论过,在那里BDFL说明
这开始是API设计的实验,我试图使事情看起来尽可能像类似的Java API(我不想再发明一个不稳定的轮子)。我特别希望这些函数是类,以便人们不会开始对其进行子类化。当时PEP-8还没有很好地确立(如果有的话),我希望工厂函数看起来像类。我认为在2.7 / 3.1中,我们可以更改工厂函数以符合PEP-8(保留旧名称几个版本)。

他提到的更改尚未完成,但我认为可以相当肯定地说,现在命名方案被视为误导性的,不应该进一步扩散。

你说这些工厂函数引入是为了模仿一个密封的类,这是正确的。BDFLsays

允许它们被子类化会使在某些平台上用等效但更快的实现替换它们变得更加困难。

我不认为这种方案太常见。大多数情况下,没有动机用等效实现替换类,并且如果一个类不是为了子类化而设计的,你可以在文档中提到。

谢谢,这正是我所寻找的。在提问之前,我应该更努力地搜索一下。 - user584847

1

这似乎是这个想法,但显然仍然可以从类继承(即使它们在不同的模块中,您仍然可以使用type(Event())来获取引用)。它可能只是旨在让人们在子类化之前思考。

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


2
我注意到在Python中实际上几乎不可能真正地使访问特定对象变得不可能。如果一个对象引用另一个对象,你可以跟随一些访问路径来到达该引用。 - Omnifarious
通常建议只有在类被设计为可被子类化时才应该显式地进行子类化,因为创建一个容器,在其中子类化可能是可能的(但并非旨在如此)通常更为合适。由于在提到的语言中,这可以通过单个关键字来实现,因此似乎更经常遵循这种模式。然而,在Python中没有这样的等效物,像这样的技巧是最接近的。我想知道是否适合复制这种约定,如果可能还有其他明确说明以下内容的方法。 - user584847
2
PEP 8说:“Python库的命名约定有点混乱”,“函数名应该是小写的”。由于Event无疑是一个函数,它的名称违反了样式指南。这并不是很严重的问题(文档清楚地说明了它是一个函数),但我认为你不应该复制这种命名方案。另请参见http://mail.python.org/pipermail/python-dev/2008-September/082117.html。 - Philipp
@mosmbelly:Python 的惯例是不阻止子类化。毕竟,也许将来有人会有一个扩展您的类的绝妙想法。如果有很好的理由不建议对其进行子类化,请在文档中提到。 - Thomas K
一般来说是正确的,但在这种情况下,该模块是由GvR设计的,不允许子类化,请参见我回答中的引用。 - Philipp

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接