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

2024-09-29 23:15:22 发布

您现在位置:Python中文网/ 问答频道 /正文

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

怪异的u类.py

class WeirdClass:
    prop = NotImplementedError

运行时文件.py

from weird_class import WeirdClass
PROP = 'somevalue'

class WeirdClassChild(WeirdClass):
    prop = PROP

这是可行的,但是每当我创建WeirdClassChild时,我就必须设置prop值,这很恼人

我想要的是WeirdClassChild自动选取PROP全局变量,而不需要我特别告诉它

我想做一些类似的事情:

class WeirdClass:
    prop = __global_namespace__.PROP

这在python中是可能的吗


Tags: 文件frompyimport属性事情class全局变量
3条回答

您可以使用元类:

#!/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')

从python3.6开始,似乎可以使用^{}来完成

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

基于您上次对如何使用它的评论,为什么不添加另一个基类呢

from weird_class import WeirdClass
PROP = 'somevalue'

class WeirdClassChildBase(WeirdClass):
    prop = PROP

class WeirdClassChild_1(WeirdClassChildBase):
    pass

class WeirdClassChild_2(WeirdClassChildBase):
    pass

...

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

# 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

我不一定推荐,但如果你有充分的理由这么做

相关问题 更多 >

    热门问题