IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Python知识库 -> <Effective Python2>学习之第三章:函数 -> 正文阅读

[Python知识库]<Effective Python2>学习之第三章:函数

文章目录

文章目录

前言

N19:不要把函数返回的多个数值拆分到三个以上的变量中

1、详解

2、总结

N20:遇到意外情况时应该抛出异常,不要返回None

1、详解

2、总结

N22:用数量可变的位置参数,给函数设计清晰的参数列表

1、详解

2、总结


前言

提示:Effective Python第二版,作者是Brett Slatkin, Google首席软件工程师,立足于python3,主要讲解原理与常见用法。

第3章主要讲解函数在使用过程中的一些规范。


N19:不要把函数返回的多个数值拆分到三个以上的变量中

1、详解

1)unpacking 机制允许python返回一个以上的值,以元组的形式;

def my_func():
    return 1, 2

first, second = my_func()

2)? 返回多个值时,可以利用(带星号的表达式)接受没有被普通变量捕获的值;

如:计算鳄鱼的长度与平均长度之比,并返回最长和最短的两条鳄鱼对应的比值。

def get_avg_ratio(numbers):
    average = sum(numbers)/len(numbers)
    scaled = [x/average for x in numbers]
    scaled.sort(reverse=True)
    return scaled

longest, *middle, shortest = get_avg_ratio(lengths)

3)返回值过多时,比如返回5个值,会造成两个问题:一是容易搞错顺序造成bug,二是调用函数并拆分返回值的那行代码会非常长,可能需要拆行。(最好不要这么写!!!)

如,返回鳄鱼长度的最小值、最大值,、平均值、中位值和样本总数量。

def get_stats(numbers):
    minimum = min(numbers)
    maximum = max(numbers)
    count = len(numbers)
    average = sum(numbers)/count

    sorted_numbers = sorted(number)
    middle = count // 2
    if count % 2 == 0:
        lower = sorted_number[middle - 1]
        upper = sorted_number[middle]
        midian = (lower + upper) / 2
    else:
        midian = sorted_number[middle]

    return minimum, maximum, average, median, count

minimum, maximum, average, median, count = get_stats(lengths)
 

2、总结

  • 函数可以把多个值合起来通过一个元组返回给调用者,可以利用unpacking 机制拆分;
  • 对于函数返回的多个值,将普通变量没有捕获的返回值全部捕获到一个(带星号的变量里);
  • 返回值拆分到四个或四个以上的变量很容易出错,最好不要!可以通过小类或namedtuple实例完成。

N20:遇到意外情况时应该抛出异常,不要返回None

1、详解

1)很多人喜欢返回None 来表示特殊情况,但存在一个问题:在条件表达式中,None与0、空字符串无法区分,容易出错。

比如:构造除法函数,除数为0会报错,返回None值;在后续对返回值进行使用的时候,按照情况1 的写法还不至于出错,但是情况2的写法,对于被除数为0,返回0的情况,也会输出Invalid inputs, 从而使得程序出现问题。针对该情况,有两种解决方案。

def carefule_divide(a,b):
    try:
        return a/b
    except ZeroDivisionError:
        return None

# 情况1
x,y = 1,0
result = carefule_divide(x,y)
if result is None:
    print('Invalid inputs')

# 情况2
x,y = 0,5
result = carefule_divide(x,y)  # shouldn't
if result is None:
    print('Invalid inputs')

2)方案一,构造二元组把计算结果分为两部分,第一个元素表示操作是否成功,第二个元素表示实际的计算值。使用时,调用者首先需要判断运算是否成功,再决定如何处理运算结果。(该方案的问题是,可能有一部分调用者容易忽略元组的第一个部分,从而无法有效区分。)

def carefule_divide(a,b):
    try:
        return True, a/b
    except ZeroDivisionError:
        return False, None

success, result = carefule_divide(x,y)
if not success:
    print('Invalid inputs')

# 偷懒的调用者
_, result = carefule_divide(x,y)
if not result:
    print('Invalid inputs')

3)方案二,不采用None表示特例,向调用方抛出异常,让其自行选择。

def carefule_divide(a,b):
    try:
        return a/b
    except ZeroDivisionError:
        raise ValueError('Invalid inputs')

# 调用方的工作
x,y = 5,2
try: 
    result = carefule_divide(x,y)
except ValueError:
    print('Invalid inputs')
else:
    print(f'Result:result')

2、总结

  • 用返回值None表示特殊情况,很容易出错。因为在条件表达式中,None跟空字符串、0无法区分,都相当于False;
  • 用异常表示特殊的情况,而不返回None,从而让调用者对异常情况进行处理。

N22:用数量可变的位置参数,给函数设计清晰的参数列表

1、详解

1)参数数量固定的函数,函数调用的时候可能会很乱;

比如values 没有值,也必须传一个空列表进去。

def log(message, values):
    if not values:
        print(message)
    else:
        values_str = '.'.join(str(x) for x in values)
        print(f'{message}:{values_str}')

#调用
log('My number are', [1,2])
log('Hi there', [])

#输出
My number are: 1, 2
Hi there

2)? 让函数接受可变数量的位置参数,即varargs或star args(*args),能够使得函数调用更丝滑;

如:将log函数的第二个参数改为,*args,调用者只需要提供不带星号的参数即可。

def log(message, *values):
    if not values:
        print(message)
    else:
        values_str = '.'.join(str(x) for x in values)
        print(f'{message}:{values_str}')

#调用
log('My number are', [1,2])
log('Hi there')

#输出
My number are: 1, 2
Hi there

3)把已有序列中的元素当成参数,传给参数个数可变的函数,可以在传递序列时使用*操作符。

这种方式存在两个问题。一是程序先把这些参数转为一个元组,再把他们当成可选的位置参数传给参数,这中间需要使用yield函数,如果输入值过多,会造成程序崩溃;二是如果需要新增位置参数,那原来的调用操作需要全部更新,否则会报错或者导致结果异常。

def log(message, *values):
    if not values:
        print(message)
    else:
        values_str = '.'.join(str(x) for x in values)
        print(f'{message}:{values_str}')

#调用
favourites = [7,33,99]
log('Favorite colors', *favourites)

#输出
Favorite colors: 7, 33, 99

2、总结

  • def 定义函数时,*args可以让函数接收数量可变的位置参数;
  • 调用函数时,在序列前面加*,把其中的元素当成位置参数传给*args;
  • *操作符加在生成器前,传递参数时,程序可能会因为内存耗尽而崩溃;
  • 在接受*args的函数添加新的位置参数,会造成原来的调用方式需要改更,还有可能造成难以排查的bug。

  Python知识库 最新文章
Python中String模块
【Python】 14-CVS文件操作
python的panda库读写文件
使用Nordic的nrf52840实现蓝牙DFU过程
【Python学习记录】numpy数组用法整理
Python学习笔记
python字符串和列表
python如何从txt文件中解析出有效的数据
Python编程从入门到实践自学/3.1-3.2
python变量
上一篇文章      下一篇文章      查看所有文章
加:2022-03-15 22:28:05  更:2022-03-15 22:29:36 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年12日历 -2024/12/29 13:40:01-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码
数据统计