跟着廖雪峰老师学python (4)

若想技术精进,当然得把基础知识打得牢牢的。

廖雪峰的官方网站  python3教程,该网站提供的教程浅显易懂,还附带了讲学视频,非常适合初学者正规入门。

以下是通过廖雪峰python官方网站学习的个人查漏补缺。

主要内容包括:(面向对象高级编程) 和 (错误、调试、测试)

 1.__slots__()能够限制实例属性    2.@property装饰器能够将类的方法当做属性调用    3.多重继承    4.定制类(__str__()、__iter__()、__getitem__()、__getattr__()、__call__())具体用处请仔细看  5.使用枚举类/使用元类    6.错误处理:try...excpet...finally...    7.调试 logging才是最好的方式    8.单元测试    9.文档测试

1.面向对象高级编程

数据封装、继承和多态只是面向对象程序设计中最基础的3个概念。在Python中,面向对象还有很多高级特性。

1.使用__slots__:限制实例属性

正常情况下,当我们定义了一个class,创建了一个class的实例后,我们可以给该实例绑定任何属性和方法,这就是动态语言的灵活性。

给实例s绑定一个属性
给实例s绑定一个方法

但是,给一个实例绑定的方法,对另一个实例是不起作用的。为了给所有实例都绑定方法,可以给class绑定方法,给class绑定方法后,所有实例均可调用:

对class类直接进行动态方法绑定,则所有实例都可以调用该方法

通常情况下,上面的set_score方法可以直接定义在class中,但动态绑定允许我们在程序运行的过程中动态给class加上功能,这在静态语言中很难实现。

使用__slots__可以限制实例的属性,比如,只允许对Student实例添加name和age属性。为了达到限制的目的,Python允许在定义class的时候,定义一个特殊的__slots__变量,来限制该class实例能添加的属性:

 __slots__变量的作用
注意: __slots__定义的属性仅对当前类实例起作用,对继承的子类是不起作用的。

除非在子类中也定义__slots__,这样,子类实例允许定义的属性就是自身的__slots__加上父类的__slots__。

2.使用@property:Python内置的@property装饰器就是负责把一个方法变成属性调用。

把一个getter方法变成属性,只需要加上@property就可以了,此时,@property本身又创建了另一个装饰器@score.setter,负责把一个setter方法变成属性赋值,于是,我们就拥有一个可控的属性操作:

神奇的@property装饰器
birth是可读写属性,而age就是一个只读属性

@property广泛应用在类的定义中,可以让调用者写出简短的代码,同时保证对参数进行必要的检查,这样,程序运行时就减少了出错的可能性。

3.多重继承

通过多重继承,一个子类就可以同时获得多个父类的所有功能。

MixIn:MixIn的目的就是给一个类增加多个功能,这样,在设计类的时候,我们优先考虑通过多重继承来组合多个MixIn的功能,而不是设计多层次的复杂的继承关系。我们不需要复杂而庞大的继承链,只要选择组合不同的类的功能,就可以快速构造出所需的子类。

在设计类的时候,我们优先考虑通过多重继承来组合多个MixIn的功能,而不是设计多层次的复杂的继承关系。

由于Python允许使用多重继承,因此,MixIn就是一种常见的设计。只允许单一继承的语言(如Java)不能使用MixIn的设计。

4.定制类

看到类似__slots__这种形如__xxx__变量或者函数名要注意,这些在Python中是有特殊用途的。

定义好__str__()方法,返回一个好看的字符串

1)__str__():返回用户看到的字符串,而__repr__()返回程序开发者看到的字符串,也就是说,__repr__()是为调试服务的。

将__repr__()返回程序开发者看到的字符串改为__str__()方法

2)__iter__:果一个类想被用于for ... in循环,类似list或tuple那样,就必须实现一个__iter__()方法,该方法返回一个迭代对象,然后,Python的for循环就会不断调用该迭代对象的__next__()方法拿到循环的下一个值,直到遇到StopIteration错误时退出循环。

在类中增加__iter__()方法,可以让类编程可迭代对象

3)__getitem__:让类使用起来更像list或tuple。

__getitem__:让类使用起来更像list或tuple

与之对应的是__setitem__()方法,把对象视作list或dict来对集合赋值。最后,还有一个__delitem__()方法,用于删除某个元素。总之,通过上面的方法,我们自己定义的类表现得和Python自带的list、tuple、dict没什么区别,这完全归功于动态语言的“鸭子类型”,不需要强制继承某个接口

4)__getattr__:当查找属性不存在时,python系统会自动调用__getattr__()方法。一个__getattr__()方法,动态返回一个属性。

注意,只有在没有找到属性的情况下,才调用__getattr__,已有的属性,比如name,不会在__getattr__中查找。

当调用不存在的属性时,比如score,Python解释器会试图调用__getattr__(self, 'score')来尝试获得属性,这样,我们就有机会返回score的值。  注:__getattr__在API动态调用上会非常有帮助。

5)__call__:任何类,只需要定义一个__call__()方法,就可以直接对实例进行调用

更多的时候,我们需要判断一个对象是否能被调用,能被调用的对象就是一个Callable对象,比如函数和我们上面定义的带有__call__()的类实例

通过callable()函数,我们就可以判断一个对象是否是“可调用”对象。

Python的class允许定义许多定制方法,可以让我们非常方便地生成特定的类。

