Python中是否有静态构造函数或静态初始化程序?

时间:2011-09-13 02:11:13

标签: python

Python中是否存在静态构造函数?

如何在Python中实现静态构造函数?

这是我的代码......当我像这样调用App时,__init__不会触发。 __init__不是静态构造函数或静态初始化程序。

App.EmailQueue.DoSomething()

我必须像这样调用它,每次都实例化App类:

App().EmailQueue.DoSomething()

这是我的班级:

class App:
    def __init__(self):
        self._mailQueue = EmailQueue()

    @property
    def EmailQueue(self):
        return self._mailQueue

每次调用__init__的问题是重新创建App对象。我的“真正的”App类很长。

6 个答案:

答案 0 :(得分:21)

静态和动态语言之间存在根本区别,起初并不总是很明显。

在静态语言中,类是在编译时定义的,并且在程序运行之前一切都很好并且具体设置。

在动态语言中,类实际上是在运行时定义的。一旦解释器解析并开始执行所有这些类和def语句,就会运行等效的静态构造函数。此时正在执行类定义。

您可以在类体内的任何位置放置任意数量的语句,它们实际上是一个静态构造函数。如果需要,可以将它们全部放在不以self作为参数的函数中,并在类的末尾调用该函数。

答案 1 :(得分:16)

提示:引用self的任何内容都需要对类进行实例化。你可以这样做:

class App:
    email_queue = EmailQueue()

App.email_queue.DoSomething()

但是来吧,这似乎有很多毛病。我喜欢SLaks,只是在课外初始化它。或者,您可以查看singleton pattern

答案 2 :(得分:6)

我创建了一个static_init装饰器,该装饰器将调用static_init类方法(如果存在)。

这是装饰器,以及如何使用它来初始化枚举类的类变量的示例:

# pylint: disable=missing-docstring,no-member

import enum

def static_init(cls):
    if getattr(cls, "static_init", None):
        cls.static_init()
    return cls

@static_init
class SomeEnum(enum.Enum):
    VAL_A = enum.auto()
    VAL_B = enum.auto()
    VAL_C = enum.auto()
    VAL_D = enum.auto()

    @classmethod
    def static_init(cls):
        text_dict = {}
        setattr(cls, 'text_dict', text_dict)
        for value in cls:
            text_dict[value.name.lower().replace("_", " ").title()] = value

def test_static_init():
    assert SomeEnum.text_dict["Val A"] == SomeEnum.VAL_A
    assert SomeEnum.text_dict["Val B"] == SomeEnum.VAL_B
    assert SomeEnum.text_dict["Val C"] == SomeEnum.VAL_C
    assert SomeEnum.text_dict["Val D"] == SomeEnum.VAL_D

答案 3 :(得分:2)

您需要实例化您的应用,然后使用它:

myApp = App()
myApp.EmailQueue.DoSomething()

答案 4 :(得分:1)

您可以使用class方法-参见下面的代码示例中的@classmethod装饰器:

class A(object):
    _some_private_static_member = None

    @classmethod
    def reset_static_data_members(cls, some_value):
        cls._some_private_static_member = some_value

A.reset_static_data_members("some static value")

但是请注意,这很可能是您不想想要做的事情,因为它会修改类型的状态-因此会影响以后所有对使用/依赖于更改后的静态类数据成员的那种类型的方法。如果在此类的实例中通过self.访问并设置了此类静态类数据成员,当您很容易得到意外的行为时,情况就变得很糟糕。

真正做到这一点的正确方法(或大多数开发人员期望行为的常识方法)是确保仅一次设置静态数据成员-导入期间(静态数据成员初始化在C ++,C#,Java中的类比方式)。 Python具有实现该功能的机制-就地初始化:

class A(object):
    _some_private_static_member_0 = "value 0"
    _some_private_static_member_1 = "value 1"

可能您可以使用从函数中返回的值初始化静态类成员,这些函数从(类中)抽象出更复杂的值生成:

class A(object):
    _some_private_static_member_0 = some_function_0()
    _some_private_static_member_1 = some_function_1()

答案 5 :(得分:0)

这是对此问题的另一种看法,在类def之后和任何类函数之前阐述代码区域。我将if条件和代码折叠区域括起来,以便各种编辑器能够在您想要隐藏它的情况下折叠这段代码....

class MyClass :

    myStaticVar1 = {}
    myStaticVar2 = []

    #region STATICINIT
    if not myStaticVar1 :
       # implement arbitrary initialization logic here
       # with any helper variables you don't want cluttering up the class
       localVarDontWantInClassScope = [1,2,3]

       myStaticVar1[0] = localVarDontWantInClassScope[0]
       myStaticVar1[1] = localVarDontWantInClassScope[2]

       myStaticVar2.append("abc")

       # local var cleanup
       del localVarDontWantInClassScope
    #endregion

    def f1(self, i) :
        print( "{} {}".format( i , MyClass.myStaticVar1[i] ) )