I have noticed this in Python's threading module source:
def Event(*args, **kwargs):
return _Event(*args, **kwargs)
class _Event(_Verbose):
...
Am I correct in assuming this is an attempt in mimicking a "sealed" class (c#) or开发者_Python百科 a "final" class (java) in other languages? Is this a common pattern in Python? Are there any other approaches to this problem in Python?
I don't think I like this choice of identifiers. It is conventional to start class names with an uppercase letter, so you'd think that you could say isinstance(x, Event)
, but you can't. I think a name such as make_event
that unambiguously identifies the function as a function would have been better.
This issue has already been discussed on the mailing list, where the BDFL states:
This started out as an experiment in API design, where I tried to make things look as much like the similar Java API as possible (I didn't want to invent yet anotherwobbly wheel). I specifically wanted these not to be classes so that people wouldn't start subclassing them. At the time PEP-8 wasn't well established (if at all) and I wanted the factory functions to look like classes. I think in 2.7 / 3.1 we can change the factory functions to conform to PEP-8 (leaving the old names in for a couple of release).
The change he mentioned hasn't been done yet, but I think it's pretty safe to say that nowadays the naming scheme is seen as misguided and should not be proliferated.
You're right when you say that these factory functions were introduced to mimic a sealed class. The BDFL says
Allowing them to be subclassed makes it harder to replace them on some platforms with equivalent but faster implementations.
I don't think this scheme is too common. Most of the time, there is no incentive to replace classes with equivalent implementations, and if a class is not designed for subclassing, you can mention that in the documentation.
That would seem to be the idea, but obviously it's still perfectly possible to inherit from the classes if you want (even if they were in a separate module, you can do type(Event())
to get a reference. It presumably is just intended to make people think before subclassing them.
It's not a common pattern in Python. There are very few things that we specifically discourage inheriting from.
精彩评论