gpt4 book ai didi

使用 kwargs 时的 Python 2 和 3 元类兼容性

转载 作者:太空宇宙 更新时间:2023-11-04 03:59:16 27 4
gpt4 key购买 nike

我正在制作一个元类,我在其中自定义 __new__ 方法以根据 kwargs 中提供的值自定义如何创建新类。这在示例中可能更有意义:

class FooMeta(type):
def __new__(cls, name, bases, kwargs):
# do something with the kwargs...
# for example:
if 'foo' in kwargs:
kwargs.update({
'fooattr': 'foovalue'
})
return super(FooMeta, cls).__new__(cls, name, bases, kwargs)

我的问题是如何让它兼容 Python 2 和 3。Six是一个很好的兼容性库,但它不能解决我的问题。您可以将其用作:

class FooClass(six.with_metaclass(FooMeta, FooBase)):
pass

这不起作用,因为六使用给定的元类创建了一个新的基类。下面是 6 的代码 ( link )(从 1.3 开始):

def with_metaclass(meta, base=object):
return meta("NewBase", (base,), {})

因此,我的 __new__ 方法将在没有任何 kwargs 的情况下被调用,因此基本上“破坏”了我的功能。问题是如何在不破坏 Python 2 和 3 的兼容性的情况下完成我想要的行为。请注意,我不需要 Python 2.6 支持,所以如果只有 Python 2.7.x 和 3.x 有可能的话,我是没关系。

背景

我需要这个才能在 Django 中工作。我想创建一个模型工厂元类,它根据模型属性自定义模型的创建方式。

class ModelMeta(ModelBase):
def __new__(cls, name, bases, kwargs):
# depending on kwargs a different model is constructed
# ...

class FooModel(six.with_metaclass(ModelMeta, models.Model):
# some attrs here to be passed to the metaclass

最佳答案

如果我没理解错的话,那就没问题了,它已经可以工作了。您是否真的检查过您的元类是否具有预期的效果?因为我认为它已经做到了。

with_metaclass 返回的类并不意味着扮演您的类 FooClass 的角色。它是一个虚拟类,用作您的类的基类。由于此基类属于元类 FooMeta,您的派生类也将具有元类 FooMeta,因此将使用适当的参数再次调用元类。

class FooMeta(type):
def __new__(cls, name, bases, attrs):
# do something with the kwargs...
# for example:
if 'foo' in attrs:
attrs['fooattr'] = 'foovalue'
return super(FooMeta, cls).__new__(cls, name, bases, attrs)
class FooBase(object):
pass
class FooClass(with_metaclass(FooMeta, FooBase)):
foo = "Yes"

>>> FooClass.fooattr
'foovalue'

顺便说一句,将元类的第三个参数称为kwargs 会令人困惑。它不是真正的关键字参数。它是要创建的类的 __dict__ --- 即类的属性及其值。根据我的经验,此属性通常称为 attrsdct(参见例如 herehere)。

关于使用 kwargs 时的 Python 2 和 3 元类兼容性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16629533/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com