如何使用 MYPY 传递关键字参数?

问题描述

假设:

Index

我这样使用:

def foo(biz: str = 'biz',baz: str = 'baz',*args:Any,**kwargs:Any)-> str:
   return biz + baz

请注意,这个目标(指定关键字并传递 args + kwargs)掩盖了我对 args 的一些其他误解:在 python 中,不能在具有认值的 arg 之后传入(关键字 arg)已设置,如下面正确指出的..

然后 def bar(ness: str = 'ness',*args,**kwargs): return foo(biz=ness,**kwargs) 版本 0.812 抛出如下错误

mypy

有没有办法解决这个问题,特别是除了下面的返回行之外的任何地方都没有进行重大更改?

$: mypy --ignore-missing-imports --disallow-untyped-defs --disallow-incomplete-defs

foo/foo.py:6: error: "foo" gets multiple values for keyword argument "biz"

解决方法

尽管对 foo 的调用进行了排序,但在考虑关键字参数 args 之前,biz 中的值已分配给位置参数。这意味着 bar可以 用位置参数调用,可以biz 之前有一个赋值给 ness分配给它。

也就是说,mypy 正在及早捕获以下潜在的运行时错误:

>>> bar("1","2")
Traceback (most recent call last):
  File "<stdin>",line 1,in <module>
  File "<stdin>",line 2,in bar
TypeError: foo() got multiple values for argument 'biz'

字符串"1"被分配给ness,字符串"2"成为args的第一个元素。当调用 foo 时,args 的元素被分配给位置参数 bizbaz;在这种情况下,只有 biz 获得一个值,即 "2"。只有到那时才考虑关键字参数 biz=ness,此时 biz 已经被考虑在内。

,

这是我一直在寻找的答案,最后:

