Python中的私有构造函数
我如何创build一个私人的构造函数,应该只调用该类的静态函数而不是从其他地方?
我如何创build一个私人构造函数?
从本质上来说, 这是不可能的 ,因为python不像你认为的那样使用构造函数,如果你来自其他的OOP语言,并且由于python不强制隐私,它只是有一个特定的语法来表明给定的方法/属性应该是视为私人。 让我详细说明…
首先:最接近你在python中可以find的构造函数是__new__
方法,但是这个方法很less使用(通常你使用__init__
来修改刚创build的对象(事实上它已经有self
作为第一个参数)。
无论如何,Python是基于每个人都是自愿的成年人的假设,因此私人/公共不像其他语言那样执行。
正如其他响应者所提到的那样,意味着“私有”的方法通常由一个或两个下划线前缀: _private
或__private
。 两者之间的区别在于后者会扰乱方法的名称,所以您将无法从对象实例化之外调用它,而前者不会。
所以例如,如果你的类A
定义了_private(self)
和__private(self)
:
>>> a = A() >>> a._private() # will work >>> a.__private() # will raise an exception
你通常要使用单下划线,特别是unit testing – 双下划线会使事情变得非常棘手。
HTH!
引用Python风格指南(PEP 8) :
另外,下列特殊forms使用前后的下划线是可以识别的(这些通常可以与任何情况下的惯例相结合):
_single_leading_underscore
:弱的“内部使用”指标。 例如,“from M import *
”不导入名称以下划线开头的对象。
single_trailing_underscore_
:single_trailing_underscore_
使用,以避免与Python关键字冲突,例如Tkinter.Toplevel(master, class_='ClassName')
__double_leading_underscore
:当命名一个类属性时,调用名字改变(在类FooBar中,__boo
变成_FooBar__boo
;见下文)。
__double_leading_and_trailing_underscore__
:位于用户控制的命名空间中的“魔术”对象或属性。 例如__init__
,__init__
__import__
或__file__
。 不要发明这样的名字; 只有按照logging使用它们。
就像没有人提到过这一点 – 你可以很好地控制在什么范围内可以看到哪些名字 – 而且有很多可用的范围。 下面是另外两种方法来限制一个类的工厂方法的build设:
#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
(注意:这仍然允许从外部引用该类(例如,对于实例检查),但是很明显,您不应该直接实例化它。)
要么
#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
这使得至less不使用至less一个魔术(双下划线)属性来访问Foo
类,但仍允许多个函数使用它(通过在删除全局Foo名称之前定义它们)。
首先,“构造函数”一词并不适用于Python,因为尽pipe__init__()
方法起到一个作用,它只是一个方法,当一个对象已经被创build并且需要初始化的时候被调用。
Python中的每个类的方法都是公共的。 通常,程序员用方法名称中的_
或__
标记“私有”方法,例如:
# inheriting from object is relevant for Python 2.x only class MyClass(object): # kinda "constructor" def __init__(self): pass # here is a "private" method def _some_method(self): pass # ... and a public one def another_method(self): pass
_
和__
前缀并没有提供一个解决scheme来限制一个对象的实例化到一个特定的“工厂”,但是Python是一个强大的工具箱,所需的行为可以通过多种方式实现(就像@Jesse W at Zcertificate)。 这是一个可能的解决scheme,保持类公开可见(允许isinstance
等),但确保build设是唯一可能的类方法:
import uuid class OnlyCreatable(object): __create_key = uuid.uuid4() @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
class-method构造一个对象:
>>> OnlyCreatable.create("I'm a test") <__main__.OnlyCreatable object at 0x1023a6f60>
当尝试构造一个对象而不使用create
class-method创build因断言而失败时:
>>> 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
类方法创build对象由于编译器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
的值。 由于这个class-attribute的值是在运行时生成的,并且它的名字前面加了__标记为不可访问,所以得到这个值和/或构造这个对象是不可能的。
class MongoConn(object): @classmethod def instance(cls): if not hasattr(cls, '_instance'): cls._instance = cls() return cls._instance def __init__(self): assert not hasattr(self.__class__, '_instance'), 'Do not call constructor directly!'
如果你想要一个单一的实例。