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

2021-11-07 22:07:50 +08:00
 MiketsuSmasher
3791 次点击
所在节点    Python
23 条回复
golangLover
2021-11-07 22:12:37 +08:00
声明为抽象类
golangLover
2021-11-07 22:13:04 +08:00
看错了,以为是 java 区的。 无视我吧。
KevinBlandy
2021-11-07 22:16:35 +08:00
在构造函数中,通过 this 获取到 class 判断。
MiketsuSmasher
2021-11-07 22:19:40 +08:00
各位,忘了声明,这个问题是关于 Python 的
oOoOoOoOoOo
2021-11-07 22:22:47 +08:00
@KevinBlandy um, python
deplivesb
2021-11-07 22:24:44 +08:00
HelloAmadeus
2021-11-07 22:57:37 +08:00
继承自定义 type 类,type 类在构造的时候判断类名
chroming
2021-11-07 22:58:18 +08:00
可以在__init__里用 self.__class__判断当前类

```python
class A(object):
def __init__(self):
if self.__class__ == A:
raise
```
learningman
2021-11-07 23:33:22 +08:00
这个类所有的成员里面都放个报错
rabenda
2021-11-07 23:36:27 +08:00
ClericPy
2021-11-07 23:46:44 +08:00
一楼没说错, 面向对象基本都有抽象类. 把抽象方法啥的都 raise 一个 NotImplementedError 就行了, 随便一搜一大把 demo
Kilerd
2021-11-07 23:57:55 +08:00
import abc

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

针对你的问题,自己实现简化一下只创建基类、子类,在基类 __new__ 中实现返回子类即可。
GeruzoniAnsasu
2021-11-08 04:46:07 +08:00
什么抽象类 拿锤子看钉子属于是

python 的 oo 跟 C 系列很不一样,你想达到的类似效果应该用 metaclass 实现
MegrezZhu
2021-11-08 05:01:15 +08:00
hulala1021
2021-11-08 09:18:08 +08:00
12 楼、18 楼说的对
2i2Re2PLMaDnghL
2021-11-08 10:03:04 +08:00
最简单的只要在 __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