Python3.x 函数

一、函数基础

1、基础

  • 所谓函数,就是把 具有独立功能的代码块 组织为一个小模块,在需要的时候 调用
  • 函数的使用包含两个步骤:
    1. 定义函数 —— 封装 独立的功能
    2. 调用函数 —— 享受 封装 的成果
案例:洗衣服
# 早上洗衣服
print("打水")
print("洗衣服")
print("甩干")
# 中午洗衣服
print("打水")
print("洗衣服")
print("甩干")
# 晚上洗衣服
print("打水")
print("洗衣服")
print("甩干")

发现了问题:我们将有独立功能的代码封装成一个函数

def washing_machine():  # 洗衣机可以帮我们完成
    print("打水")
    print("洗衣服")
    print("甩干")
# 优化后代码
# 早上洗衣服
washing_machine()  # 打开洗衣机开关
# 中午洗衣服
washing_machine()  # 打开洗衣机开关
# 晚上洗衣服
washing_machine()  # 打开洗衣机开关

2、函数的创建与调用

(1)创建函数

函数用 def 语句创建,语法如下:

def 函数名(参数列表):  # 具体情况具体对待,参数可有可无
	"""函数说明文档字符串"""
    函数封装的代码
    ……

标题行由 def 关键字,函数的名字,以及参数的集合(如果有的话)组成

def 子句的剩余部分包括了一个虽然可选但是强烈推荐的文档字串,和必需的函数体

函数名称 的命名应该 符合 标识符的命名规则

  • 可以由 字母下划线数字 组成
  • 不能以数字开头
  • 不能与关键字重名
def washing_machine():  # 洗衣机可以帮我们完成
    print("打水")
    print("洗衣服")
    print("甩干")

(2)调用函数

使用一对圆括号 () 调用函数,如果没有圆括号,只是对函数的引用

任何输入的参数都必须放置在括号中

图例:
在这里插入图片描述

案例:加洗衣粉
def washing_machine():  # 洗衣机可以帮我们完成
    print("打水")
    print("加洗衣粉!!!")
    print("洗衣服")
    print("甩干")
# 早上洗衣服
washing_machine()
# 中午洗衣服
washing_machine()
# 晚上洗衣服
washing_machine()

总结

  • 定义好函数之后,只表示这个函数封装了一段代码而已
  • 如果不主动调用函数,函数是不会主动执行的

思考

  • 能否将 函数调用 放在 函数定义 的上方?

    • 不能!
    • 因为在 使用函数名 调用函数之前,必须要保证 Python 已经知道函数的存在
    • 否则控制台会提示 NameError: name 'menu' is not defined (名称错误:menu 这个名字没有被定义)

3、函数的参数

(1)形参和实参

  • 形参定义 函数时,小括号中的参数,是用来接收参数用的,在函数内部 作为变量使用
  • 实参调用 函数时,小括号中的参数,是用来把数据传递到 函数内部 用的

问题

当我们想洗其他的东西,要手动改方法内部的代码:

def washing_machine():  # 洗衣机可以帮我们完成
    print("打水")
    print("加洗衣粉!!!")
    print("洗床单")  # 洗被套
    print("甩干")

在函数内部有一定的变化的值:

def washing_machine():  # 洗衣机可以帮我们完成
    print("打水")
    print("加洗衣粉!!!")
    print("洗衣服")
    print("甩干")
washing_machine()
def washing_machine():  # 洗衣机可以帮我们完成
    print("打水")
    print("加洗衣粉!!!")
    print("洗床单")
    print("甩干")
washing_machine()
......

思考一下存在什么问题

函数只能处理 固定 的数据

如何解决?

  • 如果能够把需要处理的数据,在调用函数时,传递到函数内部就好了!

(2)传递参数

  • 在函数名的后面的小括号内部填写 参数
  • 多个参数之间使用 , 分隔
  • 调用函数时,实参的个数需要与形参个数一致,实参将依次传递给形参
