形参和实参

  • 形参即形式参数,函数完成其工作时所需的信息。形参不占用内存空间,只有在被调用时才会占用内存空间,调用完了即被释放。
  • 实参即实际参数,调用函数时传给函数的信息。
# -*- coding: utf-8 -*-

def main(name):      # name 即为形参
    print "hello world %s" % name
    print "hello world {name}".format(name=name)
    return name

main("python")       # python 即为实参

上述而言:在调用函数并传入参数即main("python"),将实参"python"传递给函数main(),这个值就被存储在形参name中。 

函数的参数传递(实参的传递方式)

  • 位置传参:在调用函数进行传参时,实际参数(实参)与形式参数(形参)的对应关系是按照位置来依次对应的。
  • 序列传参:在调用函数进行传参时,实参为序列,用"*"将序列拆解后再进行位置传参。实参和形参通过序列传递和匹配。
  • 关键字传参:在调用函数进行传参时,按照形参的名称给形参赋值,即传递给函数的是键值对。实参和形参按名称进行匹配。
  • 字典关键字传参:在调用函数进行传参时,实参为字典,用"**"将字典拆解后再进行关键字传参。

位置传参

# 位置传参,实参与形参需要一一对应,不可多也不可少。
def main(name, age, hobby):
    content = "My name is %s,I'm %d years old,my hobby is %s" % (name, age, hobby)
    return content

content = main("张三", 26, "playgame")

序列传参

# 序列传参,序列里的元素必须和形参的数量保持一致。将序列拆解后再按照位置传参方式进行传参。
def main(name, age, hobby):
    content = "My name is %s,I'm %d years old,my hobby is %s" % (name, age, hobby)
    return content

info = ["张三", 26, "playgame"]
content = main(info[0], info[1], info[2])    # 这是位置传参,实参的值与形参的值按照顺序一一对应
content = main(*info)                        # 这是序列传参,将info拆解后再依次传入 name="张三"  age=26  hobby="playgame"

关键字传参

# 关键字传参,实参与形参无需一一对应,不可多也不可少。实参和形参按照形参名进行匹配,可以不按照位置进行匹配。
def main(name, age, hobby):
    content = "My name is %s,I'm %d years old,my hobby is %s" % (name, age, hobby)
    return content

content = main(age=28, name="王五", hobby="fishing")  # 在实参中的将名称和值关联起来,所以在传入时无需考虑顺序。

字典关键字传参

# 字典关键字传参,函数括号里不能直接写字典,前面应该加上 "**" 表示拆解字典。
# 字典的键名要在形参中存在且和形参名必须一致。字典的键名必须为字符串。
def main(name, age, hobby):
    content = "My name is %s,I'm %d years old,my hobby is %s" % (name, age, hobby)
    return content

info = {"age": 28, "name": "王五", "hobby": "fishing"}
content = main(**info)
content = main(**{"age": 28, "name": "王五", "hobby": "fishing"})

以上传参方式综合传参:函数的传参方式在能确定形参能唯一匹配到相应实参的情况下可以任意组合

位置传参和关键字传参混合使用:在没有参数组(即没有*args和**kwargs)的情况下,实参的数量必须与形参的数量一致。

def main(name, age, hobby):
    content = "My name is %s,I'm %d years old,my hobby is %s" % (name, age, hobby)
    return content

# content = main(name="张三", 28, hobby="fishing")     # 报错:位置传参必须写在关键字传参的左边
# content = main("张三", 28, age="fishing")            # 报错:同一个参数不能两次或者多次传值,只能传一次
content = main("张三", age=28, hobby="fishing")

四种传参混在一起使用:通常位置传参和序列传参先传递,其次是关键字传参和字典关键字传参。

def main(name, sex, age, score, hobby):
    print name, sex, age, score, hobby
    return "hello python success!!"

con = main("张三", *["男", 28], hobby="fishing", **{"score": 90})

函数的形参定义方式(形参的接收方式)

  • 位置形参:上面的示例是实参的传递方式,形参全是位置形参。上面是传递参数(实参),下面是接收参数(形参)。
  • 单星号元组形参:接收传入的多余的位置参数,被args接收。
  • 双星号字典形参:接收传入的多余的关键字参数,被kwargs接收。

位置形参

# 所有的形参全都一一列举出来
def 函数名(形参名1,形参名2,...,形参名n):
    语句块

单星号元组形参

def 函数名(*args):
    语句块

def main(name, *args):
    print name, args, type(args)
    return "success!!!"