-----------------------------------------------------------------------------
    PRES   HGHT   TEMP   DWPT   RELH   MIXR   DRCT   SKNT   THTA   THTE   THTV
     hPa     m      C      C      %    g/kg    deg   knot     K      K      K 
 -----------------------------------------------------------------------------
  1008.0      4   22.2   18.7     81  13.65    270      1  294.7  333.9  297.1
  1004.0     40   21.6   16.6     73  11.97    268      2  294.4  328.9  296.5
  1000.0     76   21.8   16.8     73  12.18    265      3  294.9  330.1  297.1
   996.0    111   20.8   16.2     75  11.76    270      5  294.3  328.1  296.4
   990.0    163   22.4   15.4     65  11.23    278      7  296.4  329.1  298.4
   983.0    225   22.0   14.0     60  10.32    288     10  296.6  326.7  298.4
   974.0    304   21.3   13.8     62  10.28    300     14  296.7  326.7  298.5
   946.0    556   19.2   13.2     68  10.18    313     19  297.0  326.8  298.8
   941.0    602   19.0   12.6     67   9.85    315     20  297.3  326.1  299.0
   932.0    684   18.6   11.6     64   9.28    312     19  297.7  325.0  299.3
   925.0    749   18.0   12.0     68   9.61    310     18  297.7  325.9  299.4
   909.0    898   17.1   11.7     71   9.57    315     11  298.2  326.4  299.9
   894.0   1039   16.1   11.3     73   9.52    355      5  298.7  326.8  300.4
   884.0   1135   15.5   11.1     75   9.50      5      5  299.0  327.1  300.7
   850.0   1469   13.4   10.4     82   9.40    100      5  300.2  328.1  301.9
   829.0   1677   12.1    9.4     84   9.03    115      8  301.0  327.9  302.6
   798.0   1995   10.2    8.0     86   8.49    180      8  302.2  327.7  303.8
   788.0   2100    9.6    7.5     87   8.32    170      7  302.6  327.7  304.1
   746.0   2556    6.8    5.4     91   7.59    252      4  304.4  327.5  305.8
   719.0   2859    5.4    2.4     81   6.37    307      2  306.1  325.7  307.3
   715.0   2905    5.5    2.0     78   6.22    315      2  306.7  325.9  307.9
   712.0   2939    5.6    1.7     76   6.11    313      3  307.2  326.1  308.3
   706.0   3008    5.2    1.1     75   5.90    309      4  307.5  325.8  308.6
   700.0   3078    4.8    0.8     75   5.83    305      6  307.8  325.9  308.9
   670.0   3433    1.8   -1.0     82   5.34    290     12  308.3  325.0  309.3
   652.0   3652    1.0   -3.6     71   4.52    280     15  309.8  324.1  310.6
   642.0   3776    0.0   -4.3     73   4.35    274     17  310.0  323.9  310.8
   634.0   3876   -0.8   -4.5     76   4.34    270     19  310.3  324.1  311.1
   622.0   4029   -1.9   -4.8     81   4.33    270     23  310.7  324.5  311.5
   609.0   4195   -2.9   -7.0     73   3.74    270     28  311.4  323.5  312.1
   568.0   4744   -6.1  -14.1     53   2.27    257     33  313.9  321.5  314.3
   548.0   5022   -7.7  -14.3     59   2.31    250     35  315.2  322.9  315.6
   518.0   5458  -10.3  -14.7     70   2.38    245     25  317.2  325.2  317.6
   516.0   5488  -10.5  -14.7     71   2.38    244     25  317.3  325.4  317.8
   500.0   5730  -11.7  -17.7     61   1.91    240     28  318.7  325.3  319.1
   467.0   6252  -13.9  -23.9     43   1.19    243     30  322.3  326.5  322.5
   413.0   7174  -21.5  -29.5     48   0.81    249     32  324.0  327.0  324.1
   400.0   7410  -22.9  -31.9     44   0.66    250     33  325.1  327.6  325.3
   313.0   9150  -36.3  -53.2     16   0.09    255     44  330.0  330.4  330.0
   302.0   9404  -38.3  -56.3     13   0.06    251     50  330.6  330.9  330.7
   300.0   9450  -38.3  -56.3     13   0.06    250     51  331.3  331.5  331.3
   295.0   9566  -37.7  -55.7     13   0.07    250     55  333.7  334.0  333.7
   289.0   9705  -38.4  -56.8     13   0.06    250     59  334.6  334.9  334.6
   250.0  10690  -43.7  -64.7      8   0.03    240     78  341.0  341.1  341.0
   249.0  10717  -43.8  -64.8      8   0.03    240     78  341.2  341.4  341.2
   211.0  11822  -46.9  -67.9      7   0.02    250     94  352.9  353.0  352.9
   205.0  12015  -47.4  -68.4      7   0.02    250     98  355.0  355.1  355.0
   200.0  12180  -47.9  -68.9      7   0.02    250     93  356.8  356.8  356.8
   184.0  12722  -49.9  -72.0      6   0.01    245     77  362.2  362.2  362.2
   173.0  13123  -51.3  -74.3      5   0.01    235     86  366.2  366.2  366.2
   163.0  13510  -52.7  -76.6      4   0.01    240    100  370.1  370.1  370.1
   154.0  13879  -54.1  -78.7      3   0.01    250     90  373.9  373.9  373.9
   150.0  14050  -54.7  -79.7      3   0.00    250     86  375.6  375.6  375.6
   142.0  14399  -56.5  -81.5      3   0.00    255     76  378.4  378.4  378.4
   141.0  14444  -56.5  -81.5      3   0.00    255     74  379.2  379.2  379.2
   138.0  14581  -56.4  -82.0      3   0.00    255     66  381.7  381.7  381.7
   136.0  14673  -56.3  -82.3      2   0.00    252     65  383.5  383.5  383.5
   132.0  14862  -56.8  -82.8      2   0.00    245     62  385.9  385.9  385.9
   128.0  15057  -57.3  -83.3      2   0.00    246     61  388.4  388.4  388.4
   123.0  15310  -56.9  -82.9      2   0.00    248     60  393.5  393.6  393.5
   106.0  16245  -59.9  -85.9      2   0.00    253     56  404.9  404.9  404.9
   100.0  16610  -58.9  -86.9      2   0.00    255     54  413.6  413.7  413.6
    93.7  17019  -58.1  -85.1      2   0.00    258     44  423.0  423.0  423.0
    78.4  18130  -62.3  -88.3      2   0.00    265     17  436.4  436.4  436.4
    70.0  18830  -61.5  -89.5      1   0.00    230     21  452.5  452.5  452.5
    67.0  19101  -61.1  -89.1      1   0.00    252     18  459.0  459.1  459.0
    62.1  19569  -61.7  -90.7      1   0.00    290     14  467.8  467.8  467.8
    55.0  20326  -59.1  -88.7      1   0.00    350      7  490.2  490.2  490.2
    50.0  20920  -57.1  -87.1      1   0.00     10      5  508.5  508.5  508.5
    40.6  22241  -56.1  -86.1      1   0.01     56     15  542.2  542.2  542.2
    39.0  22497  -56.5  -86.5      1   0.01     65     17  547.4  547.4  547.4
    38.3  22612  -56.7  -86.7      1   0.01     68     16  549.7  549.8  549.7
    30.0  24170  -54.1  -85.1      1   0.01    110      8  596.6  596.6  596.6
    29.0  24391  -53.4  -84.6      1   0.01    130     11  604.4  604.5  604.4
    25.0  25357  -50.1  -82.4      1   0.02     60     15  639.9  640.1  639.9
    24.0  25622  -49.2  -81.8      1   0.02     95     18  650.0  650.2  650.0
    22.6  26014  -47.9  -80.9      1   0.03     88     15  665.1  665.4  665.2
    21.4  26374  -48.1  -80.1      1   0.03     82     12  675.0  675.3  675.0
    20.0  26820  -47.9  -80.9      1   0.03     75      9  688.8  689.1  688.8
    10.0  31460  -41.7  -75.7      1   0.13     95     30  862.8  864.4  862.8
     4.4  37163  -30.1  -69.1      1   0.79     77     36 1145.5 1158.2 1146.0
     4.3  37327  -29.9  -68.9      1   0.83     77     36 1154.0 1167.4 1154.6
     4.2  37494  -31.5  -69.5      1   0.78     76     37 1154.1 1166.8 1154.7
     4.0                                        75     37"