def washing_machine(something):  # 洗衣机可以帮我们完成
    print("打水")
    print("加洗衣粉!!!")
    print("洗" + something)
    print("甩干")
# 洗衣服
washing_machine("衣服")
# 洗床单
washing_machine("床单")

图例
在这里插入图片描述

(3)作用

  • 函数,把 具有独立功能的代码块 组织为一个小模块,在需要的时候 调用
  • 函数的参数,增加函数的 通用性,针对 相同的数据处理逻辑,能够 适应更多的数据
    1. 在函数 内部,把参数当做 变量 使用,进行需要的数据处理
    2. 函数调用时,按照函数定义的参数顺序,把 希望在函数内部处理的数据通过参数 传递

练习 1:定义一个函数,计算两个数的和

4. 位置参数

shell 脚本类似,程序名以及参数都以位置参数的方式传递给 python 程序,使用 sys 模块的 argv 列表接收

import sys
print(sys.argv[1], sys.argv[2])  #类比shell: $1 $2
def get_sum(a,b):
    print(a+b)
#位置参数
#a=sys.argv[1],b=sys.argv[2]
#通过终端传来的参数都是字符串类型----这里需要类型转换
get_sum(int(sys.argv[1]),int(sys.argv[2]))

图例
在这里插入图片描述

5. 默认参数

默认参数就是声明了 默认值 的参数,因为给参数赋予了默认值,所以在函数调用时,不向该参数传入值也是允许的

def get_sum(num1, num2, num3=10):
    print(num1 + num2 + num3)
# 默认参数
# 如果没有手动给形参赋值,那么就用默认值
# 定义函数时,有默认值的参数一定放在没有默认值参数的后面
get_sum(1,2,3) # num01=1, num02=2, num03=3    6
get_sum(1,2)   # num01=1, num02=2, num03=10   13


def get_sum1(num01=5, num02):  报错
      print(num01 + num02)


def get_sum2(num1=10, num2=20, num3=30):
    print(num1 + num2 + num3)
get_sum2()     # 60

6. 函数的返回值

  • 在程序开发中,有时候,会希望 一个函数执行结束后,告诉调用者一个结果,以便调用者针对具体的结果做后续的处理
  • 返回值 是函数 完成工作后,最后 给调用者的 一个结果
  • 在函数中使用 return 关键字可以返回结果
  • 调用函数一方,可以 使用变量接收 函数的返回结果

注意:return 表示返回,表示方法执行结束,后续的代码都不会被执行

案例:计算任意两个数字的和

洗完衣服后我们需要把衣服需要使用 return 关键字将每一单的价格返回,告诉帐房先生:

def get_sum(num01, num02):
    return num01 + num02

图例
在这里插入图片描述

没有 return

如果方法内部没有 return 语句,那么会默认返回 None,即 return None

练习 3:斐波那契数列函数

斐波那契数列函数

  • 将斐波那契数列代码改为函数
  • 数列长度由用户指定
  • 要求把结果用 return 返回

版本一:方法内部直接打印

def gen_fib():
    fib = [0, 1]  # 定义列表,指定斐波那契数列的初始两个值
    n = int(input('长度: '))  # 定义变量n, 此变量为用户要看到的列表fib中的元素个数
    for i in range(n - 2):
        fib.append(fib[-1] + fib[-2])
    print(fib)  # 打印列表fib
# 调用两次函数gen_fib()
gen_fib()
gen_fib()

版本二:带返回值

def gen_fib():
    fib = [0, 1]
    n = int(input('长度: '))
    for i in range(n - 2):
        fib.append(fib[-1] + fib[-2])
    return fib  # 返回最后生成的列表fib
# 调用函数gen_fib()
print(gen_fib())

版本三:带参数

def gen_fib(n):
    fib = [0, 1]
    for i in range(n - 2):
        fib.append(fib[-1] + fib[-2])
    return fib  # 返回最后生成的列表fib
