On 1/5/21 10:25 AM, Guido van Rossum wrote:
> On Tue, Jan 5, 2021 at 8:50 AM Ethan Furman wrote:
>> [...]
>> Perhaps `ABCMeta` can be easily fixed -- it is calling the function that
>> records all abstract methods, etc., after the `type.__new__` call; can
>> it be called before?
>
> Why do you keep insisting that this is "broken"?
Because `__init_subclass__` is getting a new class object that is not ready to
be gotten.
> Yes, you have identified a way that an abstract class can be instantiated
> *by its own constructor* despite being abstract.
It doesn't feel that way to me. Referring to the code below [1], the constructor for `MyPlugin` is `abc.ABCMeta`, but
`PluginBase.__init_subclass__` is getting `MyPlugin` before `abc.ABCMeta` has finished doing its job.
> I think that's not something to get worked up about. As the doctor in the
> old joke said, "then don't do that." Or perhaps this is one of those
> situations where we're all still considered to be consenting adults --
> surely abstract classes and methods are meant as a way to help users do
> the right thing, not as an absolute guarantee.
According to the documentation:
> This module provides abstract base classes that can be used to test whether
> a class provides a particular interface; for example, whether it is hashable
> or whether it is a mapping.
Do we need to add a warning to that?
> except inside `__init_subclass__` as the class has not been fully initialized.
For that matter, if we are not going to address this issue with code, we should definitely update the
`__init_subclass__` and `__set_name__` documentation:
> Note: custom metaclasses must have all changes needed already in the class
> namespace before calling `type.__new__`, as `type.__new__` will invoke
> `__init_subclass__` and `__set_name__` before returning. Any modifications
> made to the class after that point will not be available to those two methods.
>
> Note: because of the above, any `__init_subclass__` used with `Enum` classes
will
> not see any members as members are added after the call to `type.__new__`.
>
> Note: because of the above, any `__init_subclass__` used with `ABC` classes
will
> have to determine for itself if the class is abstract or concrete as that is
> determined after the call to `type.__new__`.
As I said before, perhaps `_abc_init` can be called before `type.__new__`,
which would make that last note unnecessary.
That would not solve the problem for `Enum`, though, nor for any other metaclass that cannot complete its customization
before calling `type.__new__`.
--
~Ethan~
[1]
class PluginBase(abc.ABC):
# base class for plugins
# must override `do_something`
def __init_subclass__(cls, **kwargs):
instance = cls()
print(f"Created instance of {cls} easily: {instance}")
@abc.abstractmethod
def do_something(self):
pass
class MyPlugin(PluginBase):
pass
[2] https://docs.python.org/3/library/collections.abc.html
_______________________________________________
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-le...@python.org
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at
https://mail.python.org/archives/list/python-dev@python.org/message/KE3ZJEDFMZT4TXTTHXMVGEZSLX2HDUSZ/
Code of Conduct: http://python.org/psf/codeofconduct/