习题答案
作业一:元组。
作业二,一共有三种方法:
- 不写 return
- 写 return,但后面不加任何东西
- 写 return None(没想到吧)
作业三,代码如下:
def my_pow(a, n):
b = a
for i in range(n - 1):
b *= a
return b
数学计算函数
编程语言设计之初就是为了解决计算问题的。
abs()
这个函数只有一个参数,可以传入一个数字类型的变量,返回该数的绝对值。
等效于以下代码:
def my_abs(a):
if a < 0:
return -a
else:
return a
divmod()
接收两个数字类型的变量,返回一个元组,第一项是整除运算后的结果,第二项是余数。
>>>divmod(7, 2)
(3, 1)
>>> divmod(8, 2)
(4, 0)
pow()
这个函数是不是有些眼熟?是的,这是上一篇文章问题三的内置实现版本。明白为什么说明不能使用内置函数实现了吧?
接收两个数字类型的变量,返回。
可迭代对象函数
顾名思义,它们是对可迭代对象使用的。
min() 和 max()
接收一个可迭代对象或者多个数,返回它们中的最小 / 最大值。
其中有字符类型的元素不会报错,会按照字母顺序进行比较。
len()
接收一个可迭代对象,返回其中元素的个数。
sum()
接收一个可迭代对象,返回其中元素的总和。
等效于以下代码:
def my_sum(iterable):
sum = 0
for i in iterable:
sum += i
return sum
如果可迭代对象里面有元素不是数字将会报错。
all() 和 any()
接收一个可迭代对象,all() 会在可迭代对象中所有元素均为 True 时返回 True,否则返回 False;any() 会在其中有一个元素为 True 时返回 True,如果都是 False 则返回 False。
sorted()
接收一个可迭代对象,返回排序后的结果,可选三个参数:
- cmp:自定义排序的函数,很少使用
- key:指定作为排序依据的项,常用于对字典按照值排序
- reverse:反转结果,为 True 时按降序排列,否则按升序排列
别总是自己想着实现排序算法,Python 的这个函数在绝大多数情况下都可以在时间和内存占用上取得最佳平衡。
list() 和 tuple()
实现列表和元组的互相转换。
类型转换函数
其实这个属于基础部分,但考虑到大家后续查找的难度,放在了内置函数部分。
int()
接收一个参数,将其转换成整数并返回。
可选一个参数 base,整数类型,为第一个参数指定进制,默认为十进制。
遇到字符串参数会尝试转换,如果转换失败会报错。
对浮点数永远向下取整,而不是四舍五入,新手常见错误。
float()
接收一个参数,将其转换成浮点数并返回。
遇到字符串参数会尝试转换,如果转换失败会报错。
bool()
接受一个参数,将其转换成布尔值并返回。
Python 中常见的布尔值为 False 的数据类型:
- None
- False 本身
- 值为 0 的整数或浮点数
- 没有元素的可迭代对象
其它元素布尔值大多为 True。
str()
接收一个参数,将其转换成字符串并返回。
我们会在后文讲到它的实现原理。
进制转换函数
- bin():转换为二进制
- oct():转换为八进制
- hex():转换为十六进制
以上进制返回的结果均为字符串类型,bin() 返回的字符串以“0b”开头,oct() 以“0o”开头,hex() 以“0x”开头。
转换为十进制使用 int() 函数,第二个参数传入原数字的进制。
type()
它非常有用,所以单独拿出来讲解。
一句话概括,传入一个参数,返回它的数据类型。
举个例子:
print(type(1))
结果是<class 'int'>
,代表这是一个整数类型。
尝试着套娃一下,返回的这个数据类型本身并不是一个字符串,而是一个叫做“type”的类型。
这涉及到 Python 的类与对象编程理念。简单解释就是所有整数变量都是 int 的儿子,而 int 又是 type 的儿子。事实上,Python 中所有数据类型的祖宗都是 type。
现在你可以利用这个函数来判断一个变量的数据类型了:
def int_only(a):
if type(a) != int:
print("参数类型必须是 int!")
利用这个判断机制,我们可以为函数添加参数校验环节,避免在处理过程中发生错误。
但 Python 的设计理念想让你在发生错误时再去解决它,这样做有两个好处,其一是简化代码的逻辑,其二是不需要在每次调用时都执行检查步骤,减少对性能的影响。
现在让我们来学习一下如何处理各式各样的问题。
异常处理
Python 的异常处理机制是这样的:
try:
pass
except:
pass
else:
pass
finally:
pass
四部分,我们一点点来说。
程序运行时会首先执行 try 部分的代码,如果没有出现错误则跳过 except 部分,执行 else 部分;如果出现错误则会执行 except 部分,跳过 else 部分。最后,无论是否出错,都会执行 finally 部分。
举个例子,现在我们需要做一个获取简书用户昵称的程序,那么可以这样写:
try:
name = GetUserName("https://www.jianshu.com/u/ea36c8d8aa30/")
except:
print("获取昵称失败")
else:
print(name)
finally:
print("感谢使用")
这样,如果我们的程序因为某些原因,没能成功获取用户昵称,也不会给用户显示复杂的报错信息,而是给出更友好的提示。
但错误可能有很多种,在这个函数中可能出错的点有:
- 输入的链接无效
- 用户账号状态异常
- 网络请求超时
其实,except 后还可以加入具体的错误类别,例如except TypeError
将在 try 块中出现 TypeError 时被执行。
我们的程序中,输入链接无效时将会产生 InputError 错误,用户账号状态异常时产生 ResourceError 错误,网络请求超时时产生 TinmeOutError 错误。
那么我们可以把代码改写成这样:
try:
name = GetUserName("https://www.jianshu.com/u/ea36c8d8aa30/")
except (InputError, ResourceError):
print("输入的链接无效或用户账号状态异常")
except TinmeOutError:
print("网络请求超时")
else:
print(name)
finally:
print("感谢使用")
如你所见,except 后接多个错误时,需要将其写成元组形式,也就是用小括号包裹,逗号分隔。
程序出错时会从上至下依次进行匹配,并执行符合条件的第一个 except 块。
但我们不建议使用except:
这种形式,而是使用except Exception
代替,这样可以使代码更加直观,并避免很多不必要的麻烦。
千万不要写except BaseException
!一旦程序在 try 块中进入死循环,这样会导致无法用 Ctrl + C 退出,因为退出本质上是产生一个SystemExit
异常,而BaseException
会捕获这个异常。
课后习题
作业一,给定以下二进制字符串变量:
a = "0b1010011010"
请编写程序,将其转换为十进制。
作业二:请指出下列函数中的错误(共有 3 处):
需求:对这个数取绝对值后,将其除以 7 并四舍五入,返回结果。
def process(a):
abs(a)
a = a / 7
a = int(a)
作业三:请编写一个函数,将一个可迭代对象中的每一项转换成十六进制,转换失败的设为 None,返回转换后的列表。
下一篇文章,我们将学习类与对象的初步知识。
网友评论