从零开始学Python第15课:函数的应用

案例1

设计一个生成随机验证码的函数,验证码由数字和英文大小写字母构成,长度可以通过参数设置。

import random
import string

ALL_CHARS = string.digits + string.ascii_letters

def generate_code(*, code_len=4):
    """
    生成指定长度的验证码
    :param code_len: 验证码的长度(默认4个字符)
    :return: 由大小写英文字母和数字构成的随机验证码字符串
    """
    return ''.join(random.choices(ALL_CHARS, k=code_len))

说明1string模块的digits代表0到9的数字构成的字符串'0123456789'string模块的ascii_letters代表大小写英文字母构成的字符串'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'

说明2random模块的samplechoices函数都可以实现随机抽样,sample实现无放回抽样,这意味着抽样取出的元素是不重复的;choices实现有放回抽样,这意味着可能会重复选中某些元素。这两个函数的第一个参数代表抽样的总体,而参数k代表样本容量,需要说明的是choices函数的参数k是一个命名关键字参数,在传参时必须指定参数名。

可以用下面的代码生成5组随机验证码来测试上面的函数。

for _ in range(5):
    print(generate_code()) 

输出:

59tZ
QKU5
izq8
IBBb
jIfX

或者

for _ in range(5):
    print(generate_code(code_len=6))

输出:

FxJucw
HS4H9G
0yyXfz
x7fohf
ReO22w

说明:我们设计的generate_code函数的参数是命名关键字参数,由于它有默认值,可以不给它传值,使用默认值4。如果需要给函数传入参数,必须指定参数名code_len

案例2

设计一个判断给定的大于1的正整数是不是质数的函数。质数是只能被1和自身整除的正整数(大于1),如果一个大于1的正整数NNN是质数,那就意味着在2到N−1N-1N−1之间都没有它的因子。

def is_prime(num: int) -> bool:
    """
    判断一个正整数是不是质数
    :param num: 大于1的正整数
    :return: 如果num是质数返回True,否则返回False
    """
    for i in range(2, int(num ** 0.5) + 1):
        if num % i == 0:
            return False
    return True

说明1:上面is_prime函数的参数num后面的: int用来标注参数的类型,虽然它对代码的执行结果不产生任何影响,但是很好的增强了代码的可读性。同理,参数列表后面的-> bool用来标注函数返回值的类型,它也不会对代码的执行结果产生影响,但是却让我们清楚的知道,调用函数会得到一个布尔值,要么是True,要么是False

说明2:上面的循环并不需要从2循环到N−1N-1N−1,因为如果循环进行到N\sqrt{N}N​时,还没有找到NNN的因子,那么N\sqrt{N}N​之后也不会出现NNN的因子,大家可以自己想一想这是为什么。

案例3

设计计算两个正整数最大公约数和最小公倍数的函数。xxx和yyy的最大公约数是能够同时整除xxx和yyy的最大整数,如果xxx和yyy互质,那么它们的最大公约数为1;xxx和yyy的最小公倍数是能够同时被xxx和yyy整除的最小正整数,如果xxx和yyy互质,那么它们的最小公倍数为x×yx \times yx×y。需要提醒大家注意的是,计算最大公约数和最小公倍数是两个不同的功能,应该设计成两个函数,而不是把两个功能放到同一个函数中。

def lcm(x: int, y: int) -> int:
    """求最小公倍数"""
    return x * y // gcd(x, y)

def gcd(x: int, y: int) -> int:
    """求最大公约数"""
    while y % x != 0:
        x, y = y % x, x
    return x

说明1:函数之间可以相互调用,上面求最小公倍数的lcm函数就调用了求最大公约数的gcd函数,通过x×ygcd(x,y)\frac{x \times y}{ gcd(x, y)}gcd(x,y)x×y​来计算最小公倍数。

说明2:上面的gcd函数使用了欧几里得算法计算最大公约数,欧几里得算法也称为辗转相除法,这个算法通常有更好的执行效率,不了解的小伙伴可以自行科普。

案例4

假设样本数据保存一个列表中,设计计算样本数据描述性统计信息的函数。描述性统计信息通常包括:算术平均值、中位数、极差(最大值和最小值的差)、方差、标准差、变异系数等,计算公式如下所示:

样本均值(sample mean):

xˉ=∑i=1nxin=x1+x2+⋯+xnn\bar{x} = \frac{\sum_{i=1}^{n}x_{i}}{n} = \frac{x_{1}+x_{2}+\cdots +x_{n}}{n}xˉ=n∑i=1n​xi​​=nx1​+x2​+⋯+xn​​

样本方差(sample variance):

s2=∑i=1n(xi−xˉ)2n−1s^2 = \frac {\sum_{i=1}^{n}(x_i - \bar{x})^2} {n-1}s2=n−1∑i=1n​(xi​−xˉ)2​

样本标准差(sample standard deviation):

s=∑i=1n(xi−xˉ)2n−1s = \sqrt{\frac{\sum_{i=1}^{n}(x_i - \bar{x})^2}{n-1}}s=n−1∑i=1n​(xi​−xˉ)2​​

变异系数(coefficient of sample variation):

CV=sxˉCV = \frac{s}{\bar{x}}CV=xˉs​

def ptp(data):
    """极差(全距)"""
    return max(data) - min(data)

def mean(data):
    """算术平均"""
    return sum(data) / len(data)

