三、函数及参数类型

1.函数

  1.1 python 传不可变对象实例

  1.2python 传可变对象实例

2.参数

  2.1 必需参数/位置参数

  2.2 关键字参数

  2.3 默认参数

  2.4 不定长参数

 

 

1.函数

def 函数名(参数列表):

    函数体

def max(a,b):
    if a>b:
        return a
    else:
        return b

参数传递的类型可分为不可变对象实例和可变对象实例。

不可变对象实例

  数字、字符串、元组,如数字,变量赋值 a=5 后再赋值 a=10,这里实际是新生成一个 int 值对象 10,再让 a 指向它,而 5 被丢弃,不是改变 a 的值,相当于新生成了 a。
可变对象实例

  列表、集合、字典 ,如变量赋值 la=[1,2,3,4] 后再赋值 la[2]=5 则是将 list la 的第三个元素值更改,本身la没有动,只是其内部的一部分值被修改了

 

1.1 python 传不可变对象实例

def change(a):
    print(id(a)) # 指向的是同一个对象
    a=20
    print(id(a)) #指向一个新对象
    
a=10
print(id(a))
change(a)
print(id(a))

结果:
2247976026640
2247976026640
2247976026960
2247976026640

 

1.2 python 传可变对象实例

def change1(mylist):
    mylist1.append([4,5,6])   #append() 添加元素
    print('函数内取值',mylist1)   
    
mylist1=[1,2,3]
change1(mylist1)
print('函数外取值:',mylist1)   

结果:
[1, 2, 3, [4, 5, 6]]
[1, 2, 3, [4, 5, 6]]

 

 

2.参数

调用函数的参数可分为以下几种:

  必需参数/位置参数

  关键字参数

  默认参数

  不定长参数

 

2.1 必需参数/位置参数

def power(x):    #x是位置参数
    return x * x
    
>>>power(5)
25
>>>power()     #报错,没有传递参数


def power(x,n):    #x,n都是位置参数
    num=1
    for i in range(1,n+1):
        num*=x
    print(num)

>>>power(5,4)
625

 

2.2 关键字参数

关键字参数指的是调用时实参以key=value形式传入,如:

def pf(str):
    print(str)

pf(str='hello')   #str='hello'即为关键字参数

def person(name,age):
    print('name=',name)
    print('age=',age)
    
person(age=15,name='Sam')  #函数参数的使用不需要使用指定顺序

 

当函数中形参为 **name 形式时,接收一个字典,函数调用的实参就要用关键字参数

def person(name, age, **kw):
    print('name=',name)
    print('age=',age)
    for i in kw:
        print(kw.key,'=',kw.value)

person('Sam',31,job=doctor,city='NewYork')  #job=doctor,city='NewYork' 就是关键字参数
person('Susan',25)    #给不定长参数kw未传入值

关键字参数有什么用?它可以扩展函数的功能。比如,在person函数里,我们保证能接收到name和age这两个参数,但是,如果调用者愿意提供更多的参数,我们也能收到。试想你正在做一个用户注册的功能,除了用户名和年龄是必填项外,其他都是可选项,利用关键字参数来定义这个函数就能满足注册的需求。

 

如希望调用是传入job和city,只能在函数内部检查kw得知,使用以下:

def person(name, age, **kw):
    if 'city' in kw:
        # 有city参数
        pass
    if 'job' in kw:
        # 有job参数
        pass
    print('name:', name, 'age:', age, 'other:', kw)

要想限制关键字参数的名字,就可以用命名关键字参数,命名关键字在函数定义中出现,表明函数调用时需以关键字参数传入,在参数名称前加*或*不定长参数名,*或*不定长参数名之后的参数就是命名关键字参数。

区别:

关键字参数指的是函数调用中的参数,即实参以key=value形式传入;

而命名关键字指的是函数定义中的参数,即形参,通过前面加*或*不定长参数名,旨在说明*或*不定长参数名之后的参数在函数调用中要使用关键字参数(即key=value形式)传入;
如:

def person(name, age,*,job,city):    #job和city前面加*,这时job和city就变成了命名关键字参数,那么在函数调用的时候job和city要以关键字参数形式传入
如:person('Sam',31,job=doctor,city='NewYork')   #job=doctor,city='NewYork' 以关键字形式传入

函数的形参也可以采用不定长参数和命名关键字参数,如:

def person(name, age,*args,job,city):    #*args是不定长参数,job,city是命名关键字参数,代表调用时要传入job和city字段,且以关键字参数传入
    print(name, age,job,city)


person('Lisa',27,'168cm',job='teacher',city='Lindon')   #命名关键字参数job和city必须传入参数名job=和city=,否则报错
person('Lisa',27,'168cm','teacher','Lindon')    #'teacher','Lindon'以位置参数传入,未以关键字参数传入,报错

命名关键字也可以有缺省值,如:

def person(name, age,*,job='engineer',city):    #job='engineer'是一个默认参数,调用时可不传入
    print(name, age,job,city)
    
person('Lisa',27,city='Lindon')     #调用时job未传入

 

2.3 默认参数

默认参数是在函数的参数(即形参)中以key=value给定了默认参数,如age=6,默认参数要指向不变对象,调用时可以给这个默认参数传值,也可以不传,使用默认参数。

如学生注册信息:
def enroll(name, gender, age=6, city='Beijing'): #age=6,city='Beijing' 就是默认参数 print('name:', name) print('gender:', gender) print('age:', age) print('city:', city)

大多数学生注册时不需要提供年龄和城市,只提供必须的两个参数:
>>> enroll('Sarah', 'F')
name: Sarah
gender: F
age: 6
city: Beijing

只有与默认参数不符的学生才需要提供额外的信息:

enroll('Bob', 'M', 7)
enroll('Adam', 'M', city='Tianjin')

优点:默认参数降低了函数调用的难度,而一旦需要更复杂的调用时,又可以传递更多的参数来实现。无论是简单调用还是复杂调用,函数只需要定义一个。

设置默认参数时,有几点要注意:

一是必选参数在前,默认参数在后,否则Python的解释器会报错。

二是如何设置默认参数。

当函数有多个参数时,把变化大的参数放前面,变化小的参数放后面。变化小的参数就可以作为默认参数。

有多个默认参数时,调用的时候,既可以按顺序提供默认参数,如enroll('Bob', 'M', 7),传了name,geder和age,age使用传的参数,不使用默认参数6,city没有传,使用默认参数'Beijing';

也可以不按顺序提供部分默认参数。当不按顺序提供部分默认参数时,需要把参数名写上。比如调用enroll('Adam', 'M', city='Tianjin'),传了name,geder和city,age没有传,使用默认参数6

默认参数必须指向不变对象!

否则可能出现以下情况:

def add_end(L=[]):
    L.append('END')
    return L

正常调用:

>>> add_end([1, 2, 3])
[1, 2, 3, 'END']
>>> add_end(['x', 'y', 'z'])
['x', 'y', 'z', 'END']

使用默认参数多次调用:

>>> add_end()
['END']
>>> add_end()
['END', 'END']
>>> add_end()
['END', 'END', 'END']

原因分析:

Python函数在定义的时候,默认参数L的值就被计算出来了,即[],因为默认参数L也是一个变量,它指向对象[],每次调用该函数,如果改变了L的内容,则下次调用时,默认参数的内容就变了,不再是函数定义时的[]了。

可如下调用,解决该问题:

def add_end(L=None):
    L.append('END')
    return L

多次调用: >>> add_end() ['END'] >>> add_end() ['END'] >>> add_end() ['END']

 

2.4 不定长参数

 可变参数就是传入的参数个数是可变的,在函数的参数(即形参)前加*即表示可变参数,调用是可变参数可传入多个或0个。

 

 加了星号 * 的参数会以元组(tuple)的形式导入

def printinfo(arg1,*vartuple ): # 加了星号 * 的参数会以元组(tuple)的形式导入,存放所有未命名的变量参数
  print('arg1=',arg1)       #arg1= 4
  print('vartuple =',vartuple )      #arg2= (5, 6)
printinfo(4,5,6)


def printinfo(arg1,*vartuple ):      # 加了星号 * 的参数会以元组(tuple)的形式导入,存放所有未命名的变量参数
  print('arg1=',arg1)      #arg1= 4
  for i in vartuple:
    print(i)
printinfo(4)       #如果在函数调用时没有指定参数,它就是一个空元组。我们也可以不向函数传递未命名的变量
printinfo(4,5,6)

 

加了两个星号 ** 的参数会以字典的形式导入
def printinfo(arg1,**vardict):       # 加了两个星号 ** 的参数会以字典的形式导入
  print('arg1=',arg1)       #arg1= 1
  print('vardict =',vardict )       #vardict = {'a': 2, 'b': 3}
printinfo(1, a=2,b=3)
如传参是个list或tuple,可传参时使用*列表名/元组名
def printinfo(arg1,*vartuple ): # 加了星号 * 的参数会以元组(tuple)的形式导入,存放所有未命名的变量参数
  print('arg1=',arg1)       #arg1= 4
  print('vartuple =',vartuple )      #arg2= (5, 6)
nums=[4,5,6]
printinfo(*nums)   #传参是list

nums1=(1,2,3)
printinfo(*nums1)   #传参是tuple


本文来自于以下文章的学习笔记:
https://www.liaoxuefeng.com/wiki/1016959663602400/1017261630425888
https://www.runoob.com/python3/python3-function.html
posted @ 2023-12-25 13:51  紫蕈  阅读(11)  评论(0编辑  收藏  举报