Hi all, this is a general feeler for if this idea has any traction:
All too often I see the following pattern in asyncio 3rd-party libs, either
in their own source code or in the inusage:
inst = SomeClass()
What happens here is that, since coroutines cannot be used inside __init__
methods, the __init__ method only stores the parameters, and another,
asynchronous method actually initializes the object. This led many
3rd-party libs to use factory methods to create their class instances,
which is unideal for both users and developers. We see this pattern in
nearly any async 3rd-party lib I came across.
To solve this, I propose a new metaclass: `AsyncType`. The core difference
between AsyncType and type is that when called, AsyncType will produce a
coroutine that asynchronously calls __new__ and __init__, and returns the
instance, allowing simply for `instance = await SomeClass()`. In classes of
`AsyncType`, the __new__ and __init__ methods must be async methods
As an additional syntactic sugar, we could also have an `async class(base)`
declaration that implicitly sets the class's metaclass to be AsyncType (or
raise a TypeError if that is impossible).
This proposal is obviously incomplete, and there are many open questions:
what about __del__? How would one easily make an async ABC (without a
metaclass conflict)? How would an async class easily inherit from a sync
class (suppose sync class A implements __new__, and async class B(A)
implements __init__)? Perhaps `AsyncType` should only make the __init__
method async and leave __new__ synchronous?
I'd just like to get ahead of the (not unjustified) argument that
constructors should be lightweight:
1. Python's __init__ is not strictly a constructor. It is, as the name
implies, an initializer, that makes the type usable. Constructing the type
without initializing it makes no sense and has no usages, so why seperate
2. We can see numerous examples of (syncronous) connect-on-initialize
classes in the standard library, including ftplib, smtplib, and pretty much
most *lib modules in the standard library "Internet Protocols and Support"
3. The "initialize in a separate method" pattern produces some
strange-looking code where the class holds on to its initialization params
even though it doesn't really need them after the separate methods. The
classes should now also consider and safe-guard against cases where the
separate method is called twice, or not at all.
What does the community think about this idea?