5.使用枚举类/使用元类

更好的方法是为这样的枚举类型定义一个class类型,然后,每个常量都是class的一个唯一实例。Python提供了Enum类来实现这个功能。

6.错误处理:try...excpet...finally...

当我们认为某些代码可能会出错时,就可以用try来运行这段代码,如果执行出错,则后续代码不会继续执行,而是直接跳转至错误处理代码,即except语句块,执行完except后,如果有finally语句块,则执行finally语句块,至此,执行完毕。

调用栈:如果错误没有被捕获,它就会一直往上抛,最后被Python解释器捕获,打印一个错误信息,然后程序退出。

记录错误:Python内置的logging模块可以非常容易地记录错误信息。如果不捕获错误,自然可以让Python解释器来打印出错误堆栈,但程序也被结束了。既然我们能捕获错误,就可以把错误堆栈打印出来,然后分析错误原因,同时,让程序继续执行下去。

同样是出错,但程序打印完错误信息后会继续执行,并正常退出:

抛出错误:用raise语句抛出一个错误。

捕获错误目的只是记录一下,便于后续追踪。

7.调试             ---logging才是终极武器

1)用print()方法,简单粗暴的方式调试

2)使用断言assert调试,assert断言比print()容易关闭。启动Python解释器时可以用-O参数来关闭assert。

assert断言,断言失败,本身会抛出AssertionError
assert断言比print()容易关闭

3)使用logging调试

把print()替换为logging是第3种方式,和assert比,logging不会抛出错误,而且可以输出到文件

logging.info()可以输出一段文本。logging的另一个好处是通过简单的配置,一条语句可以同时输出到不同的地方,比如console和文件。

4)使用pdb调试-------是一种方法,但是调试不是很方便

第4种方式是启动Python的调试器pdb,让程序以单步方式运行,可以随时查看运行状态。

python -m pdb python程序文件名

(Pdb) l  # 输入命令字母l来查看代码

(Pdb) n  # 输入命令n可以单步执行代码

(Pdb) p 变量名 # 任何时候都可以输入命令p 变量名来查看变量

(Pdb) q # 输入命令q结束调试,退出程序

这种通过pdb在命令行调试的方法理论上是万能的,但实在是太麻烦了,如果有一千行代码,要运行到第999行得敲多少命令啊。还好,我们还有另一种调试方法。

5)pdb.set_trace()方法调试

pdb.set_trace()-----不是单步执行,这个方式比直接启动pdb单步调试效率要高很多,但也高不到哪去。

6)IDE

如果要比较爽地设置断点、单步执行,就需要一个支持调试功能的IDE。目前比较好的Python IDE有:

Visual Studio Code:https://code.visualstudio.com/,需要安装Python插件。     (用过一小段时间)

PyCharm:http://www.jetbrains.com/pycharm/   (本电脑上正在使用)

另外,Eclipse加上pydev插件也可以调试Python程序。

关于调试的各种方法对比,logging才是终极武器。

8.单元测试  ---测试驱动开发

“测试驱动开发”(TDD:Test-Driven Development)。单元测试:是用来对一个模块、一个函数或者一个类来进行正确性检验的测试工作。

任意输入+期待输出,编写很多测试用例

这种以测试为驱动的开发模式最大的好处就是确保一个程序模块的行为符合我们设计的测试用例。在将来修改的时候,可以极大程度地保证该模块行为仍然是正确的

为了编写单元测试,我们需要引入Python自带的unittest模块。编写单元测试时,我们需要编写一个测试类,从unittest.TestCase继承。以test开头的方法就是测试方法,不以test开头的方法不被认为是测试方法,测试的时候不会被执行对每一类测试都需要编写一个test_xxx()方法。由于unittest.TestCase提供了很多内置的条件判断,我们只需要调用这些方法就可以断言输出是否是我们所期望的。最常用的断言就是assertEqual()

self.assertEqual(abs(-1), 1) # 断言函数返回的结果与1相等

setUp与tearDown

可以在单元测试中编写两个特殊的setUp()和tearDown()方法。这两个方法会分别在每调用一个测试方法的前后分别被执行。

setUp()和tearDown()方法有什么用呢?设想你的测试需要启动一个数据库,这时,就可以在setUp()方法中连接数据库,在tearDown()方法中关闭数据库,这样,不必在每个测试方法中重复相同的代码:

class TestDict(unittest.TestCase):

    def setUp(self):

        print('setUp...')

    def tearDown(self):

        print('tearDown...')

单元测试可以有效地测试某个程序模块的行为,是未来重构代码的信心保证。

单元测试的测试用例要覆盖常用的输入组合、边界条件和异常。

单元测试代码要非常简单,如果测试代码太复杂,那么测试代码本身就可能有bug。

单元测试通过了并不意味着程序就没有bug了,但是不通过程序肯定有bug。

9.文档测试

Python内置的“文档测试”(doctest)模块可以直接提取注释中的代码并执行测试。

doctest非常有用,不但可以用来测试,还可以直接作为示例代码。通过某些文档生成工具,就可以自动把包含doctest的注释提取出来。用户看文档的时候,同时也看到了doctest。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,937评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,503评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,712评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,668评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,677评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,601评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,975评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,637评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,881评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,621评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,710评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,387评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,971评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,947评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,189评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,805评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,449评论 2 342

推荐阅读更多精彩内容