python - 在 Python 中根据上下文注入(inject)静态类属性

标签 python metaprogramming

我正在编写一个网站生成器,其中包含表示网页内容的各种类,例如 PageNewsPostTag类别

我希望能够简单地构造这些对象,对此我没有任何问题。

但是,我还想在特定上下文中构造这些对象 - 例如具有特定根 URL 的网站上下文。假设我将此上下文放入 ContentManager 类的实例中。这是我最终希望得到的代码:

page = Page(title='Test Page', content='hello world!')
assert page.cm == None

cm = ContentManager(root_url='//localhost')
page = cm.Page(title='Test Page', content='hello world!') 
assert page.cm == cm

如果 page.cm 是在 __init__ 中设置的每个实例属性,我可以轻松管理此问题,但我需要在 cm.Page 上调用类方法 需要访问 cm 对象,因此它必须是静态属性。

如果我只是将其设置为 Page 类上的静态属性,它最终也会影响其他 ContentManager 的页面,这是不可取的。

我该如何实现这一目标?元类?或者某种类工厂函数?

最佳答案

一种解决方案可以是为每个 ContentManage 实例创建 Page 的子类:

class Page:
    cm = None

    def __init__(self, title, content):
        self.title = title
        self.content = content


class ContentManager:
    def __init__(self, root_url):
        class PerContentManagerPage(Page):
            cm = self

        self.Page = PerContentManagerPage


page0 = Page(title='Test Page', content='hello world!')

cm = ContentManager(root_url='//localhost')
page = cm.Page(title='Test Page', content='hello world!')

cm2 = ContentManager(root_url='//localhost')
page2 = cm2.Page(title='Test Page 2', content='hello world!')

assert page0.cm is None
assert page.cm == cm
assert page2.cm == cm2

在Python中,类也是一个对象(其元类的实例)。每次实例化 ContentManager 时,此解决方案都会创建一个 Page 的新子类。这意味着 cm.Page 类与 cm2.Page 类不同,但两者都是 Page 的子类。这就是为什么 cm.Page.cmcm2.Page.cm 可能具有不同的值,因为它们是两个单独的类(或类对象)。

注意:虽然在Python中这可以通过动态创建子类对象来解决,但问题通常有更好的解决方案。动态创建类/子类是一个警告信号 (HACK)。

我仍然坚信您不应该为每个内容管理器实例创建页面子类。相反,我只需使用全局 ContentManagerPage 类的实例,通过以合适的方式将它们与彼此的引用连接起来,并将数据和代码放入实例属性/方法。

关于python - 在 Python 中根据上下文注入(inject)静态类属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36873540/

相关文章:

python - 值错误 : Expected object or value when reading json as pandas dataframe

c++ - `if constexpr`可以用来声明不同类型和init-expr的变量吗

python - sqlalchemy 的 xml 配置

python - 模型 limit_choices_to= {'user' : user}

python - 将数字相乘并返回带小数的数字

ruby 。如何知道定义了哪个类的实例方法?

Ruby 作用域方法值技术

c++ - 具有 C++11 构造的映射函数

c++ - 在模板特化中使用非类型模板模板参数

python - NFQUEUE/IPtables - Suricata 内嵌 Python 拦截 DNS