V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
MiketsuSmasher
V2EX  ›  Python

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

  •  
  •   MiketsuSmasher · 2021-11-07 22:07:50 +08:00 · 3774 次点击
    这是一个创建于 1116 天前的主题,其中的信息可能已经有所发展或是发生改变。
    23 条回复    2021-11-21 18:34:27 +08:00
    golangLover
        1
    golangLover  
       2021-11-07 22:12:37 +08:00
    声明为抽象类
    golangLover
        2
    golangLover  
       2021-11-07 22:13:04 +08:00
    看错了,以为是 java 区的。 无视我吧。
    KevinBlandy
        3
    KevinBlandy  
       2021-11-07 22:16:35 +08:00
    在构造函数中,通过 this 获取到 class 判断。
    MiketsuSmasher
        4
    MiketsuSmasher  
    OP
       2021-11-07 22:19:40 +08:00
    各位,忘了声明,这个问题是关于 Python 的
    oOoOoOoOoOo
        5
    oOoOoOoOoOo  
       2021-11-07 22:22:47 +08:00 via Android
    @KevinBlandy um, python
    deplivesb
        6
    deplivesb  
       2021-11-07 22:24:44 +08:00   ❤️ 1
    HelloAmadeus
        7
    HelloAmadeus  
       2021-11-07 22:57:37 +08:00 via iPhone
    继承自定义 type 类,type 类在构造的时候判断类名
    chroming
        8
    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
        9
    learningman  
       2021-11-07 23:33:22 +08:00
    这个类所有的成员里面都放个报错
    rabenda
        10
    rabenda  
       2021-11-07 23:36:27 +08:00   ❤️ 1
    ClericPy
        11
    ClericPy  
       2021-11-07 23:46:44 +08:00
    一楼没说错, 面向对象基本都有抽象类. 把抽象方法啥的都 raise 一个 NotImplementedError 就行了, 随便一搜一大把 demo
    Kilerd
        12
    Kilerd  
       2021-11-07 23:57:55 +08:00
    import abc

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

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

    python 的 oo 跟 C 系列很不一样,你想达到的类似效果应该用 metaclass 实现
    MegrezZhu
        18
    MegrezZhu  
       2021-11-08 05:01:15 +08:00
    hulala1021
        19
    hulala1021  
       2021-11-08 09:18:08 +08:00
    12 楼、18 楼说的对
    2i2Re2PLMaDnghL
        20
    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 的。
    O5oz6z3
        21
    O5oz6z3  
       2021-11-08 14:13:42 +08:00
    #8 楼最简单,硬编码类检查。抽象类需要子类覆盖抽象方法。元类我想不到怎么做,所以我猜用类装饰器给类的__init__包一层检查函数就能简单实现。
    raysonlu
        22
    raysonlu  
       2021-11-08 14:31:20 +08:00
    我理解的提议是:不能 new 定义的父类,只能 new 其子类。那就在父类的构造函数直接抛错?(子类不调用父类构造函数)
    shm7
        23
    shm7  
       2021-11-21 18:34:27 +08:00
    的确常用 ABC ,不过实用没啥纠结。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5415 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 29ms · UTC 01:21 · PVG 09:21 · LAX 17:21 · JFK 20:21
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.