对于我目前正在工作的项目之一,我正在考虑创建一个无法由客户端实例化的类,并且只通过特定接口提供实例,即客户端无法创建更多实例。它是由一些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
一旦有了。
我成功地创建了一个无法实例化的类。即。
>>> 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
但是我怎么能用这个相同的定义创建一个类的实例呢?
当然我可以这样做:
>>> class Foo():
... def __init__(self, instantiate = False):
... if not instantiate:
... raise TypeError("cannot create 'Foo' instances")
但我发现它不够优雅,也不能完全阻止客户端进一步实例化它。不,我不会为它构建一个C ++模块。
关于如何实现这样的事情的任何建议? import abc
?
回答Martijn的question以及完整性的简短理由:
实际上,您可以将有问题的特定类和相关类的实例视为树中的节点,并确保父级和子级保持连接,依赖于彼此并认识到并且具有唯一的唯一遍及任何python实例的root(由use package
保险)。特定节点中的任何状态更改都会导致其他人自行更新,并相应地更新它们所连接的数据库。除此之外,我很想知道如何安排这样的事情(traceback
课程在戏弄我)。
答案 0 :(得分:11)
你所做的是一个坏主意,你不应该这样做。
我确信还有其他更好的解决方案。
如果您确实决定采用自己的方式(不应该),那么您可以在不使用__init__()
的情况下创建对象:
python中的对象是使用__new__()
方法创建的。方法__init__()
仅编辑由__new__()
创建的对象。例如,__init__()
通常会初始化对象的某些属性。
当声明x = Foo()
之类的内容时,会发生什么:
x = object.__new__(Foo)
并创建对象。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>
我们的x
现在是Foo
的一个实例,没有任何属性,它可以使用Foo
类中定义的任何方法。
如果需要,您可以创建自己的__init__
替换函数来初始化属性:
def init_foo(foo, name):
foo.name = name
>>> init_foo(x, "Mike")
>>> x.name
'Mike'
这当然也可以是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'
更进一步,您甚至可以使用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'