main("张三", "男", "playgame")
main("张三", {"sex": "男"}, "dancing")   # 即使传入字典,字典当成整体也会以元组的方式被接收
main("张三", ["hello", "world"], "dancing")
main("张三", *["hello", "world"])       # 相当于遍历该列表,逐个添加至列表并且转为元组,*args接收。
main("张三", *"hello")                  # 相当于遍历该字符串,逐个添加至列表并且转为元组,*args接收。

# *args 表示创建一个名为 args 的空元组,该元组可接受任意多个外界传入的非关键字实参。
# *args 将多于的实参,以位置参数的方式传入,以元组的形式接收。保存在args元组中。*args名称可以自己随意取,如*word。
# 参数收集的本质就是一个元组, Python 会将传给 args 参数的多个值收集成一个元组,以元组为对象进行参数传递。
# 输出为:
# 张三  ('男', 'playgame')  <type 'tuple'>
# 张三  ({'sex': '男'}, 'dancing')  <type 'tuple'>
# 张三  (['hello', 'world'], 'dancing')  <type 'tuple'>
# 张三  ('hello', 'world')  <type 'tuple'>
# 张三  ('h', 'e', 'l', 'l', 'o')  <type 'tuple'>

双星号字典形参

def 函数名(**kwargs):
    语句块

def main(name, **kwargs):
    print name, kwargs, type(kwargs)
    return "success!!!"

main("张三", sex="男", age=28)
main(name="张三", sex="男", age=28)
main(name="张三", **{"sex": "男", "age": 28})
# **kwargs 表示创建一个名为 kwargs 的空字典,该字典可接受任意多个外界传入的关键字实参。
# **kwargs 将多于的实参,以关键字参数的形式传入,以字典的形式接收。保存在kwargs字典中。
# 输出为:
# 张三  {'age': 28, 'sex': '\xe7\x94\xb7'}  <type 'dict'>
# 张三  {'age': 28, 'sex': '\xe7\x94\xb7'}  <type 'dict'>
# 张三  {'age': 28, 'sex': '\xe7\x94\xb7'}  <type 'dict'>

单星号元组形参与双星号字典形参混合使用

# 当在函数定义参数时,同时定义*args与**kwargs时,可以接收在调用函数时传入的任何参数(任意位置传参和关键字传参)。
# 多余的位置参数,传入函数,以元组的方式被存储在*args中。多余的关键字参数,传入函数,以字典的方式被存储在**kwargs中。
def func(*args, **kwargs):
    pass

def main(x, y, *args, **kwargs):
    print x, y                    # 结果: 100 200
    print args, type(args)        # 结果: (300, ['hello', 'python'])    <type 'tuple'>
    print kwargs, type(kwargs)    # 结果: {'age': 28, 'sex': '\xe7\x94\xb7'}  <type 'dict'>
    return "success!!!"

main(100, 200, 300, ["hello","python"], age=28, sex="男")
def main(a, b, *args, **kwargs):
    print a,b         # 结果:100 200
    print args        # 结果:(300, 'A', 'B')
    print kwargs      # 结果:{'c': 'C', 'd': 'D'}

main(100, 200, 300, *"AB", **{"c": "C", "d": "D"})

函数的缺省参数(默认参数)

定义函数时我们可以给参数传递默认值,当调用函数时没有传递该参数值时使用默认参数值。带默认值的参数称为默认参数,无默认值的参数称为必需参数,调用函数时必需参数必填,默认参数选填。

缺省规则

  • 缺省参数必须自右至左依次存在。即默认参数一定在必需参数之后。即 score 在 name 之后。
  • 缺省参数可以有0个,1个,多个,甚至全部都是缺省参数。
  • 缺省参数的绑定对象存在于函数内,同函数的生命周期一致。
  • 函数体里面如果对缺省参数操作了,则会保存,下次调用时候,是保存的最新的了。
def 函数名(形参名1 = 默认实参1,形参名2 = 默认实参2,...):
    语句块

def main(name, score=60, *args, **kwargs):
    print name, score, args, kwargs
    return "success!!!"

main("张三", sex="男")          # 不给默认参数传值时,使用默认参数值
main("张三", 80, sex="男")      # 当给默认参数传值时,则覆盖
main("张三", 80, 90, sex="男")  # 多余的值用*args 和 **kwargs 接收
# 输出为:
# 张三  60  ()  {'sex': '\xe7\x94\xb7'}
# 张三  80  ()  {'sex': '\xe7\x94\xb7'}
# 张三  80  (90,)  {'sex': '\xe7\x94\xb7'}
def main(a, lst=[]):
    lst.append(a)
    print(lst)
l = [1, 2, 3]
main(5, l)   # 结果:[1, 2, 3, 5]
main(6, l)   # 结果:[1, 2, 3, 5, 6]
main(1.1)    # 结果:[1.1]
main(2.2)    # 结果:[1.1, 2.2]