# 定义列表nlist, 将要产生的斐波那契数列的长度,作为列表nlist的元素
nlist = [10, 8, 6]
# 使用for循环,传递实参(nlist中的元素)给函数gen_fib(n),得到三组斐波那契数列 
for i in  nlist:
    print(gen_fib(i))

练习4:复制文件函数
  • 修改文件练习中的拷贝程序
    • 将程序改为函数的形式
    • 源文件和目标文件要求通过参数进行传递
    • 实参要求来自于命令行

版本1:

# 定义函数copy(),实现指定单个文件拷贝的功能
def copy():
    src_name = '/usr/bin/ls'
    dst_name = '/tmp/list3'
# 以只读字节的方式打开源文件,赋值给变量src_fobj
# 以写入字节的方式打开源文件,赋值给变量dst_fobj
    src_fobj = open(src_name, 'rb')
    dst_fobj = open(dst_name, 'wb')
    while 1:
        data = src_fobj.read(4096)  
        if len(data) == 0:
            break
        dst_fobj.write(data)
        
    src_fobj.close()
    dst_fobj.close()    
copy()  # 调用拷贝文件的函数copy()

版本2:

def copy(src_name, dst_name):  # 定义函数copy(),实现任意文件的拷贝操作
# 以只读字节的方式打开源文件,赋值给变量src_fobj
# 以写入字节的方式打开源文件,赋值给变量dst_fobj
    src_fobj = open(src_name, 'rb')
    dst_fobj = open(dst_name, 'wb')
    while 1:
        data = src_fobj.read(4096)
       if len(data) == 0:
            break
        dst_fobj.write(data)
    src_fobj.close()
    dst_fobj.close()  
copy(源文件路径, 目标文件路径)  # 使用sys模块的,argv列表获取位置参数

二、函数进阶

1. 创建函数

def语句

  • 标题行由 def 关键字、函数的名字,以及参数的集合(如果有的话)组成
  • def 子句的剩余部分包括了一个虽然可选但是强烈推荐的文档字串,和必需的函数体

前向引用

  • 函数不允许在函数未声明之前,对其进行引用或者调用
def foo():			# 定义函数foo(),先调用bar()函数,报错,下面定义以后,报错取消
    print('in foo')
bar()

def bar():			# 定义函数bar()
	print('in bar')

foo()				# 函数foo()已经被定义,可以直接调用

注意

  • 定义函数时,函数的先后顺序不重要,重要的是 函数在什么位置被调用

调用函数

  • 使用一对圆括号() 调用函数,如果没有圆括号,只是对函数的引用
  • 任何输入的参数都是必须放置在括号中
>>> def foo():		# 定义函数foo()
...     print('in foo')
... 
>>> foo		# 调用函数时,函数名后必须有小括号,否则返回一个位置对象
>>> foo()		# 函数得正确调用方式

关键字参数

  • 关键字参数的概念仅仅针对函数的调用
  • 这种理念是 让调用者通过函数调用中的参数名字来区分参数
  • 这种规范允许参数不按顺序
  • 位置参数应写在关键字参数前面
>>> def get_age(name, age):		#关键字参数的使用,定义函数get_age(name,age), 形参:name和age
...     print('%s is %s years old' % (name, age))
...
>>> get_age('tom', 20)		#调用函数get_age(name,age),name为‘tom’,age为20
>>> get_age(20, 'tom')		#会按照顺序将实参传递给对应得形参,name=20,age='tom'
>>> get_age(age=20, name='tom')		#使用关键字进行传参
>>> get_age(age=20, 'tom')		#关键字参数【age=20】要写在位置参数【'tom'】的后面
>>> get_age(20, name='tom')		#传递实参时,位置参数name在第一个位置,在这里获取了两个name的值
>>> get_age('tom', age=20)		#传递实参时,name值为'tom',age值为20,正确

练习 1:简单的加减法数学游戏

需求

  • 随机生成两个100以内的数字
  • 随机选择加法或是减法
  • 总是使用大的数字减去小的数字

创建新的python文件math_game.py ,构建加减法数学游戏程序的结构

