如何使用元类创建类属性,该元类仅在类本身没有定义时才覆盖? [英] How to create a class property with a metaclass that only overrides when the class itself doesn't have it defined?

查看:49
本文介绍了如何使用元类创建类属性,该元类仅在类本身没有定义时才覆盖?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有这样的设置:

类元(类型):@财产定义测试(自我):返回元"类测试(对象):__元类__ =元测试 = "测试"类 TestSub(对象):测试 = "TestSub"打印(Test.test,TestSub.test)

产生以下输出:

('Meta', 'TestSub')

我的预期是:

('Test', 'TestSub')

我知道为什么会这样:test 被分配给 Test before 元类 Meta 被执行.但我不知道如何实施一种干净的方式来改变这种行为.我知道我可以在 Meta 类的 __init____new__ 中进行修改,但这看起来很脏,因为我必须为每个新财产.那么有没有一种干净的方法(比如编写一个新的装饰器)来获得它?

我也不喜欢仅仅为了解决这个问题而创建一个中级类的想法,但会接受它作为最后的手段.

解决方案

实际上,您的 Test 类的 test 属性没有被覆盖.它仍然存在:

<预><代码>>>>Test.__dict__['test']'测试'

但是,执行 Test.test 不会访问它,因为根据 文档:

<块引用>

如果实例的字典中有一个与数据描述符同名的条目,则数据描述符优先.

property 创建数据描述符.因此,通过使用元类中的属性,您可以阻止对类中普通类变量的访问.

如何最好地解决这个问题尚不清楚,因为不清楚您试图用这种结构完成什么.鉴于您发布的代码,您根本不清楚为什么要使用元类.如果您只想覆盖子类上的类属性,您可以使用 unutbu 的回答中所述的简单继承来实现.

I have a setup like this:

class Meta(type):
    @property
    def test(self):
        return "Meta"


class Test(object):
    __metaclass__ = Meta
    test = "Test"


class TestSub(object):
    test = "TestSub"

print(Test.test, TestSub.test)

Which yields the following output:

('Meta', 'TestSub')

What I would have expected would be:

('Test', 'TestSub')

I know why that happens: test is assigned on Test before the metaclass Meta is executed. But I have no idea about how to implement a clean way of changing this behavior. I know I could hack around in __init__ and __new__ of the Meta class, but that seems dirty because I'd have to modify it for each new property. So is there a clean way (like writing a new decorator) to get this?

I also don't like the idea of creating an intermediate class just to work around this, but would accept it as a last resort.

解决方案

In fact, your Test class's test attribute is not overwritten. It's still there:

>>> Test.__dict__['test']
'Test'

However, doing Test.test doesn't access it, because, according to the documentation:

If an instance’s dictionary has an entry with the same name as a data descriptor, the data descriptor takes precedence.

property creates a data descriptor. So by using a property in the metaclass, you block access to the ordinary class variable on the class.

How best to solve this is not clear, because it's not clear what you're trying to accomplish with this structure. Given the code you posted, it's not clear why you're using a metaclass at all. If you just want override class attributes on subclasses, you can do it with simple inheritance as described in unutbu's answer.

这篇关于如何使用元类创建类属性,该元类仅在类本身没有定义时才覆盖?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