python可变參数调用函数问题

一直使用python实现一些想法,近期在使用python的过程中出现这样一个需求,定义了一个函数。第一个是普通參数。第二个是默认參数,后面还有可变參数,在最初学习python的时候,都知道非keyword可变參数和keyword可变參数两种,调用的方式或许多种多样,这里主要提出一个比較隐含的问题。并将各种可能出现的情况进行了探讨。

函数声明格式

python尽管不支持函数重载,可是通过对函数參数的众多特性的支持基本弥补了。

函数声明的通式例如以下:

def func(argv1,argv2...[,argv_d = default1,...]        [,*var_argv][,**var_key_argv])

这是python函数声明的通式。首先是普通參数若干个。也能够没有,接着是带默认值的參数。然后是非keyword可变參数,最后是keyword可变參数。这为python提供的强大函数调用奠定了基础。

函数调用

正是在函数调用的过程中遇到了问题。为了说明。我定义了一个例如以下的函数进行说明:

def f1(a,b=1,*var): print a,‘\t‘,b,‘\t‘,var
def f2(a,b=1,**var): print a,‘\t‘,v,‘\t‘,var

首先普通參数能够使用按位置的方式调用,同一时候能够使用按形參keyword调用。默认值參数也是使用位置方式匹配或者keyword调用。实比例如以下:

这里没有使用后面的可变參数。一切都没有问题。

问题是。本人遇到的一个需求是,默认參数须要就是使用默认值调用。同一时候还有可变參数,并且是非keyword參数,那么调用时就会出现以下的情况:

能够看到,通过非keyword可变參数传入參数之后。python会默认把非keyword可变參数的前面若干个(这里是1个)当做默认參数,这里是由于我没有提供默认參数b的值,正是这个原因,在我的程序中一直没发现。

后来自习思考一下。发现Python解释器做出这种决定还是有一定的道理的,由于非keyword可变參数是默认參数之后的若干个參数。而在调用的时候由于没有传入默认參数的值。Python无法推断究竟从哪里開始是可变參数,因此在没有传入默认參数的值时,就依次从非keyword參数(调用者觉得的)中依照顺序抽取去当做默认參数的值,这从側面论证了非keyword可变參数在python内部是和普通參数默认參数一并处理的

尽管上述调用有些极端,可是确实会出现这种需求,那么能够使用keyword可变參数进行替换,上述问题就能够攻克了,由于解释器是能够差别keyword參数和默认參数的,调用例如以下:

在使用keyword可变參数时,另一个重要问题就是,keyword參数的键值不能有普通參数或者默认參数的參数名反复,这从側面论证了,python对keyword调用和keyword可变參数在内部都是经过同一个字典保存的,因此不能有反复的键。调用例如以下:

上述遇到的问题是在实际操作过程中遇到的,一般从各种教程、书本学习python都仅仅是说明上述的函数声明和调用的方式。可是差点儿没有这种实际操作中可能遇到的点点滴滴,因此学习不论什么东西最好的方式就动手,这个真理永远不会变啦!

时间: 2024-12-18 23:50:41

python可变參数调用函数问题的相关文章

C语言利用va_list、va_start、va_end、va_arg宏定义可变參数的函数

在定义可变參数的函数之前,先来理解一下函数參数的传递原理: 1.函数參数是以栈这样的数据结构来存取的,在函数參数列表中,从右至左依次入栈. 2.參数的内存存放格式:參数的内存地址存放在内存的堆栈段中,在运行函数的时候,从最后一个(最右边)參数開始入栈.因此栈底高地址,栈顶低地址,举个样例说明一下: void test(int a, float b, char c); 那么,在调用test函数的时候,实參char c先进栈,然后是float b,最后才是int a,因此在内存中变量的存放次序是c-

c 语言函数可变參数的处理

/************************************************************************* > File Name: va_list.c > Author: zshh0604 > Mail: [email protected] > Created Time: 2014年10月14日 星期二 15时16分09秒 **********************************************************

可变參数学习笔记

一.什么是可变參数 我们在C语言编程中有时会遇到一些參数个数可变的函数,比如printf()函数,其函数原型为: int printf( const char* format, ...); 它除了有一个參数format固定以外,后面跟的參数的个数和类型是可变的(用三个点"-"做參数占位符),实际调用时能够有下面的形式: printf("%d",i); printf("%s",s); printf("the number is %d ,s

宏定义之二(连接符,可变參数,文件名称,行号,函数名)

宏的高级使用--##,__VA_ARGS__, __FILE__, __FUNCTION__等 转自 http://blog.csdn.net/yiya1989/article/details/7849588 先说一下本文中会提到的内容:##,__VA_ARGS__, __FILE__, __LINE__ , __FUNCTION__等 宏变量: 先举一个样例,会用到上面这些宏: [cpp] view plaincopy #define myprintf(...) printk("[lch]:F

java之 ------ 可变參数和卫条件

可变參数:适用于參数个数不确定.类型确定的情况,java把可变參数当做数组处理. 可变參数必须位于最后一项.当可变參数个数多于一个时,必将有一个不是最后一项,所以仅仅支持有一个可变參数. 可变參数的书写形式如: int add(int x,int ...args){  方法体 } ... 位于变量类型和变量名之间.前后有无空格都能够: 调用可变參数的方法时.编译器为该可变參数隐含创建一个数组,在方法体中以数组的形式訪问可变參数. 条件逻辑推断型的应用(模拟人工推理) /* 有人邀请A,B,C,D

iOS 处理方法中的可变參数

## iOS 处理方法中的可变參数 近期写了一个自己定义的对话框的demo,想模仿系统的UIAlertView的实现方式.对处理可变參数的时候,遇到了小问题,于是谷歌了一下.写下了处理问题的方法.记录下来,以备后需. 代码实现 - (instancetype)initWithTitle:(NSString *)title message:(NSString *)message delegate:(id)delegate cancelButtonTitle:(NSString *)cancelBu

可变參数列表

再c++里有函数重载.在c里有可变參数列表,用stdarg宏实现定义在<stdarg.h>的头文件里,当中有3个宏:va_start(va_list的变量名,省略号前最后一个有名字的參数)用于初始化,va_arg(va_list的变量名,可变參数类型)用于取出可变參数.va_end(va_list的变量名)用于表明结束取值.用va_list声明一个类型为va_list的变量如arg #include<stdio.h> #include<stdarg.h> float a

可变參数

C++中传递參数时,有时候不确定參数的数量,这时候能够使用可变參数.例如以下: 1.std::initializer_list C++11标准,使用方法类似vector,參数类型需同样.使用方法例如以下: #include <initializer_list> void  method(std::initializer_list<int> il) { for(auto i: il) { printf("%d", i) ; } } int _tmain(int a

java课堂练习之可变參数与卫条件

/* 有人邀请A,B,C,D,E,F 6个人參加一项会议,这6个人有些奇怪.由于他们有非常多要求,已知: 1)A,B两人至少有1人參加会议: 2)A,E,F 3人中有2人參加会议. 3)B和C两人一致决定,要么两人都去,要么两人都不去: 4)A,D两人中仅仅1人參加会议. 5)C,D两人中也仅仅要1人參加会议: 6)假设D不去,那么E也决定不去. 那么最后到底有哪几个人參加了会议呢? */ 可变參数必须位于最后一项. 当可变參数个数多于一个时.必将有一个不是最后一项.所以仅仅支持有一个可变參数.