精华内容
下载资源
问答
  • public static class StringExtension { public staticvoid Foo(this ...为什么这里会一个this关键字,做什么用?其实这就是扩展方法!这个扩展方法在静态类中声明,定义一个静态方法,其中第一个参数定义可它

    public static class StringExtension
    {
    public staticvoid Foo(this string s)
    {
      Console.WriteLine("Foo invoked for {0}",s);
    }
    }

    为什么这里会有一个this关键字,做什么用?其实这就是扩展方法!这个扩展方法在静态类中声明,定义一个静态方法,其中第一个参数定义可它的扩展类型。Foo()方法扩展了String类,因为它的第一个参数定义了String类型,为了区分扩展方法和一般的静态方法,扩展方法还需要给第一个参数使用this关键字。

    现在就可以使用带string类型的Foo方法了:

    string s="Hello"; s.Foo();

    结果在控制台上显示Foo invoked for Hello ,因为Hello是传送给Foo方法的字符串。

    归纳:扩展方法可以写入最初没有提供该方法的类中。还可以把方法添加到实现某个接口的任何类中,这样多个类可以使用相同的实现代码。

    展开全文
  • 1、首先什么是可变参数列表? 对于一般的函数而言,参数列表都是固定的,而且各个参数之间逗号进行分开。这种函数在调用的时候,必须严格按照参数列表中参数的个数进行传参,否则编译器就会报错。 int add(int ...

    1、首先什么是可变参数列表?

    对于一般的函数而言,参数列表都是固定的,而且各个参数之间用逗号进行分开。这种函数在调用的时候,必须严格按照参数列表中参数的个数进行传参,否则编译器就会报错。

    int add(int a, int b)                 //该函数定义时,参数有两个,所以在调用时只能传入两个参数
    {
    	int c = a + b;
    	return c;
    }
    int main()
    {
    	int sum1 = 0;
    	int sum2 = 0;
    	int sum3 = 0;
    	sum1 = add(1);                    //报错:error C2198: “add”: 用于调用的参数太少
    	sum2 = add(1, 2);                 
    	sum3 = add(1, 2, 3);              //报错:warning C4020: “add”: 实参太多
    	return 0;
    }
    

    我们应该都注意到,库函数 printf(); 的参数并不是固定的,传入的参数个数不同,但该函数仍然可以成功执行。如下:

        int a = 20;
    	int b = 30;
    	printf("10\n");                
    	printf("%d\n",a);
    	printf("%d %d\n",a, b);
    
        //printf函数的定义如下:
        //int __cdecl printf(_In_z_ _Printf_format_string_ const char * _Format, ...);
        //可以看出参数列表中的参数并没有完全给出

    所以,具有可变参数列表的函数就是:函数定义时,参数列表中的的参数不完全定义;调用该函数时,可以根据实际情况传入多个参数,且可以成功完成其函数功能。而该函数的参数列表就是可变参数列表。

    2、那么通过一个简单的函数,详细了解一下具有可变参数列表的函数时如何实现函数功能的

    #include<stdio.h>
    #include<stdarg.h>
    
    int average(int n, ...)            //该函数的功能为:求出任意个数参数的平均值
    {
    	int i = 0;
    	int sum = 0;
    	va_list arg;                   //即:char* arg;
    	va_start(arg, n);              //即:arg = (char*)&n + 4;
                                       //初始化arg为位置参数列表中的第一个参数的地址
                                    
    	for(i=0; i<n; i++)
    	{
    		sum += va_arg(arg, int);   //即: sum += (*(int *)(arg += 4) - 4);
                                       //此时已经将arg重新赋值为可变参数列表中第二个参数的地址,
                                       //但是此处保留的仍然是上一个参数的地址,然后对保留地址进行                                            
                                       //强制类型转换之后解以用得到内容(参数)
    	}
    	return sum/n;
    	va_end(arg);                   //即:arg = char* 0;    //把arg置为NULL
    }
    int main()
    {
    	int a = 10;
    	int b = 20;
    	int c = 30;
    	int avg1 = average(2, a, b);
    	int avg2 = average(3, a, b,c);
    	printf("avg1 = %d\n",avg1);
    	printf("avg2 = %d\n",avg2);
    	return 0;
    }
    

    上述代码的执行结果:

    可以看到函数中定义出了几个之前未见过的符号,我们转到定义看看到底是什么:

    typedef char *  va_list;       //类型重定义:将char* 定义为va_list
    
    #define va_start _crt_va_start      
    #define va_arg _crt_va_arg
    #define va_end _crt_va_end     //这三个都是#define 定义的符号,不清楚是什么,再次转到定义:
    
    #define _crt_va_start(ap,v)  ( ap = (va_list)_ADDRESSOF(v) + _INTSIZEOF(v) )
    #define _crt_va_arg(ap,t)    ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) )
    #define _crt_va_end(ap)      ( ap = (va_list)0 )         
                                   //原来是三个宏,对其中不明白的符号再次转到定义:
    
    #define _ADDRESSOF(v)   ( &(v) )
    #define _INTSIZEOF(n)   ( (sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1) )
                                   //仍然是两个宏
                                  
    
    

    哦,这时候先进行替换,方便理解:

    va_list arg;            相当于    char* arg;     //arg是个字符指针呀

    va_start(arg, n);    相当于   _crt_va_start(arg, n);相当于(arg = (va_list)_ADDRESSOF(n) + _INTSIZEOF(n))

                                   相当于   (arg = (char*)&n + ( (sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1) )

                                   其中  ( (sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1) ) ;求出n的字节数,然后向上取整为4的倍数(换句话说: _INTSIZEOF(n)整个做的事情就是将n的长度化为int长度的整数倍

                                   所以在上述代码中相当于 arg = (char*)&n + 4;

                                  //初始化arg为位置参数列表中的第一个参数的地址(如调用这个函数时用的参数为(int 3, 1,2,6),那么此时arg指向的是1所在的地址)

    va_arg(arg, int);    相当于  _crt_va_arg(arg,int)           

                                   相当于   ( *(int *)((arg += _INTSIZEOF(int)) - _INTSIZEOF(int)) )

                                   所以在上述代码中相当于 *(int *)(arg += 4) - 4;

                                   //此时已经将arg重新赋值为可变参数列表中第二个参数的地址,但是此处保留的仍然是上一个参数的地址,然后对保留地址进行强制类型转换之后解以用得到内容(参数)

    va_end(arg);          相当于    (arg = (va_list)0)    

                                   所以在上述代码中相当于 arg = char* 0;  //把arg置为NULL

    回到原来代码中进行替换。

    为了更好的理解,我们把该程序的反汇编拷贝出来解析一下:(仅以int avg1 = average(2, a, b);本次调用为例)

    int main()                               //调用main函数之前已经调用了其他函数
    {
    01154770  push        ebp                //将当前ebp的地址压栈到当前的栈顶,每次压栈esp都更新
    01154771  mov         ebp,esp            //将当前的ebp移动到当前esp的位置处
    01154773  sub         esp,0FCh           //将esp向低地址处移动OFCh,为main()开辟空间
    01154779  push        ebx                //将寄存器ebx压入栈顶
    0115477A  push        esi                //将寄存器esi压入栈顶
    0115477B  push        edi                //将寄存器edi压入栈顶
    0115477C  lea         edi,[ebp-0FCh]     //将为main开辟空间时的esp的地址加载进入edi中
    01154782  mov         ecx,3Fh            //ecx中放入3Fh
    01154787  mov         eax,0CCCCCCCCh     //eax中放入0CCCCCCCCh  
    0115478C  rep stos    dword ptr es:[edi] //从edi中所存的地址处开始,用0CCCCCCCCh始化3Fh次
    0115478E  mov         ecx,offset _FC008D77_test@c (0115C003h)  
    01154793  call        @__CheckForDebuggerJustMyCode@4 (01151212h)  
    	int a = 10;
    01154798  mov         dword ptr [a],0Ah     //创建变量,dword ptr [a]中放入0Ah
    	int b = 20;
    0115479F  mov         dword ptr [b],14h     //创建变量,dword ptr [b]中放入14h
    	int c = 30;
    011547A6  mov         dword ptr [c],1Eh     //创建变量,dword ptr [c]中放入1Eh
    
    	int avg1 = average(2, a, b);            //调用函数前先进行传参(参数列表中从右向左)
    011547AD  mov         eax,dword ptr [b]     //eax中放入dword ptr [b]的内容
    011547B0  push        eax                   //调用average函数前将要用的形参放入寄存器并压栈
    011547B1  mov         ecx,dword ptr [a]     //eax中放入dword ptr [b]的内容
    011547B4  push        ecx                   //调用average函数前将要用的形参放入寄存器并压栈              
    011547B5  push        2                     //将参数2也压栈
    011547B7  call        _average (01151398h)  //开始调用average函数(将此地址进行压栈/保护现场)
    011547BC  add         esp,0Ch               //esp回到原来的位置,将开辟的栈帧回收
    011547BF  mov         dword ptr [avg1],eax  //将eax中存的平均值放入avr1中准备打印
    
    
    int average(int n, ...)           
    {
    01151810  push        ebp  
    01151811  mov         ebp,esp  
    01151813  sub         esp,0E4h  
    01151819  push        ebx  
    0115181A  push        esi  
    0115181B  push        edi  
    0115181C  lea         edi,[ebp-0E4h]  
    01151822  mov         ecx,39h  
    01151827  mov         eax,0CCCCCCCCh  
    0115182C  rep stos    dword ptr es:[edi]   //average()函数的栈帧开辟以及初始化过程,同main()
       
    0115182E  mov         ecx,offset _FC008D77_test@c (0115C003h)  
    01151833  call        @__CheckForDebuggerJustMyCode@4 (01151212h)  
    	int i = 0;
    01151838  mov         dword ptr [i],0      //创建局部变量i并初始化为0;
    	int sum = 0;
    0115183F  mov         dword ptr [sum],0    //创建局部变量sum并初始化为0;
    	va_list arg;                   
    	va_start(arg, n);             
    01151846  lea         eax,[ebp+0Ch]        //将当前的ebp+0Ch处的地址存放到eax中
    01151849  mov         dword ptr [arg],eax  //将eax中的内容赋值给arg			   
    	for (i = 0; i < n; i++)
    0115184C  mov         dword ptr [i],0      //进入循环,先把i用0赋值
    01151853  jmp         average+4Eh (0115185Eh) //跳转到0115185Eh处,执行eax,dword ptr [i]
    01151855  mov         eax,dword ptr [i]    //由0115187Bh跳转过来 
    01151858  add         eax,1                //执行++
    0115185B  mov         dword ptr [i],eax    //并重新赋值给i,继续进行循环
    0115185E  mov         eax,dword ptr [i]    //由01151853h跳转过来,将此时的i加载到eax中
    01151861  cmp         eax,dword ptr [n]    //eax的值与变量n的值进行比较
    01151864  jge         average+6Dh (0115187Dh)  
    	{
    		sum += va_arg(arg, int);           //即: sum += (*(int *)(arg += 4) - 4);
    01151866  mov         eax,dword ptr [arg]  
    01151869  add         eax,4  
    0115186C  mov         dword ptr [arg],eax   //此时arg存放的是下一个参数(第3个参数)的地址
    0115186F  mov         ecx,dword ptr [arg]  
    01151872  mov         edx,dword ptr [sum]  
    01151875  add         edx,dword ptr [ecx-4] //sum的值加上一次arg所指地址处的内容(第2个参数)
    01151878  mov         dword ptr [sum],edx   //将求的和继续放在sum中		   
    	}
    0115187B  jmp         average+45h (01151855h) //跳转到0115185Eh处,执行准备执行i++
    	return sum / n;
    0115187D  mov         eax,dword ptr [sum]   //将for循环结束之后的sum放入eax中
    01151880  cdq  
    01151881  idiv        eax,dword ptr [n]     //用eax中的数值除以变量n的内容,得到平均值
    01151884  jmp         average+7Dh (0115188Dh)  
    	va_end(arg);                   //即:arg = char* 0;    //把arg置为NULL
    01151886  mov         dword ptr [arg],0  
    }
    0115188D  pop         edi                   
    0115188E  pop         esi  
    0115188F  pop         ebx                   //弹出栈顶的各种寄存器
    01151890  add         esp,0E4h              //回收为average开辟的栈帧
    01151896  cmp         ebp,esp  
    01151898  call        __RTC_CheckEsp (0115121Ch)  
    0115189D  mov         esp,ebp                  
    0115189F  pop         ebp  
    011518A0  ret                 //最终将栈顶的元素取出作为一个地址跳转到该地址处回到main()函数)
    

    再以一个简单的图表示一下:

    int avg1 = average(2, a, b);  该语句调用average() 函数时,其参数列表中有三个参数,而且是从右向左依次压栈的。

    因为参数列表中最左侧的参数表示的就是该参数之后参数的个数,所以压栈顺序它在函数栈帧的最上方。当调用函数时,读取这个参数就能在此基础上明确参数的总个数,在利用for循环和arg指针就能准确的完成该函数的功能。

    所以average(); 函数不管有几个参数都可以按照上面的函数栈帧的运行规律正确读取参数个数并成功完成功能。

    3、总结一下:

    3.1 实现参数列表可变的函数的前提是:函数栈帧的压栈规律(参数列表中的参数是从右向左以此压栈的,同时函数栈帧是先使用高地址再使用低地址的)。

    3.2 具有可变参数列表的函数在定义时,参数列表中的参数是不完全给定的,只给出第1个参数,后面用“...”表示,而且第1个参数必须是int类型,用于调用该函数时确定本次调用该函数所传的参数的个数(若传递n个参数,则第1个参数为n-1)。

    3.3 一般都要用到   va_list arg;    va_start(arg, n);    va_arg(arg, int);    va_end(arg)    

    3.4 有一点必须注意:va_arg(arg, int) 每使用一次这个函数,arg指针都会指向下一个参数,所以必须合理使用

    4、可变参数的限制:

    4.1 可变参数必须从头到尾依次访问,在依次访问中可以在中间某一参数处停止,但不能直接访问参数列表中间的参数。

    4.2 参数列表中至善有一个命名参数,否则无法使用va_start

    4.3 上述用到的宏是无法直接判断实际存在的参数的数量。

    4.4 如果在va_arg中执行了错误的类型,那么其后果是不可预测的。

     

    展开全文
  • python的参数传递机制具有值传递(int、float等值数据类型)和引用传递(以字典、列表等非值对象数据类型为代表)两种基本机制以及方便的关键字传递特性(直接使用函数的形参名指定实参的传递目标,如...

    在Python中,“**”参数表示此处接受任意多个关键字参数,这些参数以字典形式保存,即会被解释为一个字典;“*”参数表示此处接受任意多个非关键字参数,这些参数将以数组形式保存,即会被解释为一个元组。

    python的参数传递机制具有值传递(int、float等值数据类型)和引用传递(以字典、列表等非值对象数据类型为代表)两种基本机制以及方便的关键字传递特性(直接使用函数的形参名指定实参的传递目标,如函数定义为def f(a,b,c),那么在调用时可以采用f(b=1,c=2,a=3)的指定形参目标的传递方式,而不必拘泥于c语言之类的形参和实参按位置对应)除此之外,python中还允许包裹方式的参数传递,这为不确定参数个数和参数类型的函数调用提供了基础。

    例如:def f(*a,**b),包裹参数传递的实现是在定义函数时在形参前面加上*或**,*所对应的形参(如上面的a)会被解释为一个元组(tuple,而**所对应的形参(如上面的b)会被解释为一个字典。具体调用时参数的传递见下面的代码:

    上面代码的运行结果是:

    (3, 4)

    {'n': 2, 'm': 1}

    可见,对于不使用关键字传递的变量,会被作为元组的一部分传递给*a,而使用关键字传递的变量作为字典的一部分传递给了**b。

    同时有个tricky的地方,python中规定非关键字传递的变量必须写在关键字传递变量的前面,所以混合使用*和**时肯定时*形参在**形参的前面。

    此外,在进行函数调用时,与之配套的就有个被称为解包裹的方式:

    上面代码的输出与前面一致。

    把元组或字典作为参数传入时,如果要适配包裹形式的形参定义(如上面将h传给*a,k传给**b),按照元组用*,字典用**的方式“解包裹”传递即可。

    实际上,在调用f时使用*,是为了提醒Python:我想要把实参h拆成分散的2个元素c和d,进行分别传递(所有上面代码中的f定义成def f(arg1,arg2,**b)也是可以的,这样arg1会获得3这个值而arg2会获得4这个值)。**同理类似。另外,解包裹时*对于列表([]定义的为列表,()定义的为元组)也适用。

    展开全文
  • python的参数传递机制具有值传递(int、float等值数据类型)和引用传递(以字典、列表等非值对象数据类型为代表)两种基本机制以及方便的关键字传递特性(直接使用函数的形参名指定实参的传递目标,如函数定义为def f(a,b...

    5ce6406a73f8e937.jpg

    python的参数传递机制具有值传递(int、float等值数据类型)和引用传递(以字典、列表等非值对象数据类型为代表)两种基本机制以及方便的关键字传递特性(直接使用函数的形参名指定实参的传递目标,如函数定义为def f(a,b,c),那么在调用时可以采用f(b=1,c=2,a=3)的指定形参目标的传递方式,而不必拘泥于c语言之类的形参和实参按位置对应)除此之外,python中还允许包裹方式的参数传递,这为不确定参数个数和参数类型的函数调用提供了基础。

    例如:def f(*a,**b),包裹参数传递的实现是在定义函数时在形参前面加上*或**,*所对应的形参(如上面的a)会被解释为一个元组(tuple,而**所对应的形参(如上面的b)会被解释为一个字典。具体调用时参数的传递见下面的代码:

    1558593729851589.png

    上面代码的运行结果是:

    (3, 4)

    {'n': 2, 'm': 1}

    可见,对于不使用关键字传递的变量,会被作为元组的一部分传递给*a,而使用关键字传递的变量作为字典的一部分传递给了**b。

    同时有个tricky的地方,python中规定非关键字传递的变量必须写在关键字传递变量的前面,所以混合使用*和**时肯定时*形参在**形参的前面。

    此外,在进行函数调用时,与之配套的就有个被称为解包裹的方式:

    1558593876365684.png

    上面代码的输出与前面一致。

    把元组或字典作为参数传入时,如果要适配包裹形式的形参定义(如上面将h传给*a,k传给**b),按照元组用*,字典用**的方式“解包裹”传递即可。

    实际上,在调用f时使用*,是为了提醒Python:我想要把实参h拆成分散的2个元素c和d,进行分别传递(所有上面代码中的f定义成def f(arg1,arg2,**b)也是可以的,这样arg1会获得3这个值而arg2会获得4这个值)。**同理类似。另外,解包裹时*对于列表([]定义的为列表,()定义的为元组)也适用。

    1558593926980327.png

    展开全文
  • 前言平常我们在别人写好的python包的时候,在cmd输入xx -h就能查看到帮助信息,...argv获取参数Python 中也可以所用 sys 的 sys.argv 来获取命令行参数:sys.argv 是命令行参数列表。len(sys.argv) 是命令行参数...
  • C语言的带参数的baimain函数格du式为main(int argc,char* argv[]),其中zhiargc为参数个数加1,argv为参数列表,dao从zhuanargv[1]开始。编译后生成可执shu行文件,可以在执行的程序后加参数,比如编译一个程序为...
  • Python 的内建标准类型一种分类标准是分为可变类型与不可变类型:可变类型:列表、字典不可变类型:数字、字符串、元组因为变量保存的实际都是对象的引用,所以在给一个不可变类型(比如 int)的变量 a 赋新值的...
  • 命令模式使用场景及定义 命令模式常见的使用场景是:时候需要向某些对象发送请求,但是并不知道请求的接受者是谁,也不知道请求的具体操作是什么.此时希望一种松耦合的方式来设计程序,使得请求的发送者和 ...FZU ...
  • a 声明时的参数列表什么也没有,那调用的时候把b方法名放进去干什么? 是不是回调函数, 当A执行完毕后,以返货结果为B的参数调用B? [b]问题补充:[/b] 看了楼下的说法,可奇怪的是公司那个方法就是什么也没写啊 ...
  • python函数的默认参数...那为什么这个警告呢?那是因为我们了可变类型进行默认参数的定义。可变类型和不可变类型可变类型(mutable):列表,字典不可变类型(unmutable):数字,字符串,元组定义可变类型会...
  • 再谈参数列表

    2007-11-12 21:12:00
    实践证明,这种做法是正确的,只是有的时候,过长的参数列表让代码看起来不舒服(不是有编码规范吗,规定参数列表中的参数不能超过5个)。但是对于降低代码的bug产出率来说,这点不舒服是必须忍受的,哪里有什么便宜...
  • 我们在写可变参数列表函数之前,先来了解一下什么是可变参数列表函数。 我们在c语言编程中有时会遇到 一些参数个数可变的函数,例如printf()函数,其函数原型为: int printf(const char* format,…); 它...
  • python函数的默认参数...那为什么这个警告呢?那是因为我们了可变类型进行默认参数的定义。可变类型和不可变类型可变类型(mutable):列表,字典不可变类型(unmutable):数字,字符串,元组定义可变类型会...
  • 一、什么是可变参数列表?  我相信只要学过C语言,就一定过 scanf() 和 printf() 两个标准库函数。过的朋友都知道,这两个函数功能强大无比,能输入输出各种各样类型的东西!scanf() 能支持整型、浮点型、字符...
  • params 有什么用

    2019-12-31 19:55:54
    params在方法成员的参数列表中使用,为该方法提供了参数个数可变的能力,也就是可变的方法参数也可称为数组型参数 适用于方法的参数个数不知的情况下,用于传递大量的数几何参数;当使用数组参数是,可通过使用...
  • 在类构造函数中,不在函数体内对变量赋值,而在参数列表后,跟一个冒号和初始化列表。 初始化和赋值对内置类型的成员没有什么大的区别,像上面的人一个构造函数都可以。对非内置类型成员变量,为了避免两次构造,...
  • Python 的内建标准类型一种分类标准是分为可变类型与不可变类型:可变类型:列表、字典不可变类型:数字、字符串、元组因为变量保存的实际都是对象的引用,所以在给一个不可变类型(比如 int)的变量 a 赋新值的时候...
  • 一个很经典的笑话:三个月之前,只有我和上帝知道这代码是干什么的。现在,只有上帝知道了。在Python中,不知道函数参数类型是一个很正常的事情,特别是在一个大项目里。我见过有些项目里,每一个函数体的前十几行...
  • 假设你你的清单table = [[1, 2, 3], [10, 20, 30], [100, 200, 300]]您可以使用zip转置它,并将原始列表作为参数列表传递(星号做什么):transposed = zip(*table): [(1, 10, 100), (2, 20, 200), (3, 30, 300)]要...
  • Python 的内建标准类型一种分类标准是分为可变类型与不可变类型: 可变类型:列表、字典 不可变类型:数字、字符串、元组 因为变量保存的实际都是对象的引用,所以在给一个不可变类型(比如 int)的变量 a 赋新...
  • 今天朋友在问我 Nginx 源码来安装时候哪些编译的参数,常用的参数有哪些,它们又分别代表什么意思。其实用 ./configure –help 就可以看出来它哪里编译的参数,不过那个朋友的英文不是很好,OwnLinux 有幸...
  • params 有什么用

    2013-01-24 17:46:47
    params 有什么用? 答: params 关键字在方法成员的参数列表中使用,为该方法提供了参数个数可变的能力 它在只能出现一次并且不能在其后再有参数定义,之前可以 示例: Codeusing System;using System....
  • 从上面代码中可以看出,函数的打印的是同一个列表对象numbers,因为他们的id值是一样的,只不过是列表中的元素在变化。为什么会这样呢?这要从函数的特性说起,在 Python 中,函数是第一类对象(function is the ...
  • C#-params 有什么用

    2016-06-20 09:38:00
    C#-params 有什么用? params 关键字在方法成员的参数列表中使用,为该方法提供了参数个数可变的能力 它在只能出现一次并且不能在其后再有参数定义,之前可以 示例: using System; using System....
  • 从上面代码中可以看出,函数的打印的是同一个列表对象numbers,因为他们的id值是一样的,只不过是列表中的元素在变化。为什么会这样呢?这要从函数的特性说起,在 Python 中,函数是第一类对象(function is the ...
  • 假如要写一个函数(求任意多个整数的平均值),参数列表不确定时,我们平时的固定的参数列表是存在很多隐患的,所以,就了stdarg宏----&gt;可变参数列表是通过他来实现的,头文件stdarg.h,他是标准库的一...
  • 从上面代码中可以看出,函数的打印的是同一个列表对象numbers,因为他们的id值是一样的,只不过是列表中的元素在变化。为什么会这样呢?这要从函数的特性说起,在 Python 中,函数是第一类对象(function is the ...
  • Python 的内建标准类型一种分类标准是分为可变类型与不可变类型:可变类型:列表、字典不可变类型:数字、字符串、元组因为变量保存的实际都是对象的引用,所以在给一个不可变类型(比如 int)的变量 a 赋新值的时候...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 958
精华内容 383
关键字:

参数列表有什么用