简体   繁体   English

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

[英]What is a simple way to deal with argument initial in (*args, **kwargs) python?

Base class looks like this (code comes from Django, but the question isn't Django specific): 基类看起来像这样(代码来自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

Derived class looks like this: 派生类如下所示:

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))

If the coder passes instance as a kwargs this is all fine and should work, but what if they don't do that and pass it in args instead? 如果编码器将实例作为kwargs传递,这很好并且应该可以工作,但是如果他们不这样做,而是将其传递给args怎么办? What is a sane way to extract instance when dealing with *args and **kwargs? 处理* args和** kwargs时,提取实例的明智方法是什么? Admittedly in this case the chances of instance being in args is small, but if it was the 3rd argument instead of the 5th (not counting self). 诚然,在这种情况下,实例出现在args中的机会很小,但是如果它是第3个参数而不是第5个参数(不计算self)。

Well in django if instance is not passed or its not properly set then it becomes None and init will then create a new instance for you http://docs.nullpobug.com/django/trunk/django.forms.models-pysrc.html#BaseModelForm But this isn't your question. 在django中,如果实例未通过或未正确设置,则它将变为None,然后init将为您创建一个新实例http://docs.nullpobug.com/django/trunk/django.forms.models-pysrc.html #BaseModelForm但这不是您的问题。 If the other variables aren't properly set an exception will probably be raised. 如果其他变量的设置不正确,则可能会引发异常。

Its really up to you if you want to check if the user has properly used your API, and in python this can be quite daunting, and checking for instance types isn't very pythonic, there are very heated debate though out the web about whether its a good or bad thing to have a language thats so dynamically typed. 如果您要检查用户是否已正确使用您的API,这完全取决于您,在python中这可能非常艰巨,并且检查实例类型不是pythonic,尽管在网络上有关是否具有如此动态键入的语言是好事还是坏事。 On one hand you can be very productive in a dynamically typed language on the other you can have really nasty bugs whose solution aren't that apparent, but thats from my own experience. 一方面,您可以使用动态类型的语言来提高工作效率,另一方面,您可以遇到真正令人讨厌的错误,其解决方案似乎并不明显,但这仅是我的经验。

I believe consistency is one of the most crucial things a system could have, as such I tend to always use keyword values, all set to None and then simply do an assert to make sure all that are required aren't None, you could have a function that just checks your parameters are good. 我相信一致性是系统可能具有的最关键的功能之一,因此我倾向于始终使用全部设置为“无”的关键字值,然后简单地执行断言以确保所需的所有条件都不是“无”,您可以仅检查您的参数的功能是好的。 Keyword arguments tend to be the most flexible, from my own experience, since you don't need to keep track of the order, you pay the price by having the callee remember its name. 根据我自己的经验,关键字参数通常是最灵活的,因为您不需要跟踪订单,因此可以通过让被叫者记住其名称来支付费用。

If you really need 'instance' then you can iterate over args and/or kwargs using isinstance to get the instance variable, though like I said this isn't very pythonic.... 如果您确实需要“实例”,则可以使用isinstance遍历args和/或kwargs以获取实例变量,尽管就像我说的那样,它不是很pythonic。

If you insist on accepting *args , one way to handle this situation if getting instance matters to MyForm , is to explicitly include instance as a keyword argument to MyForm , add instance to kwargs, and then pass up kwargs. 如果您坚持接受*args那么在MyForm获取instance重要时 ,处理这种情况的一种方法是显式地将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)

Note that, if someone put instance as the third positional argument, they would be making a very explicit error, since instance is the last argument to BaseModelForm. 请注意,如果有人将instance作为第三个位置参数,则他们会犯一个非常明显的错误,因为instance是BaseModelForm的最后一个参数。

However, a better way to handle this situation would be to specifically not allow additional positional arguments. 但是,处理这种情况的更好方法是明确不允许使用其他位置参数。 Eg: 例如:

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))

That way, MyForm can only be called with up to 2 positional arguments. 这样,只能使用最多2个位置参数来调用MyForm Any more and the Python interpreter will generate a TypeError: <func> takes exactly 2 arguments (# given) . Python解释器将生成TypeError: <func> takes exactly 2 arguments (# given)

If you need to use the instance argument, you should explicitly include it in the keyword arguments to MyForm . 如果需要使用instance参数,则应将其明确包含在MyForm的关键字参数中。 Failing that, you at least should note it in the doc string to the function. 失败的话,您至少应该在函数的doc字符串中注明。

If you're subclassing BaseModelForm and it has a self.instance variable, you could access it directly via super. 如果您是BaseModelForm的子类,并且具有self.instance变量,则可以直接通过super访问它。 Eg self.instance = super(EdocForm, self).instance . 例如self.instance = super(EdocForm, self).instance That way, you let the superclass handle whatever it needs to do with instance and grab the instance for yourself post-processing. 这样,您可以让超类处理实例所需要做的任何事情,并为您自己进行实例后期处理。 (be careful about syntax with super...you need both the class and self) (要注意super的语法...您需要类和自身)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM