在Python OOP中可以从导入时包含的模块初始化类

我正在使用
Python 2.7

我想知道在Python OOP中是否可以在模块级别添加代码来初始化模块中包含的类.

class DoSomething(object):

    foo = 0
    bar = 0

    @classmethod
    def set_all_to_five(cls):
        cls.bar = 5
        cls.foo = 5

    @classmethod
    def set_all_to_ten(cls):
        cls.bar = 10
        cls.foo = 10


#Module level code - runs on import of the class DoSomething
DoSomething.set_all_to_five()

输出:

>>> from productX.moduleY import DoSomething
>>> print DoSomething.bar
5

该类只包含@classmethod方法,因此我可以调用它们而无需实例化该类.

模块级代码DoSomething.set_all_to_5()在导入模块时初始化类级属性.

最佳答案

[It it] OK to add code in the module level to initialize a class that is contained in the module?

是的,你拥有的很好.当人们将Python描述为动态语言时,这就是“dynamic”这个词的含义:您可以在运行时更改类型的定义.定义类的整个模块必须在可以使用DoSomething名称之前成功导入,因此不可能有人意外使用该类的“未修补”版本.

但是,如果您希望在类块中完全定义类的行为,而不是在类定义之后应用“monkeypatch”,则可以使用其他一些选项.

使用元类:

class DoSomethingMeta(type):

    def __init__(self, name, bases, attrs):
        super(DoSomethingMeta, self).__init__(name, bases, attrs)
        self.set_all_to_five()


class DoSomething(object):

    __metaclass__ = DoSomethingMeta  # for Python3, pass metaclass kwarg instead

    foo = 0
    bar = 0

    @classmethod
    def set_all_to_five(cls):
        cls.bar = 5
        cls.foo = 5

    @classmethod
    def set_all_to_ten(cls):
        cls.bar = 10
        cls.foo = 10

或者,更简单地说,通过使用装饰器:

def mydecorator(cls):
    cls.set_all_to_five()
    return cls

@mydecorator
class DoSomething(object):
    ....
点赞