什么是处理(*args,**kwargs)python中初始参数的简单方法



基类看起来像这样(代码来自Django,但问题不是Django特有的):

class BaseModelForm(BaseForm):
    def __init__(self, data=None, files=None, auto_id='id_%s', prefix=None,
                 initial=None, error_class=ErrorList, label_suffix=':',
                 empty_permitted=False, instance=None):
class ModelForm(BaseModelForm):
    __metaclass__ = ModelFormMetaclass

派生类如下所示:

class MyForm(forms.ModelForm):
    def __init__(self, data=None, files=None, *args, **kwargs):
        super(EdocForm, self).__init__(data, files, *args, **kwargs)
        self.Meta.model.get_others(data, files, kwargs.get('instance', None))

如果编码人员将实例作为 kwargs 传递,这很好并且应该可以工作,但是如果他们不这样做而是在 args 中传递它怎么办? 在处理 *args 和 **kwargs 时提取实例的理智方法是什么? 诚然,在这种情况下,实例在 args 中的可能性很小,但如果它是第 3 个参数而不是第 5 个参数(不计算 self)。

好吧,

在 django 中,如果实例没有传递或未正确设置,那么它就会变成 None,然后 init 将为你创建一个新实例http://docs.nullpobug.com/django/trunk/django.forms.models-pysrc.html#BaseModelForm但这不是你的问题。如果未正确设置其他变量,则可能会引发异常。

如果您想检查用户是否正确使用了您的 API,这真的取决于您,在 python 中,这可能非常令人生畏,并且检查实例类型并不是很 pythonic,尽管网络上有非常激烈的争论关于拥有如此动态类型的语言是好事还是坏事。一方面,你可以在动态类型语言中非常高效,另一方面,你可能会有非常讨厌的错误,其解决方案并不那么明显,但这是我自己的经验。

我相信一致性是系统可能拥有的最关键的东西之一,因此我倾向于总是使用关键字值,全部设置为 None,然后简单地做一个断言以确保所有需要的不是 None,你可以有一个函数只检查你的参数是否好。根据我自己的经验,关键字参数往往是最灵活的,因为您不需要跟踪订单,您可以通过让被调用者记住其名称来支付代价。

如果你真的需要"实例",那么你可以使用isinstance迭代args和/或kwargs来获取实例变量,尽管就像我说的,这不是很pythonic。

如果你坚持接受*args如果instance问题要MyForm,处理这种情况的一种方法是明确包含instance作为关键字参数来MyForm,将实例添加到kwargs,然后传递kwargs。

class MyForm(forms.ModelForm):
    def __init__(self, data=None, files=None, instance=None, *args, **kwargs):
        kwargs['instance'] = instance
        super(EdocForm, self).__init__(data, files, *args, **kwargs)

请注意,如果有人将实例作为第三个位置参数,他们将犯一个非常明确的错误,因为实例是 BaseModelForm 的最后一个参数。

但是,处理这种情况的更好方法是明确不允许额外的位置参数。 例如:

class MyForm(forms.ModelForm):
    def __init__(self, data=None, files=None, **kwargs):
        super(EdocForm, self).__init__(data, files, *args, **kwargs)
        self.Meta.model.get_others(data, files, kwargs.get('instance', None))

这样,最多只能使用 2 个位置参数调用MyForm。再多一点,Python 解释器将生成一个TypeError: <func> takes exactly 2 arguments (# given)

如果需要使用 instance 参数,则应将其显式包含在关键字参数中以MyForm 。如果做不到这一点,您至少应该在函数的文档字符串中注明它。

如果你正在子类化 BaseModelForm 并且它有一个self.instance变量,你可以通过 super直接访问它。 例如 self.instance = super(EdocForm, self).instance .这样,您就可以让超类处理它需要与实例执行的任何操作,并为自己获取实例进行后处理。(注意超级语法...你既需要类又需要自我)

最新更新