gpt4 book ai didi

python - 返回修改后的类和使用 type() 的区别

转载 作者:太空宇宙 更新时间:2023-11-03 12:52:26 25 4
gpt4 key购买 nike

我想这更像是一个 python 问题而不是 django 问题,但我无法在其他任何地方复制这种行为,所以我将使用无法按预期工作的确切代码。

当我发现这个工厂函数片段时,我正在 django 中处理一些动态表单:

def get_employee_form(employee):
"""Return the form for a specific Board."""
employee_fields = EmployeeFieldModel.objects.filter(employee = employee).order_by ('order')
class EmployeeForm(forms.Form):
def __init__(self, *args, **kwargs):
forms.Form.__init__(self, *args, **kwargs)
self.employee = employee
def save(self):
"Do the save"
for field in employee_fields:
setattr(EmployeeForm, field.name, copy(type_mapping[field.type]))
return type('EmployeeForm', (forms.Form, ), dict(EmployeeForm.__dict__))

[来自:http://uswaretech.com/blog/2008/10/dynamic-forms-with-django/ ]

有一件事我不明白,为什么返回修改后的 EmployeeForm 不起作用?我的意思是这样的:

def get_employee_form(employee):
#[...]same function body as before

for field in employee_fields:
setattr(EmployeeForm, field.name, copy(type_mapping[field.type]))
return EmployeeForm

当我尝试返回修改后的类时,django 忽略了我的附加字段,但返回 type() 的结果完美无缺。

最佳答案

Lennart 的假设是正确的:元类确实是罪魁祸首。不用猜,看the sources就知道了: 元类是 DeclarativeFieldsMetaclass 当前位于该文件的第 53 行,并根据类在创建时具有的属性添加属性 base_fields 和可能的 media时间。在第 329 行你看到:

class Form(BaseForm):
"A collection of Fields, plus their associated data."
# This is a separate class from BaseForm in order to abstract the way
# self.fields is specified. This class (Form) is the one that does the
# fancy metaclass stuff purely for the semantic sugar -- it allows one
# to define a form using declarative syntax.
# BaseForm itself has no way of designating self.fields.
__metaclass__ = DeclarativeFieldsMetaclass

这意味着在创建具有基础 type 的新类时存在一些脆弱性——所提供的黑魔法可能会也可能不会成功!一种更可靠的方法是使用 EmployeeForm 的类型,它将选取可能涉及的任何元类——即:

return type(EmployeeForm)('EmployeeForm', (forms.Form, ), EmployeeForm.__dict__)

(不需要复制那个 __dict__,顺便说一句)。区别很细微但很重要:我们没有直接使用 type 的 3-args 形式,而是使用 1-arg 形式来获取表单类的类型(即元类),然后以 3-args 形式调用该元类。

确实是黑魔法,但这就是框架的缺点,这些框架使用“纯粹为了语义糖的花哨的元类”&c:只要你想做框架支持的事情,你就在三叶草中,但是哪怕是一点点摆脱这种支持都可能需要抵消巫术(这在某种程度上解释了为什么我经常宁愿使用轻量级、透明的设置,比如 werkzeug,而不是像 Rails 或Django 做:我精通深黑魔法并不意味着我很高兴必须在普通生产代码中使用它……但是,那是另一个讨论;-)。

关于python - 返回修改后的类和使用 type() 的区别,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1251294/

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