,

根据您的回答,我假设您希望 linter 传递 bar 的定义,并且您愿意为此目的对 bar 的实现/声明进行更改。

对我来说,根本问题是 bar 的实现是错误的 - 如果 *args 不为空,那么调用 foo(biz=ness,*args,**kwargs) 将失败,并准确报告由我的。

def foo(biz: str = 'biz',baz: str = 'baz',*args:Any,**kwargs:Any)-> str:
    return biz + baz

def bar_from_question(ness: str = 'ness',**kwargs):
    return foo(biz=ness,**kwargs)
>>> bar_from_question("1")
1baz
>>> bar_from_question("1",in <module>
  File "/Users/jean/Projects/python/test-mypy/test.py",line 7,in bar_from_question
     return foo(biz=ness,**kwargs)
TypeError: foo() got multiple values for argument 'biz'

对我来说,你有三个选择:

  1. 通过不再传递 foo 来修复对 args 的调用。这样的更改不会导致功能损失,因为 args 中的非空 bar 无论如何都会引发 TypeError。在这种情况下,您还可以从 args 的签名中删除 bar(同样,不会丢失功能 - 您只需将 TypeError 调用触发的 foo 替换为TypeError 在调用 bar)

    def bar_do_not_pass_args_to_foo(ness: str = 'ness',**kwargs)
    
    def bar_remove_args_from_signature(ness: str = 'ness',**kwargs)
    
  2. 通过将 foo 作为位置参数而不是命名参数传递来修复对 biz 的调用:

    def bar_pass_biz_as_positional(ness: str = 'ness',**kwargs):
        return foo(ness,**kwargs)
    
  3. 对 mypy 隐藏问题(我从你的回答中了解到)

    def bar_hide_from_mypy(ness: str = 'ness',**kwargs):
        kwargs['biz'] = ness
        return foo(*args,**kwargs)
    

    但是,如果目标只是简单地防止 mypy 报告错误,则有相应的语法:

    def bar_suppress_mypy(ness: str = 'ness',**kwargs)  # type: ignore
    

现在,如果我在运行时解释器中比较每个提议的结果:

>>> bar_do_not_pass_args_to_foo("1")
'1baz'
>>> bar_do_not_pass_args_to_foo("1","2")
'1baz'
>>> bar_remove_args_from_signature("1")
'1baz'
>>> bar_remove_args_from_signature("1",in <module>
TypeError: bar_remove_args_from_signature() takes from 0 to 1 positional arguments but 2 were given
>>> bar_pass_biz_as_positional("1")
'1baz'
>>> bar_pass_biz_as_positional("1","2")
'12'
>>> bar_hide_from_mypy("1")
'1baz'
>>> bar_hide_from_mypy("1",line 20,in bar_hide_from_mypy
    return foo(*args,**kwargs)
TypeError: foo() got multiple values for argument 'biz'
>>> bar_suppress_mypy("1")
'1baz'
>>> bar_suppress_mypy("1",line 23,in bar_suppress_mypy
    return foo(biz=ness,**kwargs)  # type: ignore
TypeError: foo() got multiple values for argument 'biz'

你可以看到:

  • 对于 bar_from_question 返回结果的每种情况,其他所有 bar_... 实现都会返回相同的结果;
  • 除了 bar_from_question 之外的所有实现都对 mypy 保持沉默,我的印象是你想要的;

在您的情况下,我会寻求解决潜在问题的方法(即应用第 1 点或第 2 点),而不仅仅是试图强制使用 mypy(第 3 点)。