gpt4 book ai didi

python-3.x - 防止抽象类的实例化

转载 作者:行者123 更新时间:2023-12-02 03:03:30 25 4
gpt4 key购买 nike

在 Java 中,我们可以通过将类设为抽象类来阻止类的实例化。我认为 python 的行为方式相同。但是令我惊讶的是,我发现我可以创建一个抽象类的对象:

from abc import ABCMeta
class Foo(metaclass=ABCMeta):
pass
Foo()

为什么 python 允许这样做,我该如何防止呢?

最佳答案

Python 适用于“同意的成年人”——如果需要,您可以通过项目中的命名约定(或模块成员身份)将类标记为抽象类。然而,做一个硬性的“无法实例化”的抽象类是可行的 - 但正如问题的评论者所建议的那样,这不会增加项目本身的安全性或良好实践。

因此,要为 ABC 的抽象类保留剩余的机制,您可以继承 ABCMeta 类,并使用它来装饰 __new__ 方法,这样它就不会实例化 - 否则,只需执行相同的操作,而是从 type 继承。

换句话说,下面的代码将 __new__ 方法包装在使用它作为元类创建的类上。当该方法运行时,它会检查它正在实例化的类是否是用 ABC 元本身标记的类,如果是,它会引发类型错误。

    class ReallyAbstract(ABCMeta):
def __new__(metacls, name, bases, namespace):
outter_cls = super().__new__(metacls, name, bases, namespace)
for bases in outter_cls.__mro__:
if getattr(getattr(bases, "__new__", None), "_abstract", False):
# Base class already marked as abstract. No need to do anything else
return outter_cls
original_new = getattr(outter_cls, "__new__")
if getattr(original_new, "_abstract", False):
# If we get a method that has already been wrapped
# just return it unchanged.
# TODO: if further classes on the hierarhy redfine __new__
return outter_cls

def __new__(cls, *args, **kw):
if cls is outter_cls:
raise TypeError
return original_new(cls, *args, **kw)
__new__._abstract = True
outter_cls.__new__ = __new__
return outter_cls

在控制台上:

    In [7]: class A(metaclass=ReallyAbstract):
...: pass
...:

In [7]: A()
TypeError Traceback (most recent call last)
<ipython-input-7-...> in <module>()
----> 1 A()

....

只是为了完整起见 - 如果 ABCMeta 在 Python 中包含至少一个“抽象方法”,则它们不可实例化。就像其他 O.O.在更多静态语言中强制执行的功能,我们的想法是按照惯例拥有它。但是,是的,我同意,既然他们开始着手创建一个 AbstractClass 机制,它的行为应该不会那么令人惊讶,这意味着默认情况下不应该实例化。

关于python-3.x - 防止抽象类的实例化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44256700/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com