def exam():				#函数exam(), 功能:出题,让用户作答
    pass
def main():				#函数main(), 功能:主函数,用户选择继续答题或退出
    while 1:             	#永久循环
        exam()          	#调用函数,让用户作答
        #判断是否继续
        yn = input('Continue(y/n)?')
        if yn in 'nN':
            print('\nBye-bye')
            break

if __name__ == '__main__':
    main()

编写出题函数 exam()

# 导入random模块的randint方法【随机产生一个整数】和choice方法【随机取出一个元素】
from  random import  randint, choice
def exam():
    nums = [randint(1, 100) for i in range(2)]	#使用列表解析,产生两个1 ~ 100的随机整数
    nums.sort(reverse=True)        			#让列表nums中的元素,从大到小排序
    op = choice('+-')              #随机取出运算符'+'或'-'
    if op == '+':      		#当op为'+'或'-'时,得到列表nums中两个元素的正确计算结果
        result = nums[0] + nums[1]
    else:
        result = nums[0] - nums[1]
    prompt = '%s %s %s = '  % (nums[0], op, nums[1])	#给用户显示出题信息
    answer = int(input(prompt))		#定义变量answer,获取用户输入得答案
    if answer == result:    #判断用户答案和正确结果是否相等,打印相应信息
        print('Very Good!!!')
    else:
        print('Wrong Answer!!!')
def main():				#函数main(), 功能:主函数,用户选择继续答题或退出
    while 1:             #永久循环
        exam()           #调用函数,让用户作答
        yn = input('Continue(y/n)?')
        if yn in 'nN':
            print('\nBye-bye')
            break              #退出while循环

if __name__ == '__main__':
    main()

2. 匿名函数

  • python 允许用 lambda 关键字创造匿名函数
  • 匿名是因为不需要以标准的 def 方式来声明
  • 一个完整的 lambda "语句"代表了一个表达式,这个表达式定义体必须和声明放在同一行
# 使用def定义函数add(x,y)
def add(x, y):
    return  x + y
if __name__ == '__main__':
	print(add(10, 5))

myadd = lambda x, y: x + y		# 定义匿名函数,赋值给myadd,x和y作为形参
print(myadd(10, 20))

filter() 函数

  • filter(func, seq): 调用一个布尔函数 func 来迭代遍历每个序列中的元素;返回一个使 func 返回值为 true 的元素的序列
  • 如果布尔函数比较简单,直接使用 lambda 匿名函数就显得非常方便了

filter(func, seq)函数的使用,如果seq序列中的元素,传入函数func后,返回值为True,则保留下来

from random import  randint		#导入random模块的randint方法(随机产生一个整数)
def func1(x):						#定义函数func1(x),奇数返回True, 偶数返回False
    return True if x % 2 == 1 else False

if __name__ == '__main__':
    nums = [ randint(1, 100) for i in range(10)]   #10个100以内的随机数
print(nums)                                    #打印nums
result = filter(func1, nums)                   #filter()过滤结果
result2 = filter(lambda x: True if x % 2 == 1 else False, nums)
print(list(result))               #将result转换为列表,打印
print(list(result2))

map() 函数

  • map(func, seq): 调用一个函数func 来迭代遍历每个序列中的元素;返回一个经过func处理过的元素序列

map(func, seq)函数的使用,将seq序列中的元素,传入函数func后,经过处理后全部保留下来

from random import  randint

def func2(x):		# 定义函数func2(x),函数返回结果:(x * 2) + 1
    return x * 2 + 1

if __name__ == '__main__':
    nums = [ randint(1, 100) for i in range(10)]   # 10个100以内的随机数
    print(nums)                                    # 打印nums
result3 = map(func2, nums)    # 结果为:nums经过函数func2处理后的序列对象
result4 = map(lambda x: x * 2 + 1, nums)
print(list(result3))          # 将result3转换为列表,打印
print(list(result4))

总结

在这里插入图片描述

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值