函数的初识

引言

假如没有len这个内置函数,我们想统计一个字符串或者列表长度,可以使用

s1 = 'jfdsklfjdkslffdsafsajsd'
c = 0
for i in s1:
    c += 1
print(c)
l1 = [1, 2, 34, 55, 66]
c = 0
for i in l1:
    c += 1
print(c)

但是有个问题,我们发现:

# 面向过程过程(流水账)
# 代码重复。
# 可读性差。

引出函数概念:
函数:一个函数封装一个功能。

下面来实现以下:
自己写一个函数,完全与len相同。

'''
def 函数名():
函数体

'''
# 函数的执行
# 函数名() 函数的执行者,调用者
def my_len():
    l1 = [1, 2, 34, 55, 66]
    c = 0
    for i in l1:
        c += 1
    print(c)
    
print(my_len())

返回值return
# return 1,函数中遇到return终止函数。
# return 2,返回值 返回给了函数的调用者
# 1, return 返回的是None
# 2, return 单个值 返回单个值
# 3, return 多个值 返回一个由这多个值组成的元组

return 单个值  返回单个值
def my_len():
    print(111)
    print(222)
    return '太白'
print(my_len(),type(my_len()))  #后面的type里面的也执行了一遍,所以有两个111 222

返回多个值   返回一个由这多个值组成的元组

def
my_len(): print(111) print(222) return (1, 2, 3), [12,4] #返回给了my_len():函数的调用者
ret = my_len() 
print(ret, type(ret)) #返回多个值

def my_len():
    l1 = [1, 2, 34, 55, 66]
    c = 0
    for i in l1:
        c += 1
    return c

print(my_len())

补充:

我们还可以这样写:

l1 = [1, 2, 34, 55, 66]
def my_len():  # 形参  和变量一样,自己定义
    c = 0
    for i in l1:
        c += 1
    return c,2


ret,ret1= my_len()  # 函数的执行者(实参)
print(ret,ret1)

分别赋值的这个概念。 

函数的传参
函数分为实参和形参

l1 = [1, 2, 34, 55, 66]
def my_len(s):  # 形参  和变量一样,自己定义
    c = 0
    for i in s:
        c += 1
    return c    # retrun c所以就是返回最后c的值。


ret= my_len(l1)  # 函数的执行者(实参)
print(ret)

现在我们已经把my_len做出来和len一样的效果了。

现在测试一下任意字符串。

print(my_len('fdskalfdsjflsdajf;lsa'))

 但是这个效率很低,但是我们还是要用自带的len

# 实参角度:
# 位置参数 : 从前至后 一一对应
# 关键字传参: 不用按照顺序,一一对应
# 混合传参: 位置参数一定在前面。

# 实参角度:
#1、 位置参数
def func1(a,b):
    print(a+b)
func1('alex','wusir')

位置参数必须一一对应,否则会报错

练习题:

比较两个数大小,返回打的那个值。
def func1(a,b):
    # if a > b:
    #     return a
    # else:
    #     return b
    return a if a > b else b   #和上面的if else一样,可以写成一条
print(func1(100,200))

def func1(a,b):
return a if a > b else b #和上面的if else一样,可以写成一条
print(func1(100,200))

上面的用到了三元运算。我们引申一个三元运算。

三元运算(对if else 优化): 只针对于 if else 二选一的情况。
a = 3
b = 2
# if a > b:
#     ret = a
# else:
#     ret = b
ret = a if a > b else b   #和上面的if else一样,可以写成一条   如果a > b,我让ret==a,否则等于b  a、b、ret分别是三元
print(ret)

只用两行实现:


 
 2、关键字传参
def func2(age,name):
    print(name,age)
func2(name='alex', age=73)

  3、混合传参    混合传参: 位置参数一定在前面。

def func3(a,b,c,name):
    print(a,b,c,name)

func3(1,2,3,name='alex')

 坑:  混合传参: 位置参数一定在前面。

形参角度
# 位置传参: 按照顺序,一一对应
# 默认传参: 如果不传,则默认使用默认参数,传参则覆盖。 常用的会设置默认参数
# 动态参数,万能参数 *args **kwargs

1、位置参数 需要一一对应,否则报错
def func1(a,b,c):
    print(a,b,c)
func1(1,2,3)

2、默认参数 :
def func2(name,age,sex=''):
    print(name,age,sex)

func2('alex',73,sex='')

对于默认参数来说我们来一个练习题:

如果不传,则默认使用默认参数,传参则覆盖。 常用的会设置默认参数

1、班主任要统计同学的人员信息,我们使用函数、文件操作做一个登记表,设置默认性别是男  如果你是经常要输入的,可以设置一个默认。

def wfile(name, age, sex='男'):   # 设置默认性别是男
    with open('登记表', encoding='utf-8', mode='a') as f1:
        f1.write('{}|{}|{}
'.format(name, age, sex))  # 使用write默认只能有一个参数,所以我们要用到格式化输出<br>

while 1:
    name = input('姓名(输入Q/q退出):')
    if name.upper() == 'Q': break # 增加退出
    age = input('年龄:')
    if name.startswith('1'):  # 增加标识,如果这个是男,我们加一个标识,开头是1的开头的,是男的就不用再输入性别了。
        wfile(name, age)
    else:
        sex = input('性别:')
        wfile(name, age, sex)

  

 

3、万能参数 *args, **kwargs
* 的魔性用法

* 的魔性用法
# 函数执行时
# *iterable 打散
# **dict 打散


可以扩展多个数字相加,就得预留多个空间。

一个* 代理了把所有的位置参数1,2,3,4聚合到了一个元祖里面给了args,**是指的把所有的关键字参数,聚合到了字典里,赋值给了kwargs,前提是在函数的定义的时候。


def func4(*args, **kwargs):  # 在函数的定义 * ** 聚合
    print(args)  # (1,2,3,11,...77)

l1 = [1,2,3]
l2 = [11,22,33]
l3 = (55,66,77)
func4(*l1,*l2,*l3)   #前面加上*,直接就可以变成(1,2,3,11..77)的元祖格式  *iterable *一颗星代表打撒,**两颗星也是代理打撒,操作的是字典

 

def func4(*args, **kwargs):  # 在函数的定义 * ** 聚合
    print(kwargs)
dic = {'name':'alex'}
dic1 = {'age':'12'}
func4(**dic,**dic1)

 


 形参角度:所有参数的顺序 位置参数---->*args----->默认参数---->**kwargs
def func5(a,b,*args,sex=''):
    print(a)
    print(b)
    print(sex)
    print(args)
#
func5(1,2,4,5,6,7,8,9)

def func5(a,b,*args,sex='',**kwargs,):
    print(a)
    print(b)
    print(sex)
    print(args)

func5(1,2,4,5,6,7,8,9,sex='')

原文地址:https://www.cnblogs.com/wangkaiok/p/9878590.html