Python中的kwargs参数的可变性 [英] Mutability of the **kwargs argument in Python

查看:157
本文介绍了Python中的kwargs参数的可变性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

考虑一种情况,我在一个方法中更改 kwargs dict:

  def print_arg(** kwargs):
打印kwargs.pop('key')

如果我用这样的字典调用方法 pop_arg

  mydict = {'key':'value'} 
print_arg(** mydict)

将<?c $ c> mydict 由此电话更改?



我也对基础的更详细的解释感兴趣方法调用机制让 mydict 更改。

解决方案

  import dis 
dis.dis(lambda:print_arg(** {'key':'value' ))

 

  6 0 LOAD_GLOBAL 0(print_arg)
3 BUILD_MAP 1
6 LOAD_CONST 1('value')
9 LOAD_CONST 2('key')
12 STORE_MAP
13 CALL_FUNCTION_KW 0
16 RETURN_VALUE

 



我们来看看什么 CALL_FUNCTION_KW ceval .c ):

  case CALL_FUNCTION_VAR:
case CALL_FUNCTION_KW:
case CALL_FUNCTION_VAR_KW:
{

// ...

x = ext_do_call(func,& sp,flags,na,nk);

// ...

 

  static PyObject * 
ext_do_call(PyObject * func,PyObject *** pp_stack,int flags,int na,int nk)
{
int nstar = 0;
PyObject * callargs = NULL;
PyObject * stararg = NULL;
PyObject * kwdict = NULL;
PyObject * result = NULL;

if(flags& CALL_FLAG_KW){//如果**涉及
kwdict = EXT_POP(* pp_stack); //获取带有**
的dict传递if(!PyDict_Check(kwdict)){
PyObject * d;
d = PyDict_New(); // make a new dict
if(d == NULL)
goto ext_call_fail;
if(PyDict_Update(d,kwdict)!= 0){//用旧的
//更新它// .. .. ..
goto ext_call_fail;
}
Py_DECREF(kwdict);
kwdict = d; // kwdict现在是新的dict
}
}

....
result = PyObject_Call(func,callargs,kwdict); // call with new dict


Consider a case where I change the kwargs dict inside a method:

def print_arg(**kwargs):
    print kwargs.pop('key')

If I call the method pop_arg with a dictionary like this:

mydict = {'key':'value'}
print_arg(**mydict)

will mydict be changed by this call?

I am also interested in a more detailed explanation of the underlying method calling mechanism that lets mydict change or not.

解决方案

Let's see:

import dis
dis.dis(lambda: print_arg(**{'key': 'value'}))

 

  6           0 LOAD_GLOBAL              0 (print_arg)
              3 BUILD_MAP                1
              6 LOAD_CONST               1 ('value')
              9 LOAD_CONST               2 ('key')
             12 STORE_MAP           
             13 CALL_FUNCTION_KW         0
             16 RETURN_VALUE        

 

Let's find what CALL_FUNCTION_KW does (ceval.c):

    case CALL_FUNCTION_VAR:
    case CALL_FUNCTION_KW:
    case CALL_FUNCTION_VAR_KW:
    {

        // ... 

        x = ext_do_call(func, &sp, flags, na, nk);

        // ...

 

static PyObject *
ext_do_call(PyObject *func, PyObject ***pp_stack, int flags, int na, int nk)
{
    int nstar = 0;
    PyObject *callargs = NULL;
    PyObject *stararg = NULL;
    PyObject *kwdict = NULL;
    PyObject *result = NULL;

    if (flags & CALL_FLAG_KW) {                     // if ** is involved
        kwdict = EXT_POP(*pp_stack);        // get the dict passed with **      
        if (!PyDict_Check(kwdict)) {
            PyObject *d; 
            d = PyDict_New();                       // make a NEW dict
            if (d == NULL)
                goto ext_call_fail;
            if (PyDict_Update(d, kwdict) != 0) {    // update it with old
                // .. fail ..
                goto ext_call_fail;
            }
            Py_DECREF(kwdict);   
            kwdict = d;              // kwdict is now the new dict
        }
    }

    ....  
    result = PyObject_Call(func, callargs, kwdict);  // call with new dict

这篇关于Python中的kwargs参数的可变性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