从全局变量导入的类填充属性

时间:2019-04-25 17:17:38

标签: python class global-variables

我有一个要在运行时填充的类属性,但是我不想传递该值。我现在正在做的是:

weird_class.py

class WeirdClass:
    prop = NotImplementedError

runtime_file.py

from weird_class import WeirdClass
PROP = 'somevalue'

class WeirdClassChild(WeirdClass):
    prop = PROP

这可行,但是每当我创建WeirdClassChild时,都必须设置prop值,这很烦人。

我想让WeirdClassChild自动选择PROP全局变量,而无需我特别告知它。

我想做类似的事情:

class WeirdClass:
    prop = __global_namespace__.PROP

这在python中可能吗?

4 个答案:

答案 0 :(得分:2)

您可以使用inspect ion来确定实例化您的类的上下文:

# class definition
import inspect
class Weird:
    def __init__(self):
        caller_frame = inspect.stack()[1]
        caller_module = caller_frame[0]
        self.prop = caller_module.f_globals['PROP']

# instantiation
PROP = 555
x = Weird()
print(x.prop)
=> 555

我不一定会推荐它,但是如果您有充分的理由这样做...

答案 1 :(得分:1)

您也许可以使用元类:

#!/usr/bin/env python3

PROP = "only for subclasses"


class _WierdMeta(type):
    # Not sure if you should use __init__ or __new__
    # Use one or the other.

    # `cls` is an instance of the class type that _WierdMeta creates
    def __init__(cls, name, bases, dct):
        if bases:
            cls.prop = PROP
        super().__init__(name, bases, dct)

    # `cls` is _WierdMeta  
    def __new__(cls, name, bases, dct):
        class_type = super().__new__(cls, name, bases, dct)
        if bases:
            class_type.prop = PROP
        # this return value will be the `cls` passed to __init__ above
        return class_type

class WierdBase(metaclass=_WierdMeta):
    """Base class."""
    prop = "base"


class WierdChild(WierdBase):
    pass


wb = WierdBase()
wc = WierdChild()
print(wb.prop)  # print('base') 
print(wc.prop)  # print('only for subclasses')

似乎从Python 3.6开始,您可以使用__init_subclass__来做到这一点。

class WierdBase():
    """Base class."""
    prop = "base"

    # I'm not 100% on the args here...
    def __init_subclass__(cls, **kwargs):
        # ... or here.
        super().__init_subclass__(**kwargs)
        if cls is not WierdBase:
            cls.prop = PROP

答案 2 :(得分:1)

根据您最后的用法说明,为什么不添加另一个基类?

from weird_class import WeirdClass
PROP = 'somevalue'

class WeirdClassChildBase(WeirdClass):
    prop = PROP

class WeirdClassChild_1(WeirdClassChildBase):
    pass

class WeirdClassChild_2(WeirdClassChildBase):
    pass

...

答案 3 :(得分:0)

我将其分为三个文件,并按照此处说明的方法进行操作:https://instructobit.com/tutorial/108/How-to-share-global-variables-between-files-in-Python

  • globals.py-在这里初始化PROP的值
  • weird_class.py-在这里,您应该导入globals.py并使用PROP值
  • start.py-在这里您可以测试奇怪的类,但是在导入其模块之前,您应该导入globals.py并调用一些初始化方法

globals.py文件将汇总所有全局默认值。首先假设在start.py脚本中,您应该导入全局变量并对其进行初始化。

    import globals
    globals.initialize()
    from weird_class import WeirdClass

    c = WeirdClass()
    print(c.prop)

在weird_class文件中,如果已导入变量,则可以从globals.py访问变量:

    import globals
    class WeirdClass:
        prop = globals.PROP

最后globals.py看起来像这样:

    def initialize():
        global PROP
        PROP = "my global value"

此处的关键部分是在设置初始值之前声明global PROPglobal关键字将在模块global中使变量globals

在模块范围内的单个中心位置具有全局变量,常量和所有魔术值通常是一个优势。