如何创建一个不可实例化的类?

Ble*_*ers 4 python instantiation objectinstantiation

对于我目前正在工作的项目之一,我正在考虑创建一个无法由客户端实例化的类,并且只通过特定接口提供实例,即客户端无法通过某些实现创建更多实例hackery如:

>>> try:
...     raise WindowsError
... except:
...     foo = sys.exc_info()
... 
>>> foo
(<type 'exceptions.WindowsError'>, WindowsError(), <traceback object at 0x0000000005503A48>)
>>> type(foo[2])()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: cannot create 'traceback' instances
Run Code Online (Sandbox Code Playgroud)

一旦他有一个.

我成功地创建了一个无法实例化的类.即

>>> class Foo():
...     def __init__(self):
...         raise TypeError("cannot create 'Foo' instances")
... 
>>> bar = Foo()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 3, in __init__
TypeError: cannot create 'Foo' instances
>>> bar
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'bar' is not defined
Run Code Online (Sandbox Code Playgroud)

但是,如何使用每个相同的定义来创建类的实例?

当然我可以这样做:

>>> class Foo():
...     def __init__(self, instantiate = False):
...         if not instantiate:
...               raise TypeError("cannot create 'Foo' instances")
Run Code Online (Sandbox Code Playgroud)

但我发现它不够优雅,也不能完全阻止客户进一步实例化它.并且我不会为它构建C++模块.

关于如何实现这样的事情的任何建议?import abc

回答Martijn的问题和完整性的简短理由:

实际上,你可以考虑特定的和相关的类的实例,作为树中的节点,父和子都保持连接,依赖和认知彼此,并且在任何一个中都有一个唯一的根python的一个例子(由使用保险package).特定节点中的任何状态更改都会导致其他人自行更新它们所连接的数据库.除此之外,我很想知道这样的事情是如何实现的(traceback课程在戏弄我).

Ska*_*One 11

你正在做的是一个坏主意,你不应该这样做.我确信还有其他更好的解决方案.如果您确实决定采用自己的方式(不应该),那么您可以在不使用的情况下创建对象__init__():


python中的对象是使用该__new__()方法创建的.该方法__init__()仅编辑由其创建的对象__new__().例如,__init__()通常初始化对象的一些属性.

当宣布x = Foo()发生的事情时,这是:

  1. x = object.__new__(Foo) 首先调用并创建对象.
  2. Foo.__init__(x) 被称为秒,它只是将一些属性等初始化为已存在的对象.

这意味着您不需要打电话Foo()(因此也可以打电话__init__()).相反,你可以直接打电话__new__():

class Foo(object):
    def __init__(self):
        raise TypeError("Cannot create 'Foo' instances.")

>>> x = object.__new__(Foo)
>>> x
<__main__.Foo object at 0x02B074F0>
Run Code Online (Sandbox Code Playgroud)

我们x现在是一个实例Foo,没有任何属性,它可以使用Foo类中定义的任何方法.

如果需要,您可以创建自己的替换函数__init__来初始化属性:

def init_foo(foo, name):
    foo.name = name

>>> init_foo(x, "Mike")
>>> x.name
'Mike'
Run Code Online (Sandbox Code Playgroud)

这当然也可以Foo是实例方法:

class Foo(object):
    def __init__(self):
        raise TypeError("Cannot create 'Foo' instances.")

    def init(self, name):
        self.name = name

>>> x = object.__new__(Foo)
>>> x.init("Mike")
>>> x.name
'Mike'
Run Code Online (Sandbox Code Playgroud)

更进一步,您甚至可以使用a classmethod来创建只有一个调用的对象:

class Foo(object):
    def __init__(self):
        raise TypeError("Cannot create 'Foo' instances.")

    @classmethod
    def new(cls, name):
        obj = object.__new__(cls)
        obj.name = name
        return obj

>>> x = Foo.new("Mike")
>>> x.name
'Mike'
Run Code Online (Sandbox Code Playgroud)

  • 你能解释一下_为什么_@BleedingFingers 正在做的事情是个坏主意吗?我相信你是对的,但除非你用事实来支持你的陈述,否则它似乎更像是一种意见,而且由于我们不明白为什么它不好,我们不太可能注意你的警告。 (3认同)