前言
《编写高质量python代码的59个有效方法》这本书分类逐条地介绍了编写python代码的有效思路和方法,对理解python和提高编程效率有一定的帮助。本笔记简要整理其中的重要方法。
承接上文https://www.jianshu.com/p/15a6050220e6
上一篇笔记主要介绍了关于基本的python编程思想;
本篇介绍关于函数和 类与继承的编程方法
2. 函数
函数作为编程中最基本重要的编程模块/组织工具,是代码复用和重构的重要工具
使用异常表示特殊情况,不要返回None
这是一个比较细微的场景,是能够体现严谨的编程思想。 如下所示
def divide(a,b):
try:
return a/b
except ZeroDivisionError:
return None
def divide(a,b):
try:
return a/b
except ZeroDivisionError:
return None
x,y=0,5
result=divide(x,y)
if result is None:
print('Invalid Inputs')
对异常情况返回None,但当分子为0时,会给后续编程带来影响(往往不会专门判定None),如下所示,就会出现错误,这种错误往往比较难发现:
x,y=0,5
result=divide(x,y)
if not result :
print('Invalid Inputs')
可以通过增加返回值,增添None判定来解决潜在的问题:
def divide(a,b):
try:
return True,a/b
except ZeroDivisionError:
return False,None
更合适的做法是将异常直接再抛出,调用函数时处理异常即可
def divide(a,b):
try:
return a/b
except ZeroDivisionError as e:
raise ValueError('Invalid inputs') from e
x,y=5,0
try:
res=divide(5,0)
except ValueError:
print('Invalid inputs')
else:
print('Result %.1f' % res)
考虑使用生成器改写直接返回列表的函数
我们经常会利用函数生成一系列结果,用列表的形式返回结果。
## 查找字符串中每个词的首字母的位置
def index_words(text):
result=[]
if text:
result.append(0)
for index,letter in enumerate(text):
if letter==' ':
result.append(index+1)
return result
a='This is a test case.'
index_words(a)
这种写法很常见,这种写法代码比较拥挤;而且当输入较长时,列表占用内存较大;可以考虑使用生成器
def index_words(text):
if text:
yield 0
for index,letter in enumerate(text):
if letter==' ':
yield index+1
list(index_words(a))
通过yield逐次产生结果,可以通过list()将生成器直接转成list,最常见的写法是对生成器进行迭代。使用生成器的唯一问题是:函数返回的迭代器是有状态的,不能重复使用。
使用数量可变的位置参数
可以使用*args,设置长度可变的位置参数
将上例改成下面的形式,减少手工的参数设置
def log(message,*values):
if not values:
print(message)
else:
values_str=', '.join(str(x) for x in values)
print('%s: %s'%(message,values_str))
log('Numbers',1,2,3)
用关键词参数来表达可选的行为
这种写法是我们编程常用的,在代码比较复杂的情况下,在调用函数时指明关键词参数,能够帮助调试,方面函数迭代。用只能以关键字形式指定的参数来确保代码清晰
关键字形式指定参数是编程中常用的方法,但有时关键词较多,可以设定只能以关键词形式指定参数来调用函数,如下图所示:
def safe_division(a,b,*,flag1,flag2):
pass
return 0
safe_division(1,0,flag1=0,flag2=0)
safe_division(1,0, 0, 0)# 报错
*号代表后面的参数均为只能以关键字形式指定的参数,如果以位置参数指定会报错。
3. 类与继承
该部分的方法由于代码和例子比较长,比较复杂,仅挑部分知识点出来,想深入了解的可以看原书。
@classmethod
多态、是得继承体系重点多个类能够以各自独有的方式实现某个方法。具有相同的接口/继承自相同的抽象类,但有不同的功能。
super初始化父类
传统初始化父类的方式如下所示,是在子类里用子类实例直接调用父类的init方法。
这种方式在多重继承下容易出现问题,可以使用内置的super函数初始化父类: ,class变量是用来准确地引用当前类。
网友评论