Python中有静态构造函数或静态初始化器吗?

问题描述 投票:0回答:7

Python中有静态构造函数这样的东西吗?

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

这是我的代码...当我像这样调用应用程序时,

__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 对象都会被重新创建。 我的“真正的”应用程序课程很长。

python
7个回答
34
投票

我创建了一个

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

32
投票

静态语言和动态语言之间存在根本区别,一开始并不总是显而易见。

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

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

您可以在类体内的任何位置放置任意数量的语句,它们实际上是静态构造函数。 如果需要,您可以将它们全部放在不使用

self
作为参数的函数中,并在类末尾调用该函数。


23
投票

提示:任何引用

self
的内容都需要该类的实例化。你可以这样做:

class App:
    email_queue = EmailQueue()

App.email_queue.do_something()

但是拜托,这看起来像是很多废话。我使用 SLAks,只需在课堂外初始化它即可。或者,您可以查看单例模式


5
投票

您可以使用

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")

但是,请注意,这很可能是您想要做的事情,因为它修改了type的状态 - 因此它将影响对该类型的使用/依赖于更改的方法的所有进一步调用静态类数据成员。如果在此类的实例中通过

self.
访问和设置此类静态类数据成员,情况可能会变得很糟糕,此时您很容易会出现意外行为。

真正正确的方法(或者大多数开发人员期望的行为的常识方法),是确保静态数据成员仅在导入期间设置一次(类似于静态数据成员的方式)初始化在 C++、C#、Java 中表现)。 Python 有这样的机制 - in-place初始化:

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()

1
投票

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

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

1
投票

这是对这个问题的另一种看法,阐述了类 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] ) )

0
投票

只是想根据@jxramos的答案分享似乎对我有用的东西

这里局部变量位于函数中,以避免删除它们:

class StaticClass():
    numbers = []

    @staticmethod
    def static_init() -> []:
        values = []
        for i in range(1, 6):
            values.append(i)
        return values

    numbers = static_init()
© www.soinside.com 2019 - 2024. All rights reserved.