初见函数-函数的参数类型

一、函数的介绍

  当我们写一个程序,如果相同的功能需要重复100次。

  在没有函数的情况下,我们需要复制粘贴100次。整个脚本文件就变得非常庞大。

  如果需要修改这个功能,那我们也需要修改100次。而且容易出错。 so  我们引进了函数。

    

1.1 定义函数

  一个函数最基本的组成部分: 

      关键字   def

      函数名  函数名要反应其意义,就是命名规范

      注释   代码规范,解释该函数的作用,以及参数的作用

      函数体  这个函数需要完成的逻辑功能。

      返回值  默认为None,可以不写。但是我们都会定义自己的返回值。注意:函数一遇到return 就会结束了,后面的代码就不会执行了(if  else 嵌套return)。

def 函数名(参数1,参数2,参数3,...):                   #函数名要能反映其意义
    '''注释'''
    函数体
    return 返回的值                   #

1.2  函数的运行过程与调用

1.2.1 调用

  函数名本质上就是函数的内存地址的标签

  调用: 函数名()         

    第一步: 先找到函数名 

    第二步: 根据找到的函数名,运行其中保存的代码

函数名其实就是一个变量,其中保存了 函数的代码。  加上一个() 就运行了其中保存的代码了。

1.2.2 运行过程  

1 x = 100
2 def add(a, b):
3     y = a + b
4     return y
5 su = add(x, 100)

  第一步: 把 x = 100 加载到内存中。

  第二步: 把函数名add 与其 对应的函数体代码  放在内存中。 注:其下的代码在这时候,是没有运行的,只是保存到变量中。

  第三步:直接到第5行。 在内存中,找到上一步,add函数名变量。遇到(),执行该函数变量的保存的代码。这一步涉及到传递参数的内容,在下面会讲解。

  第四步:遇到return,返回到第5行,给su 赋值。

1.3 函数的注释规范

def odd(a: int, b: '默认值'=3 ) -> '写返回值':
    "函数说明,介绍函数的功能,会添加到__doc__中,可使用三引号多行,en首单词首字母大些"
    return a + b

print(odd(3))

二、参数传递

 1 x = 10000
 2 
 3 def add(a, b):  # 实参 到 形参的传递,其实就是指向了同一块内存,有两个别名而已
 4     print('Before', id(a))
 5     a += 1  # a = a + 1  ,前面的a是局部变量a(执行这句生成),新的一块内存,  后面的a是全局的
 6     print('after', id(a))
 7 
 8 print('globle before', id(x))
 9 add(x, 2)
10 print('globle after', id(x))

三、 参数类型

  函数中参数可以分为  位置参数 、 默认参数 、不定长参数

  参数排序的规则: 位置参数-->*args-->默认参数-->**kwargs  否则,解释器进行语法分析的时候 直接报错。   

3.1 位置参数-必须传递参数

def mymax(x, y):
    the_max = x if x > y else y
    return the_max

maxnum = mymax()  # 此处不传参数
print(maxnum)

计算结果报错:
    maxnum = mymax()
TypeError: mymax() missing 2 required positional arguments: 'x' and 'y'

3.2 默认参数

  可以不传递参数,但是默认参数,只会计算一次(在第一次调用的时候,进行赋值),如果进行了赋值,则指向一块新的内存地址。

如下:

def func(a, b=[]): # b的默认值指向一个空的列表,每次不带默认值都会指向这块内存
    print(id(b), end='---')
    b.append(a)
    return b

print(func(1))  # 向默认的空列表里加入元素1 ,默认列表里已经是[1]
print(func(2))  # 向默认的列表里加入元素2,默认列表里已经是[1,2]

print(func(3, []))  # 向b指向新的一块内存地址的空列表里加入元素1 ,默认列表里还是[1,2]
print(func(4))  # 向默认的列表里加入元素4,默认列表里已经是[1,2,4]


运行结果:
4352862280---[1]
4352862280---[1, 2]
4352860872---[3]
4352862280---[1, 2, 4]

3.3 关键字参数

  关键字参数是针对 函数的调用来讲的。 使用关键字参数来调用函数,就可以不按照次序来传递。

def mymax(x, y):
    # 此时x = 20,y = 10
    the_max = x if x > y else y
    return the_max

maxsum = mymax(y=10, x=20)               # 关键字传参,不按照定义的次序
print(maxsum)

计算结果
20

3.4 不定长参数 *args 

  不定长参数 *args ,接受位置参数,在函数中会转换为一个元祖。

def func(*args): #这种定义会把传递的参数包成元组
        print(args,type(args))

func(10,20)
#结果:
#(10, 20) <class 'tuple'>

 举一个相反的例子:

def func(a,b):
        print('a=%d, b=%d' % (a,b) )

a = (10, 20)
func(*a) # 在调用函数使用`*`则会把元组解包成单个变量按顺序传入函数
#结果:a=10, b=20

总结:*号在定义函数参数时,传入函数的参数会转换成元组,如果 *号在调用时则会把元组解包成单个元素(元祖的形式)。

3.5 不定长参数 **kwargs

def func(**kw):#使用**定义参数会把传入参数包装成字典dict
        print(kw, type(kw) )

func(a=10,b=20)#这种函数在使用时必须指定参数值,使用key=value这种形式
#结果:{'b': 20, 'a': 10} <class 'dict'>

  举一个相反的列子

def func(a,b):
        print('a=%d, b=%d' % (a,b) )

d = {'a':10, 'b':20 }
func(**d) #在调用时使用**会把字典解包成变量传入函数。

总结:**号在定义函数参数时,传入函数的参数会转换成字典,如果 **号在调用时则会把字典解包成单个元素(k=v形式)。

3.6 指定必须要传递一个参数

def car(a=1, *, price): # * 代表后面的参数必须要传递
    print('waht')

car(price='haha')       # 必须使用关键字参数,否则报错

四、lambda函数

  一些函数功能比较简单,而我们不想去完整的去定义一个完整的参数,不想写函数名。

  就可以去用lambda函数。又叫做 匿名函数。

def plus(x):
    return x + 1
plus(19)

# 进行函数的改写
# 但是这种方法官方不建议,给匿名函数都命名了,还叫命名吗。。
add = lambda x: x+1
add(19)

# 或写成这种
print((lambda x: x + 1)(3))

扩展:filter + lambda

my_list = [1, 2, 3, 4, 5, 6]
def odd(*L): new_list = [] for i in L: if i % 1 == 0: new_list.append(i) return new_list print(*my_list) # *把列表解开变成位置参数。 # 改装 ''' filter(func,iterable) 两个参数: 第一个参数 func :在这里写 函数就会显得冗长,那么我们就用lambda来写 第二个参数 iterbale :一个可迭代对象。 把迭代对象中每个元素拿到func中去执行,满足就留下来。 ''' # 第一步 lambda x: x % 2 == 0 # 第二步 返回的是一个可迭代的对象 filter(lambda x: x % 2 == 0, my_list) # 第3步 转换为列表 y = list(filter(lambda x: x % 2 == 0, my_list)) print(y)

  

  

  

原文地址:https://www.cnblogs.com/louhui/p/8921511.html