怎么创建一个类,做到不能创建这个类自身的实例,但可以创建这个子类的实例?

2021 年 11 月 7 日
 MiketsuSmasher
4492 次点击
所在节点    Python
23 条回复
golangLover
2021 年 11 月 7 日
声明为抽象类
golangLover
2021 年 11 月 7 日
看错了,以为是 java 区的。 无视我吧。
KevinBlandy
2021 年 11 月 7 日
在构造函数中,通过 this 获取到 class 判断。
MiketsuSmasher
2021 年 11 月 7 日
各位,忘了声明,这个问题是关于 Python 的
oOoOoOoOoOo
2021 年 11 月 7 日
@KevinBlandy um, python
deplivesb
2021 年 11 月 7 日
HelloAmadeus
2021 年 11 月 7 日
继承自定义 type 类,type 类在构造的时候判断类名
chroming
2021 年 11 月 7 日
可以在__init__里用 self.__class__判断当前类

```python
class A(object):
def __init__(self):
if self.__class__ == A:
raise
```
learningman
2021 年 11 月 7 日
这个类所有的成员里面都放个报错
rabenda
2021 年 11 月 7 日
ClericPy
2021 年 11 月 7 日
一楼没说错, 面向对象基本都有抽象类. 把抽象方法啥的都 raise 一个 NotImplementedError 就行了, 随便一搜一大把 demo
Kilerd
2021 年 11 月 7 日
import abc

这都没有人用过吗?
ArchieMeng
2021 年 11 月 8 日
还真没用过,因为没这需求
oOoOoOoOoOo
2021 年 11 月 8 日
```python
class Finch:
____...
```
WilliamYang
2021 年 11 月 8 日
用一些新出的内置魔法方法或者元类,应该可以的
Kobayashi
2021 年 11 月 8 日
这就是 Tornado 的 Configurable 做的事。IOLoop 实例化默认实例化其子类 EPollIOLoop ,KQueueIOLoop 或者 SelectIOLoop 。通过 Configurable.__new__ 里做的修改。
它做的过为复杂,当时应该是在自己实现一套接口(同类型的还有 abc, zope.interface 。

针对你的问题,自己实现简化一下只创建基类、子类,在基类 __new__ 中实现返回子类即可。
GeruzoniAnsasu
2021 年 11 月 8 日
什么抽象类 拿锤子看钉子属于是

python 的 oo 跟 C 系列很不一样,你想达到的类似效果应该用 metaclass 实现
MegrezZhu
2021 年 11 月 8 日
hulala1021
2021 年 11 月 8 日
12 楼、18 楼说的对
2i2Re2PLMaDnghL
2021 年 11 月 8 日
最简单的只要在 __new__ 里面判断一下 if cls == MyClass: raise 就行了

#17 猜测 X-Y 问题不无道理,这种操作通常有一些更 Pythonic 的形式。
1. 比如你把这个类取名以下划线开头 _MyClass
2. 鉴于鸭子类型,可能你更应该声明一个 typing.Protocol (类似 golang 的 interface ,按照隐式的实质结构而不是显式的声明继承来判断其所属类)
3. 如果你要做一些通用的高等方法调用依赖于实现的初等方法,那么 abc 确实是比较稳定的,把初等方法搞成 abstractmethod
4. 但其实 abc 是 mixin 的一种特殊形式,还会破坏 metaclass 魔法,你先得确认自己需要的不是更通用的 mixin 。mixin 也是 composition over inheritance 的。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/813708

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX