精华内容
下载资源
问答
  • Python函数参数传递几种形式

    千次阅读 2019-10-14 23:13:34
    python函数参数传递几种形式前言位置传参序列传参(单星号元组传参)关键字传参字典关键字传参(双星号字典传参)混合传参函数的缺省参数结束 前言 莫听穿林打叶声,何妨吟啸且徐行。竹杖芒鞋轻胜马,谁怕?一蓑...

    前言

    莫听穿林打叶声,何妨吟啸且徐行。竹杖芒鞋轻胜马,谁怕?一蓑烟雨任平生。❤️

    位置传参

    位置传参:实际调用参数(实参) 的对应关系与形式参数(形参)的对应关系是按位置来依次对应的。

    	def fx(a, b, c):
    		pass
    	fx(1, 2, 3)
    

    序列传参(单星号元组传参)

    序列传参:在函数调用过程中,用 * 将序列拆解(或收集)后按位置进行传递的传参方式,。

    	def fx(a, b, c):
    		pass
    	t = (1, 2, 3)
    	fx(*t)
    
    	def fx(*args):
    		print(args[1])
    	fx(1, 2, 3, 4)
    	结果为:
    		2
    

    关键字传参

    关键字传参:实参和形参按名称进行匹配。

    	def fx(a, b, c):
    		pass
    	fx(c = 1, a = 2, b = 3)
    
    	def fx(address, sex, *, name, age):	# *后面代表这个参数调用时必须使用关键字的方式
    		print(address, sex, name, age)
    	fx("上海", "男", name="张三" ,age=18)
    
    	def fx(address, sex, *, name, age):	# *后面代表这个参数调用时必须使用关键字的方式
    		print(address, sex, name, age)
    	fx("上海", "男", **{"name":"张三","age":18})
    

    字典关键字传参(双星号字典传参)

    字典关键字传参:实参为字典,用**拆解字典(或收集关键字)后再进行关键字传参。

    	def fx(a, b, c):
    		pass
    	d = {'c': 33, 'b': 22, 'a': 11}
    	fx(**d)
    
    	def fx(**kwargs):
    	    print(kwargs)
            print(kwargs['c'])
    	fx(a=1, b="b", c=[1, 2, 3], d=True)
    	结果为:
    		{'a': 1, 'b': 'b', 'c': [1, 2, 3], 'd': True}
        	[1, 2, 3]
    

    说明:
    字典的键名和形参名必须一致;
    字典的键名必须为字符串;
    字典的键名要在形参中存在。

    混合传参

    混合传参实参顺序:通常位置传参和序列传参先传递,其次是关键字传参和字典关键字传参。

    	def fx(a, b, c, d, e, f):
    		pass
    	fx(10, *(20, 30), e=50, **{'d':40, 'f':60})
    

    混合传参形参顺序:自左至右为: 1. 位置形参;2. 星号元组形参;3. 命名关键字形参;4. 双星号字典形参。

    	def fx(a, b, *args, c, **kwargs):
    		print(c)
        	print(kwargs)
    	fx(100, 200, 300, 400,*"AB", **{'d':"D"}, c=100)
    	结果为:
    		100
    		{'d': 'D'}
    	fx(100, 200, 300, 400,*"AB", **{'d':"D", "c":"C"}, e=100)
    	结果为:
    		C
    		{'d': 'D', 'e': 100}
    

    函数的缺省参数

    函数的缺省参数:形参的默认值。
    说明:
    缺省参数在形参末尾依次存在;
    缺省参数可以有0个,1个,多个,甚至全部都有缺省参数;
    缺省参数的值同函数的生命周期一致。

    	def fx(name, age=1, address="不详"):
    	    print("我叫", name, '我今年:', age,'岁, 家庭住址:', address)
    	fx("张飞", 30, "中原")
    	fx("关羽", 35)
    	fx("赵云")
    	结果为:
    		我叫 张飞 我今年: 30, 家庭住址: 中原
    		我叫 关羽 我今年: 15, 家庭住址: 不详
    		我叫 赵云 我今年: 1, 家庭住址: 不详
    
    	def fx(a, lst=[]):	# 此示例来示意fn函数中lst绑定的缺省参数的列表的生命周期
    	    lst.append(a)
    	    print(lst)
    	L = [1,2,3,4]
    	fx(5, L)
    	fx(6, L)
    	fx(1)
    	fx(2)
    	结果为:
    		[1, 2, 3, 4, 5]
    		[1, 2, 3, 4, 5, 6]
    		[1]
    		[1, 2]
    

    结束

    我很荣幸你能看到这篇博客,个人水平有限,欢迎讨论留言。如果对您有启发,不妨点赞、分享和收藏。❤️

    展开全文
  • Python传入参数几种方法

    万次阅读 多人点赞 2018-03-20 18:04:13
    Python唯一支持的参数传递方式是『共享传参』(call by sharing) 多数面向对象语言都采用这一模式,包括Ruby、Smalltalk和Java(Java的引用类型是这样,基本类型按值传递) 共享传参是指函数的各个形式参数获得...

    Python传入参数的方法有:位置参数、默认参数、可变参数、关键字参数、和命名关键字参数、以及各种参数调用的组合


    写在前面

    Python唯一支持的参数传递方式是『共享传参』(call by sharing)

    多数面向对象语言都采用这一模式,包括Ruby、Smalltalk和Java(Java的引用类型是这样,基本类型按值传递)

    *共享传参是指函数的各个形式参数获得实参中各个引用的副本;也就是说,函数内部的形参是实参的别名(alias)

    这种方案的结果是,函数可能会修改作为参数传入的可变对象,但是无法修改那些对象的标识(即不能把一个对象替换为另一个对象)


    位置参数

    位置参数是最简单的传入参数的方式,在其它的语言中也常常被使用

    演示一:

    def func(a, b):
    	print(a+b)
    
    func(1, 2)	#3
    

    演示二:

    def power(x, n):
    	s = 1
    	while(n > 0):
    		n -= 1
    		s *= n
    	return s
    
    power(2, 3)	#8
    

    默认参数

    默认参数就是在调用函数的时候使用一些包含默认值的参数

    def power(x, n=2):
    	s = 1
    	while(n > 0):
    		n -= 1
    		s *= n
    	reutrn s
    
    power(3)	#9
    power(2, 3)	#8
    

    定义默认参数要牢记一点:默认参数必须指向不变对象!

    # 以下这个函数如果被多次调用会在默认添加多个END字符串
    def add_end(l = []):
    	l.append('END')
    	return l
    
    # 为了避免这个问题,应该把传入的默认参数设置为不可变的
    def add_end(l = None):
    	l = []
    	l.append('END')
    	return l
    

    可变参数

    可变参数就是允许在调用参数的时候传入多个(≥0个)参数(类似于列表、字典)

    #传入一个列表,严格地说这不是可变参数
    def calc(l):
    	sum = 0
    	for n in l:
    		sum += n
    	return sum
    
    >>> calc([1,2,3])
    7
    
    # 这才是可变参数,虽然在使用上和列表没有区别,但是参数nums接收到的是一个tuple(这些参数在传入时被自动组组装为一个元祖)
    def calc(*nums):
    	sum = 0
    	for n in nums:
    		sum += n
    	return sum
    
    >>> calc(1,2,3)
    7
    
    >>> my_ls = [1,2,3]
    >>> calc(*my_ls)
    7
    

    关键字参数

    可变参数允许传入0个~多个参数,而关键字参数允许在调用时以字典形式传入0个或多个参数(注意区别,一个是字典一个是列表);在传递参数时用等号(=)连接键和值

    # 用两个星号表示关键字参数
    def person_info(name, age, **kw):
    	print("name", name, "age", age, "other", kw)
    
    >>> person_info("Xiaoming", 12)
    name Xiaoming age 12 other{}
    >>> person_info("Dahuang", 35, city = "Beijing")
    name Dahuang age 35 other {'city':'Beijing'}
    

    命名关键字参数

    命名关键字参数在关键字参数的基础上限制传入的的关键字的变量名

    和普通关键字参数不同,命名关键字参数需要一个用来区分的分隔符*,它后面的参数被认为是命名关键字参数

    # 这里星号分割符后面的city、job是命名关键字参数
    person_info(name, age, *, city, job):
    	print(name, age, city, job)
    
    >>> person_info("Alex", 17, city = "Beijing", job = "Engineer")
    Alex 17 Beijing Engineer	#看来这里不再被自动组装为字典
    

    不过也有例外,如果参数中已经有一个可变参数的话,前面讲的星号分割符就不要写了(其实星号是写给Python解释器看的,如果一个星号也没有的话就无法区分命名关键字参数和位置参数了,而如果有一个星号即使来自变长参数就可以区分开来)

    # args是变长参数,而city和job是命名关键字参数
    person_info(name, age, *args, city, job):
    	print(name, age, args, city)
    
    >>> person_info("Liqiang", 43, "balabala", city = "Wuhan", job = "Coder")
    Liqiang 43 balabala Wuhan Coder
    

    参数组合

    总结一下,在Python中一种可以使用5中传递参数的方式(位置参数、默认参数、变长参数、关键字参数、命名关键字参数)

    注意,这些参数在书写时要遵循一定的顺序即:位置参数、默认参数、变长参数、关键字参数、命名关键字参数(和本文的行文顺序一致)

    def f1(a, b, c=0, *args, **kw):
    	print("a = ", a, "b = ", b, "args = ", args, "kw = ",kw)
    def f2(a, b, c=0, *, d, **kw):
    	print("a = ", a, "b = ", b, "c = ", c, "d = ", d, "kw = ", kw)
    
    >>> f1(1, 2)
    a = 1 b = 2 c = 0 args =() kw = {}
    >>> f1(1, 2, c=3)
    a = 1 b = 2 c = 3 args = () kw = {}
    >>> f1(1, 2, 3, 'a', 'b')
    a = 1 b = 2 c = 3 args = ('a', 'b') kw = {}
    >>> f1(1, 2, 3, 'a', 'b', x = 99)
    a = 1 b = 2 c = 3 args = ('a', 'b') kw = {'x':99}
    >>> f2(1, 2, d = 99, ext = None)
    a = 1 b =2 c = 0 d = 99 kw = {'ext':None}
    

    写在后面

    关于Python参数传递,有以下几点提请注意:

    1)参数的传递是通过自动将对象赋值给本地变量名来实现的
    函数参数在实际中只是Python赋值的另一个实例而已,因为引用可以是以指针的形式来实现的,所有的参数实际上都是通过指针进行传递的,作为参数被传递的对象从来不自动拷贝

    2)在函数内部的参数名的赋值不会影响调用者
    在函数运行时,在函数头部的参数名时一个新的、本地的变量名,这个变量名是在函数的本地作用域内的,函数参数名和调用者作用域中的变量是没有区别的

    3)改变函数的可变对象参数的值也许会对调用者有影响
    换句话说,因为参数是简单地赋值给传入的对象,函数就能够就地改变传入的可变对象,因此其结果会影响调用者;可变参数对函数来说可以做输入和输出的

    Python的通过赋值进行传递的机制与C++的引用参数选项不完全相同,但是实际中,它与C语言的参数传递模型相当类似:

    1)不可变参数“通过值”进行传递
    像整数和字符串这样的对象是不可变对象,它们通过对象引用而不是拷贝进行传递的,但是因为无论如何都不可能在原处改变不可变对象,实际的效果就很像创建了一份拷贝

    2)可变对象是通过“指针”进行传递的
    列表和字典这样的对象也是通过对象引用进行传递的,这一点与C语言使用指针传递数组很相似,可变对象能够在函数内部进行原处的改变,这一点和C数组很像

    这里写图片描述

    这里写图片描述

    总而言之,理解Python的变量、函数的关键就是理解『绑定』的概念——绑定就是绑定对象,理解了这一点就好办了(完)。

    展开全文
  • 1. 几种函数参数传递方式 '*': 取元组或列表整体作为参数传递(看后面代码例子更容易理解) '**': 取字典整体作为参数传递(看后面代码例子更容易理解) '*args': 接受元组作为函数参数 '**kwargs': 接受字典...

    1. 几种函数参数传递方式

    '*':			取元组或列表整体作为参数传递(看后面代码例子更容易理解)
    '**':			取字典整体作为参数传递(看后面代码例子更容易理解)
    '*args':		接受元组作为函数参数
    '**kwargs':		接受字典作为函数参数
    

    2. 函数示例来理解用法

    参数传递 " * " 代码示例

    >>> def fun(a,b,c):
    ...     print a,b,c
    ... 
    >>> fun(1, 2, 3)	# 普通的参数传递方式
    1 2 3				
    
    >>> l = [1, 2, 3]	# 定义一个列表
    >>> fun(*l)			# 采用 * 的方式传递参数
    1 2 3
    

    参数传递 " *args " 代码示例

    >>> def fun(*args):
    ...     print("args is: %s", args) 
    ... 
    >>> fun(11, 12, 13)		
    (11, 12, 13)		# 注意输出的是元组形式
    

    参数传递 " ** " 代码示例

    >>> def fun(a, b, c):
    ...     print a, b, c
    ... 
    >>> fun(1,5,7)
    1 5 7
    >>> fun(a=1,b=5,c=7)
    1 5 7
    >>> d={'b':5, 'c':7}	# 定义一个字典
    >>> fun(1, **d)			# ** 取字典的整体作为函数参数
    1 5 7
    

    参数传递 " **kwargs " 代码示例

    >>> def fun(a, **kwargs):
    ...     print a, kwargs
    ... 
    >>> fun(1, b=4, c=5)		# 普通参数传递和字典参数传递
    1 {'c': 5, 'b': 4}
    >>> fun(45, b=6, c=7, d=8)	# 普通参数传递和字典参数传递(不限制参数数量)
    45 {'c': 7, 'b': 6, 'd': 8}
    >>> fun(1, **{'b':2, 'c':34})	# 配合使用 ** 传递字典参数
    a is  1
    We expect kwargs 'b' and 'c' in this function
    b is  2
    c is  34
    

    3. “args” 和 "kwargs"应用场景

    在任何时候继承类和重写方法时,我们应当用到’*args’和’**kwargs’将接收到的位置参数和键值参数给父类方法。

    代码示例

    >>> # 先声明一个类,然后定义Model类中的save()方法
    >>> class Model(object):
    ...     def __init__(self, name):
    ...             self.name = name
    ...     def save(self, force_update=False, force_insert=False):
    ...             if force_update and force_insert:
    ...                     raise ValueError("Cannot perform both operations")
    ...             if force_update:
    ...                     print "Updated an existing record"
    ...             if force_insert:
    ...                     print "Created a new record"
    ...
    >>> # 定义一个新的类,继承上面的 Model类
    >>> class ChildModel(Model):
    ...     def save(self, *args, **kwargs):
    ...             if self.name=='abcd':		# 继承自父类Model的属性值
    ··· 					# 调用父类Model的 save() 方法
    ···						# 此时这可以进行方法的重写
    ...                     super(ChildModel, self).save(*args, **kwargs)	
    ...             else:
    ...                     return None
    ... 
    >>> # 实例化子类,并调用子类的 save() 方法
    >>> c = ChildModel('abcd')
    >>> c.save(force_insert=True)
    Created a new record
    >>> c.save(force_update=True)
    Updated an existing record
    
    展开全文
  • python函数参数传递几种方法 洗头用飘柔 2008-06-19 13:06:48 Python函数参数传递是通过“赋值”来传递的。但这条规则只回答了函数参数传递的“战略问题”,并没有回答“战术问题”,也就说没有回答怎么...

    python中函数参数传递的几种方法

    洗头用飘柔洗头用飘柔 2008-06-19 13:06:48
    Python中函数参数的传递是通过“赋值”来传递的。但这条规则只回答了函数参数传递的“战略问题”,并没有回答“战术问题”,也就说没有回答怎么赋值的问题。函数参数的使用可以分为两个方面,一是函数参数如何定义,二是函数在调用时的参数如何解析的。而后者又是由前者决定的。函数参数的定义有四种形式:

       1. F(arg1,arg2,...)
       2. F(arg2=<value>,arg3=<value>...)
       3. F(*arg1)
       4. F(**arg1)

    第1 种方式是最“传统”的方式:一个函数可以定义不限个数参数,参数(形式参数)放在跟在函数名后面的小括号中,各个参数之间以逗号隔开。用这种方式定义的函数在调用的时候也必须在函数名后的小括号中提供相等个数的值(实际参数),不能多也不能少,而且顺序还必须相同。也就是说形参和实参的个数必须一致,而且想给形参1的值必须是实参中的第一位,形参与实参之间是一一对应的关系,即“形参1=实参1 形参2=实参2...”。很明显这是一种非常不灵活的形式。比如:"def addOn(x,y): return x + y",这里定义的函数addOn,可以用addOn(1,2)的形式调用,意味着形参x将取值1,主将取值2。addOn(1,2,3)和addOn (1)都是错误的形式。
    第2种方式比第1种方式好一点,在定义的时候已经给各个形参定义了默认值。因此,在调用这种函数时,如果没有给对应的形式参数传递实参,那么这个形参就将使用默认值。比如:“def addOn(x=3,y=5): return x + y”,那么addOn(6,5)的调用形式表示形参x取值6,y取值5。此外,addOn(7)这个形式也是可以的,表示形参x取值7,y取默认值5。这时候会出现一个问题,如果想让x取默认值,用实参给y赋值怎么办?前面两种调用形式明显就不行了,这时就要用到Python中函数调用方法的另一大绝招 ──关健字赋值法。可以用addOn(y=6),这时表示x取默认值3,而y取值6。这种方式通过指定形式参数可以实现可以对形式参数进行“精确攻击”,一个副带的功能是可以不必遵守形式参数的前后顺序,比如:addOn(y=4,x=6),这也是可以的。这种通过形式参数进行定点赋值的方式对于用第1种方式定义的函数也是适用的。
    上面两种方式定义的形式参数的个数都是固定的,比如定义函数的时候如果定义了5个形参,那么在调用的时候最多也只能给它传递5个实参。但是在实际编程中并不能总是确定一个函数会有多少个参数。第3种方式就是用来应对这种情况的。它以一个*加上形参名的方式表示,这个函数实际参数是不一定的,可以是零个,也可以是N个。不管是多少个,在函数内部都被存放在以形参名为标识符的tuple中。比如:


    对这个函数的调用addOn() addOn(2) addOn(3,4,5,6)等等都是可以的。

    与第3种方式类似,形参名前面加了两个*表示,参数在函数内部将被存放在以形式名为标识符的dictionary中。这时候调用函数必须采用key1=value1、key2=value2...的形式。比如:

       1. def addOn(**arg):
       2. sum = 0
       3. if len(arg) == 0: return 0
       4. else:
       5. for x in arg.itervalues():
       6. sum += x
       7. return sum

    那么对这个函数的调用可以用addOn()或诸如addOn(x=4,y=5,k=6)等的方式调用。

    上面说了四种函数形式定义的方式以及他们的调用方式,是分开说的,其实这四种方式可以组合在一起形成复杂多样的形参定义形式。在定义或调用这种函数时,要遵循以下规则:

       1. arg=<value>必须在arg后
       2. *arg必须在arg=<value>后
       3. **arg必须在*arg后

    在函数调用过程中,形参赋值的过程是这样的:
    首先按顺序把“arg”这种形式的实参给对应的形参
    第二,把“arg=<value>”这种形式的实参赋值给形式
    第三,把多出来的“arg”这种形式的实参组成一个tuple给带一个星号的形参
    第四,把多出来的“key=value”这种形式的实参转为一个dictionary给带两个星号的形参。
    听起来好复杂,实际是是很简单的。很直观,来看例子:

       1. def test(x,y=5,*a,**b):
       2. print x,y,a,b

    就这么一个简单函数,来看看下面对这个函数调用会产生什么结果:
    test(1) ===> 1 5 () {}
    test(1,2) ===> 1 2 () {}
    test(1,2,3) ===> 1 2 (3,) {}
    test(1,2,3,4) ===> 1 2 (3,4)
    test(x=1) ===> 1 5 () {}
    test(x=1,y=1) ===> 1 1 () {}
    test(x=1,y=1,a=1) ===> 1 1 () {'a':1}
    test(x=1,y=1,a=1,b=1) ===> 1 1 () {'a':1,'b':1}
    test(1,y=1) ===> 1 1 () {}
    test(1,2,y=1) ===> 出错,说y给赋了多个值
    test(1,2,3,4,a=1) ===> 1 2 (3,4) {'a':1}

    test(1,2,3,4,k=1,t=2,o=3) ===> 1 2 (3,4) {'k':1,'t':2,'o':3}


    OK,目前为止,我们要定义一个函数的时候,必须要预先定义这个函数需要多少个参数(或者说可以接受多少个参数)。一般情况下这是没问题的,但是也有在定义函数的时候,不能知道参数个数的情况(想一想C语言里的printf函数),在Python里,带*的参数就是用来接受可变数量参数的。看一个例子
    def funcD(a, b, *c):
      print a
      print b
      print "length of c is: %d " % len(c)
      print c
    调用funcD(1, 2, 3, 4, 5, 6)结果是
    1
    2
    length of c is: 4
    (3, 4, 5, 6)
    我们看到,前面两个参数被a、b接受了,剩下的4个参数,全部被c接受了,c在这里是一个tuple。我们在调用funcD的时候,至少要传递2个参数,2个以上的参数,都放到c里了,如果只有两个参数,那么c就是一个empty tuple。

    好了,一颗星我们弄清楚了,下面轮到两颗星。

    上面的例子里,调用函数的时候,传递的参数都是根据位置来跟函数定义里的参数表匹配的,比如funcB(100, 99)和funcB(99, 100)的执行结果是不一样的。在Python里,还支持一种用关键字参数(keyword argument)调用函数的办法,也就是在调用函数的时候,明确指定参数值付给那个形参。比如还是上面的funcB(a, b),我们通过这两种方式调用
    funcB(a=100, b=99)

    funcB(b=99, a=100)
    结果跟funcB(100, 99)都是一样的,因为我们在使用关键字参数调用的时候,指定了把100赋值给a,99赋值给b。也就是说,关键字参数可以让我们在调用函数的时候打乱参数传递的顺序!

    另外,在函数调用中,可以混合使用基于位置匹配的参数和关键字参数,前题是先给出固定位置的参数,比如
    def funcE(a, b, c):
      print a
      print b
      print c
    调用funcE(100, 99, 98)和调用funcE(100, c=98, b=99)的结果是一样的。

    好了,经过以上铺垫,两颗星总算可以出场了:
    如果一个函数定义中的最后一个形参有 ** (双星号)前缀,所有正常形参之外的其他的关键字参数都将被放置在一个字典中传递给函数,比如:
    def funcF(a, **b):
      print a
      for x in b:
        print x + ": " + str(b[x])
    调用funcF(100, c='你好', b=200),执行结果
    100
    c: 你好
    b: 200
    大家可以看到,b是一个dict对象实例,它接受了关键字参数b和c。

    常规参数,*参数及**参数可以同时使用,具体怎么用?看看Python Reference Manual吧,关于Function definitions的那些章节。其实,笨想也能猜出来啊,o(∩_∩)o...



    展开全文
  • 函数调用时,实参默认按照位置顺序传递,需要个数的和形参匹配,按位置传递参数,称为:“位置参数”。 例子: def one(a,b,c): print(a,b,c) one(1,2,3) one(1,2) #这里报错,位置参数不匹配 返回值: &...
  • 形参:函数定义使用的参数 实参:函数调用使用的参数 1、位置实参:参数的先后顺序很重要 def func(first, last): print("fisrt: " + first, ",last: " + last + "\n") func('a', ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 75,458
精华内容 30,183
关键字:

python函数参数传递的几种形式

python 订阅