Python中的私有构造函数
我该如何创建一个私有构造函数,让它只能被类中的静态函数调用,而不能从其他地方调用呢?
14 个回答
你可以对在不同范围内可见的名称有很大的控制权——而且可用的范围有很多。下面是两种 三种其他方法,可以限制一个类只能通过工厂方法来创建:
#Define the class within the factory method
def factory():
class Foo:
pass
return Foo()
或者
#Assign the class as an attribute of the factory method
def factory():
return factory.Foo()
class Foo:
pass
factory.Foo = Foo
del Foo
(注意:这仍然允许从外部引用这个类(比如用于isinstance
检查),但很明显你不应该直接实例化它。)
或者
#Assign the class to a local variable of an outer function
class Foo:
pass
def factory_maker():
inner_Foo=Foo
def factory():
return inner_Foo()
return factory
factory = factory_maker()
del Foo
del factory_maker
这样做会让访问Foo
类变得不可能(至少,除非使用至少一个魔法(双下划线)属性),但仍然允许多个函数使用它(通过在删除全局Foo名称之前定义它们)。
如何创建一个私有构造函数?
简单来说,这是不可能的。因为 Python 的构造函数和你在其他面向对象编程语言中理解的方式不一样,而且 Python 并不严格限制私有性,它只是有一种特定的语法来表示某个方法或属性应该被视为私有的。让我详细解释一下……
首先,Python 中最接近构造函数的东西是__new__
方法,但这个方法非常少用(你通常会使用__init__
,它用于修改刚创建的对象,实际上它的第一个参数已经是self
了)。
无论如何,Python 的设计理念是大家都是成年人,因此私有和公共的概念并不像其他语言那样严格。
正如其他回答者提到的,通常被认为是“私有”的方法会在前面加一个或两个下划线:_private
或 __private
。这两者的区别在于,后者会对方法的名称进行混淆,这样你就无法从对象外部调用它,而前者则不会。
举个例子,如果你的类A
定义了_private(self)
和__private(self)
:
>>> a = A()
>>> a._private() # will work
>>> a.__private() # will raise an exception
通常你会想使用单个下划线,特别是在单元测试中,使用双下划线可能会让事情变得非常复杂……
希望这对你有帮助!
在Python中,前面加一个下划线(_
)或两个下划线(__
)并不能限制对象只能通过特定的“工厂”来创建。不过,Python是个强大的工具箱,我们可以用多种方法实现想要的效果(正如@Jesse W在Z上展示的那样)。
这里有一个可能的解决方案,它让类仍然可以被公开访问(这样可以使用isinstance
等功能),但确保对象只能通过类方法来创建:
class OnlyCreatable(object):
__create_key = object()
@classmethod
def create(cls, value):
return OnlyCreatable(cls.__create_key, value)
def __init__(self, create_key, value):
assert(create_key == OnlyCreatable.__create_key), \
"OnlyCreatable objects must be created using OnlyCreatable.create"
self.value = value
通过create
这个类方法来构造对象:
>>> OnlyCreatable.create("I'm a test")
<__main__.OnlyCreatable object at 0x1023a6f60>
如果试图不使用create
这个类方法来构造对象,就会因为断言失败而无法创建:
>>> OnlyCreatable(0, "I'm a test")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 11, in __init__
AssertionError: OnlyCreatable objects can only be created using OnlyCreatable.create
如果试图模仿create
这个类方法来创建对象,也会因为编译器对OnlyCreatable.__createKey
的处理而失败。
>>> OnlyCreatable(OnlyCreatable.__createKey, "I'm a test")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: type object 'OnlyCreatable' has no attribute '__createKey'
在类方法之外构造OnlyCreatable
的唯一方法是知道OnlyCreatable.__create_key
的值。由于这个类属性的值是在运行时生成的,并且它的名字前面有两个下划线,标记为不可访问,因此实际上几乎“无法”获取这个值和/或构造这个对象。