【问题标题】:Why is the init method for the child class also altering the parent class?为什么子类的init方法也会改变父类?
【发布时间】:2020-12-17 04:13:24
【问题描述】:

Python 版本:3.8.5

棉花糖:3.9.1

我创建了一个方法来创建 Marshmallow 模式并将属性标签添加到传递给函数的任何模式。您可能会看到下面的示例代码:

from marshmallow import Schema, fields

def _configure_y_subschema(schema):
    """Configures a Y schema wherever Y attributes are necessary.
    Args:
        schema: The ownership schema to duplicate
    Returns:
        A `YSchema` that is a duplication of the specified schema
        with all fields having `x_is_y = True`
    """
    y_dynamic_class = type(
        schema.__name__.replace('Schema', 'YSchema'),
        (schema,),
        {}
    )

    def y_init(self, *args, **kwargs):
        super(y_dynamic_class, self).__init__(*args, **kwargs)
        for field in self.fields:
            self.fields[field].metadata['x_is_y'] = True

    y_dynamic_class.__init__ = y_init
    return y_dynamic_class


class SomeSchema(Schema):
   example1 = fields.String()
   example2 = fields.List(fields.Integer())


parent_schema_obj = SomeSchema()

child_y_schema_class = _configure_y_subschema(SomeSchema)
child_schema_obj = child_y_schema_class()

当我运行生成的代码时,parent_schema_objchild_schema_obj 字段中的所有字段都有 x_is_y=True。有谁知道为什么父母和孩子都在更新?如果是这样,我怎么能只有子类的字段具有x_is_y=True 属性?很高兴提供任何其他信息。

【问题讨论】:

  • Schema的定义在哪里?就此而言,fields 的定义在哪里?
  • fieldsSchema 来自棉花糖库@Grismar
  • 或许在示例开头添加from marshmallow import Schema, fields 语句并指定您使用的 Python 版本和库?
  • Python 版本:3.8.5 棉花糖:3.9.1 @Grismar
  • 是不是因为你原来的类将东西定义为类变量?

标签: python marshmallow


【解决方案1】:

你会发现,在y_init,这个条件成立:

self.fields['example1'].metadata is parent_schema_obj.fields['example1'].metadata

child_y_schema_class 字段和 SomeSchema 字段的元数据字典是同一个字典,当您通过 self.fields[field].metadata['x_is_y'] = True 对其进行修改时,您会同时修改两者。

目前尚不清楚您要达到什么目标,因此很难就如何采取不同的做法提供指导。但这回答了“为什么”的问题。

【讨论】:

  • 感谢@grismar 提供的信息。我试图让它只有孩子有x_is_y=True
  • 不过,这有点 XY 问题的情况——你能详细说明你为什么要这样做吗?这里的目标是什么?
  • 我的应用程序中有几个模式,这是一个小的 sn-p。但想象一下 SomeSchema 嵌套在 Schema、SchemaA、SchemaB 和 SchemaC 中。在以 A、B、C 结尾的模式中,我需要 SomeSchema 具有属性 x_is_y=True 但不在模式中。我不想在很多地方声明相同的 SomeSchema,我只想要一个函数来动态创建一个具有所需属性的新类@grismar
  • 写一个 mixin 不是实现这一目标的正确方法吗?
  • 我很想知道 mixin 如何能够更改模式字段的属性?它只会包含特定字段的模板
猜你喜欢
  • 2021-08-24
  • 2013-06-20
  • 1970-01-01
  • 1970-01-01
  • 2020-06-14
  • 2021-09-15
  • 1970-01-01
  • 1970-01-01
  • 2013-03-01
相关资源
最近更新 更多