def median(data):
    """中位数"""
    temp, size = sorted(data), len(data)
    if size % 2 != 0:
        return temp[size // 2]
    else:
        return mean(temp[size // 2 - 1:size // 2 + 1])

def var(data, ddof=1):
    """方差"""
    x_bar = mean(data)
    temp = [(num - x_bar) ** 2 for num in data]
    return sum(temp) / (len(temp) - ddof)

def std(data, ddof=1):
    """标准差"""
    return var(data, ddof) ** 0.5

def cv(data, ddof=1):
    """变异系数"""
    return std(data, ddof) / mean(data)

def describe(data):
    """输出描述性统计信息"""
    print(f'均值: {mean(data)}')
    print(f'中位数: {median(data)}')
    print(f'极差: {ptp(data)}')
    print(f'方差: {var(data)}')
    print(f'标准差: {std(data)}')
    print(f'变异系数: {cv(data)}')

说明1:中位数是将数据按照升序或降序排列后位于中间的数,它描述了数据的中等水平。中位数的计算分两种情况:当数据体量nnn为奇数时,中位数是位于n+12\frac{n + 1}{2}2n+1​位置的元素;当数据体量nnn为偶数时,中位数是位于n2\frac{n}{2}2n​和n2+1\frac{n}{2} + 12n​+1两个位置元素的均值。

说明2:计算方差和标准差的函数中有一个名为ddof的参数,它代表了可以调整的自由度,默认值为1。在计算样本方差和样本标准差时,需要进行自由度校正;如果要计算总体方差和总体标准差,可以将ddof参数赋值为0,即不需要进行自由度校正。

说明3describe函数将上面封装好的统计函数组装到一起,用于输出数据的描述性统计信息。事实上,Python 标准库中有一个名为statistics的模块,它已经把获取描述性统计信息的函数封装好了,有兴趣的读者可以自行了解。

案例5

我们用函数重构之前讲过的双色球随机选号的例子(《第09课:常用数据结构之列表-2》),将生成随机号码和输出一组号码的功能分别封装到两个函数中,然后通过调用函数实现机选N注号码的功能。

"""
双色球随机选号程序

Author: 骆昊
Version: 1.3
"""
import random

RED_BALLS = [i for i in range(1, 34)]
BLUE_BALLS = [i for i in range(1, 17)]

def choose():
    """
    生成一组随机号码
    :return: 保存随机号码的列表
    """
    selected_balls = random.sample(RED_BALLS, 6)
    selected_balls.sort()
    selected_balls.append(random.choice(BLUE_BALLS))
    return selected_balls

def display(balls):
    """
    格式输出一组号码
    :param balls: 保存随机号码的列表
    """
    for ball in balls[:-1]:
        print(f'\033[031m{ball:0>2d}\033[0m', end=' ')
    print(f'\033[034m{balls[-1]:0>2d}\033[0m')


n = int(input('生成几注号码: '))
for _ in range(n):
    display(choose())

说明:大家看看display(choose())这行代码,这里我们先通过choose函数获得一组随机号码,然后把choose函数的返回值作为display函数的参数,通过display函数将选中的随机号码显示出来。重构之后的代码逻辑非常清晰,代码的可读性更强了。如果有人为你封装了这两个函数,你仅仅是函数的调用者,其实你根本不用关心choose函数和display函数的内部实现,你只需要知道调用choose函数可以生成一组随机号码,而调用display函数传入一个列表,就可以输出这组号码。将来我们使用各种各样的 Python 三方库时,我们也根本不关注它们的底层实现,我们需要知道的仅仅是调用哪个函数可以解决问题。

总结

在写代码尤其是开发商业项目的时候,一定要有意识的将相对独立且重复使用的功能封装成函数,这样不管是自己还是团队的其他成员都可以通过调用函数的方式来使用这些功能,减少工作中那些重复且乏味的劳动。

如果你对Python感兴趣,想要学习python,这里给大家分享一份Python全套学习资料,都是我自己学习时整理的,希望可以帮到你,一起加油!

😝有需要的小伙伴,可以V扫描下方二维码免费领取🆓

1️⃣零基础入门

① 学习路线

对于从来没有接触过Python的同学,我们帮你准备了详细的学习成长路线图。可以说是最科学最系统的学习路线,你可以按照上面的知识点去找对应的学习资源,保证自己学得较为全面。
在这里插入图片描述

② 路线对应学习视频

还有很多适合0基础入门的学习视频,有了这些视频,轻轻松松上手Python~
在这里插入图片描述

③练习题

每节视频课后,都有对应的练习题哦,可以检验学习成果哈哈!
在这里插入图片描述

2️⃣国内外Python书籍、文档

① 文档和书籍资料

在这里插入图片描述

3️⃣Python工具包+项目源码合集

①Python工具包

学习Python常用的开发软件都在这里了!每个都有详细的安装教程,保证你可以安装成功哦!
在这里插入图片描述

②Python实战案例

光学理论是没用的,要学会跟着一起敲代码,动手实操,才能将自己的所学运用到实际当中去,这时候可以搞点实战案例来学习。100+实战案例源码等你来拿!
在这里插入图片描述

③Python小游戏源码

如果觉得上面的实战案例有点枯燥,可以试试自己用Python编写小游戏,让你的学习过程中增添一点趣味!
在这里插入图片描述

4️⃣Python面试题

我们学会了Python之后,有了技能就可以出去找工作啦!下面这些面试题是都来自阿里、腾讯、字节等一线互联网大厂,并且有阿里大佬给出了权威的解答,刷完这一套面试资料相信大家都能找到满意的工作。
在这里插入图片描述
在这里插入图片描述

上述所有资料 ⚡️ ,朋友们如果有需要的,可以扫描下方👇👇👇二维码免费领取🆓

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值