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!' 

如果你想要一个单一的实例。