Selenium2自动化测试实战基于Python语言》读书笔记--第3章

第3章 Python基础

由于作者写的这本书完全是以Python语言为基础的,所以需要读者具备一定的Python编程能力。如果说最好的Python基础教程,那应该说是《笨方法学Python》了。

3.1 Python哲学

<span style="color:#000000"><code>Python <span style="color:#006666">2.7</span><span style="color:#006666">.13</span> (v2<span style="color:#006666">.7</span><span style="color:#006666">.13</span>:a06454b1afa1, Dec <span style="color:#006666">17</span> <span style="color:#006666">2016</span>, <span style="color:#006666">20</span>:<span style="color:#006666">42</span>:<span style="color:#006666">59</span>) [MSC v<span style="color:#006666">.1500</span> <span style="color:#006666">32</span> bit (Intel)] <span style="color:#000088">on</span> win32
Type <span style="color:#009900">"copyright"</span>, <span style="color:#009900">"credits"</span> <span style="color:#000088">or</span> <span style="color:#009900">"license()"</span> <span style="color:#000088">for</span> more information.
>>> import this
The Zen <span style="color:#000088">of</span> Python, <span style="color:#000088">by</span> Tim Peters

Beautiful <span style="color:#000088">is</span> better than ugly.
Explicit <span style="color:#000088">is</span> better than implicit.
Simple <span style="color:#000088">is</span> better than complex.
Complex <span style="color:#000088">is</span> better than complicated.
Flat <span style="color:#000088">is</span> better than nested.
Sparse <span style="color:#000088">is</span> better than dense.
Readability counts.
Special cases aren't special enough <span style="color:#000088">to</span> break <span style="color:#000088">the</span> rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In <span style="color:#000088">the</span> face <span style="color:#000088">of</span> ambiguity, refuse <span style="color:#000088">the</span> temptation <span style="color:#000088">to</span> guess.
There should be one<span style="color:#880000">-- and preferably only one --obvious way to do it.</span>
Although <span style="color:#000088">that</span> way may <span style="color:#000088">not</span> be obvious <span style="color:#000088">at</span> <span style="color:#000088">first</span> unless you're Dutch.
Now <span style="color:#000088">is</span> better than never.
Although never <span style="color:#000088">is</span> often better than *right* now.
If <span style="color:#000088">the</span> implementation <span style="color:#000088">is</span> hard <span style="color:#000088">to</span> explain, <span style="color:#000088">it</span>'s a bad idea.
If <span style="color:#000088">the</span> implementation <span style="color:#000088">is</span> easy <span style="color:#000088">to</span> explain, <span style="color:#000088">it</span> may be a good idea.
Namespaces are one honking great idea <span style="color:#880000">-- let's do more of those!</span>
>>> </code></span>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

翻译为中文就是:

  • 优美胜于丑陋
  • 明了胜于晦涩
  • 简单胜过复杂
  • 扁平胜于嵌套
  • 间隔胜于紧凑
  • 可读性很重要
  • 即使假错特例的实用性之名,也不违背这些规则
  • 虽然实用性次于纯度
  • 错误不应该被无声的忽略
  • 除非明确的沉默
  • 当存在多种可能时,不要尝试去猜测
  • 应该有一个,最好只有一个,很明显可以做到这一点
  • 虽然这种方式可能不容易,除非你是Python之父
  • 现在做总比不做好
  • 虽然过期从未比现在好
  • 如果这个实现不容易解释,那么它肯定是坏主意
  • 如果这个实现容易解释,那么它很可能是个好主意
  • 命名空间是一种绝妙的理念,应当多加利用

3.2 输出与输入

3.2.1 print打印

Python提供print()方法来打印信息:

<span style="color:#000000"><code class="language-python">>>><span style="color:#000088">print</span> (<span style="color:#009900">"hello python"</span>)
hello python</code></span>
  • 1
  • 2

打印变量:

<span style="color:#000000"><code class="language-python"><span style="color:#006666">>>> </span>name = <span style="color:#009900">"zhangsan"</span>
<span style="color:#006666">>>> </span><span style="color:#000088">print</span> (<span style="color:#009900">"hello %s , Nice to meet you!"</span> % name)
hello zhangsan , Nice to meet you!
<span style="color:#006666">>>> </span>name = <span style="color:#009900">"Lisi"</span>
<span style="color:#006666">>>> </span><span style="color:#000088">print</span> (<span style="color:#009900">"hello %s , Nice to meet you!"</span> % name)
hello Lisi , Nice to meet you!</code></span>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

%s 只能打印字符串,如果想要打印数组,需要使用%d:

<span style="color:#000000"><code class="language-python"><span style="color:#006666">>>> </span>age = <span style="color:#006666">27</span>
<span style="color:#006666">>>> </span><span style="color:#000088">print</span> (<span style="color:#009900">"You are %d !"</span> % age)
You are <span style="color:#006666">27</span> !</code></span>
  • 1
  • 2
  • 3

如果不知道自己打印的类型,可以使用%r:

<span style="color:#000000"><code class="language-python"><span style="color:#006666">>>> </span>age = <span style="color:#006666">27</span>
<span style="color:#006666">>>> </span><span style="color:#000088">print</span> (<span style="color:#009900">"You are %d !"</span> % age)
You are <span style="color:#006666">27</span> !
<span style="color:#006666">>>> </span>
<span style="color:#006666">>>> </span>n =<span style="color:#006666">100</span>
<span style="color:#006666">>>> </span><span style="color:#000088">print</span> (<span style="color:#009900">"You print is %r ."</span> % n)
You <span style="color:#000088">print</span> <span style="color:#000088">is</span> <span style="color:#006666">100</span> .
<span style="color:#006666">>>> </span>n = <span style="color:#009900">"abc"</span>
<span style="color:#006666">>>> </span><span style="color:#000088">print</span> (<span style="color:#009900">"You print is %r ."</span> % n)
You <span style="color:#000088">print</span> <span style="color:#000088">is</span> <span style="color:#009900">'abc'</span> .
<span style="color:#006666">>>> </span>name = <span style="color:#009900">"zhangsan"</span>
<span style="color:#006666">>>> </span>age = <span style="color:#006666">22</span>
<span style="color:#006666">>>> </span><span style="color:#000088">print</span> (<span style="color:#009900">"student info: %s %d ."</span> % (name, age))
student info: zhangsan <span style="color:#006666">22</span> .</code></span>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

3.2.2 input输入

如果希望打印的是程序运行过程中由用户来决定的内容,可以使用input()方法:

<span style="color:#000000"><code class="language-python">n = input(<span style="color:#009900">"Enter any content: "</span>)
<span style="color:#000088">print</span> <span style="color:#009900">"Your input is %r"</span> % n</code></span>
  • 1
  • 2

运行上述脚本时,用户输入的信息就会被打印出来。

3.2.3 引号与注释

Python不区分单引号、双引号,都可以用来表示一个字符串:

<span style="color:#000000"><code class="language-python"><span style="color:#006666">>>> </span><span style="color:#000088">print</span> (<span style="color:#009900">"hello"</span>)
hello
<span style="color:#006666">>>> </span><span style="color:#000088">print</span> (<span style="color:#009900">'hello'</span>)
hello</code></span>
  • 1
  • 2
  • 3
  • 4

单引号和双引号可以相互嵌套使用,但不能交叉使用:

<span style="color:#000000"><code class="language-python"><span style="color:#006666">>>> </span><span style="color:#000088">print</span> (<span style="color:#009900">"你说:'早上你好'"</span>)
你说:<span style="color:#009900">'早上你好'</span>
<span style="color:#006666">>>> </span><span style="color:#000088">print</span> (<span style="color:#009900">'我说:"今天天气不错"'</span>)
我说:<span style="color:#009900">"今天天气不错"</span>
<span style="color:#006666">>>> </span><span style="color:#000088">print</span> (<span style="color:#009900">"你微笑着'向我道别"</span>。<span style="color:#009900">')

SyntaxError: invalid syntax</span></code></span>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

Python的单行注释使用“#”表示:

<span style="color:#000000"><code class="language-python">>>><span style="color:#880000">#单行注释</span>
>>><span style="color:#000088">print</span> (<span style="color:#009900">"hello world"</span>) <span style="color:#880000">#打印hello world</span>
hello world</code></span>
  • 1
  • 2
  • 3

多行注释使用三对引号表示,同样不区分单、双引号:

<span style="color:#000000"><code class="language-python"><span style="color:#009900">"""
我们实现一个伟大的程序
那么是
print 一行数据 ^_^
"""</span>
<span style="color:#009900">'''
This is a
Multi line comment
'''</span>
<span style="color:#000088">print</span> (<span style="color:#009900">"Hello World"</span>)</code></span>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

3.3 分支与循环

结构化程序实质上是由有限个顺序、分支和循环三种基本结构排列、嵌套而成。

3.3.1 if语句

if实现分支判断,一般语法为:if…else…

<span style="color:#000000"><code class="language-python">>>>a = <span style="color:#006666">2</span>
>>>b = <span style="color:#006666">3</span>
>>><span style="color:#000088">if</span> a > b:
    <span style="color:#000088">print</span> (<span style="color:#009900">"a max!"</span>)
<span style="color:#000088">else</span>:
    <span style="color:#000088">print</span> (<span style="color:#009900">"b max!"</span>)

b max!</code></span>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

注意: Python没有像其他语言一样使用“{}”表示语句体,而是通过语句的缩进来判断语句体,缩进默认为4个空格。

if语句通过“==”运算符判断相等:

<span style="color:#000000"><code class="language-python">>>>student = <span style="color:#009900">"xiaoming"</span>
>>><span style="color:#000088">if</span> student == <span style="color:#009900">"xiaoming"</span>:
    <span style="color:#000088">print</span> (<span style="color:#009900">"xiaoming, You are on duty today."</span>)
<span style="color:#000088">else</span>:
    <span style="color:#000088">print</span> (<span style="color:#009900">"Please call xiaoming to duty"</span>)

xiaoming, You are on duty today.</code></span>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

if语句通过“!=”运算符判断不相等;

if语句还可以使用“in”、“not in”表示包含关系:

<span style="color:#000000"><code class="language-python">>>>hi = <span style="color:#009900">"hello world"</span>
>>><span style="color:#000088">if</span> <span style="color:#009900">"hello"</span> <span style="color:#000088">in</span> hi:
    <span style="color:#000088">print</span> (<span style="color:#009900">"Contain"</span>)
<span style="color:#000088">else</span>:
    <span style="color:#000088">print</span> (<span style="color:#009900">"Not Contain"</span>)

Contain</code></span>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

if语句还可以进行布尔类型的判断:

<span style="color:#000000"><code class="language-python">>>>a = <span style="color:#000088">True</span>
>>><span style="color:#000088">if</span> a:
    <span style="color:#000088">print</span> (<span style="color:#009900">"a is True"</span>)
<span style="color:#000088">else</span>:
    <span style="color:#000088">print</span> (<span style="color:#009900">"a is not True"</span>)

a <span style="color:#000088">is</span> <span style="color:#000088">True</span></code></span>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

练习:

<span style="color:#000000"><code class="language-python">results = <span style="color:#006666">72</span>

<span style="color:#000088">if</span> results >= <span style="color:#006666">90</span>:
    <span style="color:#000088">print</span> (<span style="color:#009900">"优秀"</span>)
<span style="color:#000088">elif</span> results >= <span style="color:#006666">70</span>:
    <span style="color:#000088">print</span> (<span style="color:#009900">"良好"</span>)
<span style="color:#000088">elif</span> results >= <span style="color:#006666">60</span>:
    <span style="color:#000088">print</span> (<span style="color:#009900">"及格"</span>)
<span style="color:#000088">else</span>:
    <span style="color:#000088">print</span> (<span style="color:#009900">"不及格"</span>)</code></span>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

答案:良好。

3.3.2 for语句

Python提供了两种循环:while循环、for循环。

for循环的使用更加灵活、简单,可以直接对一个字符串进行遍历:

<span style="color:#000000"><code class="language-python"><span style="color:#006666">>>> </span><span style="color:#000088">for</span> i <span style="color:#000088">in</span> <span style="color:#009900">"hello world"</span>:
    <span style="color:#000088">print</span> (i)


h
e
l
l
o

w
o
r
l
d</code></span>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

对一个字典进行遍历:

<span style="color:#000000"><code class="language-python"><span style="color:#006666">>>> </span>fruits = [<span style="color:#009900">'banana'</span>, <span style="color:#009900">'apple'</span>, <span style="color:#009900">'mango'</span>]
<span style="color:#006666">>>> </span><span style="color:#000088">for</span> fruit <span style="color:#000088">in</span> fruits:
    <span style="color:#000088">print</span> fruit


banana
apple
mango</code></span>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

使用range()函数来进行指定次数的循环:

<span style="color:#000000"><code class="language-python"><span style="color:#006666">>>> </span><span style="color:#000088">for</span> i <span style="color:#000088">in</span> range(<span style="color:#006666">5</span>):
    <span style="color:#000088">print</span> (i)


<span style="color:#006666">0</span>
<span style="color:#006666">1</span>
<span style="color:#006666">2</span>
<span style="color:#006666">3</span>
<span style="color:#006666">4</span></code></span>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

注意: range()函数默认从0开始循环。

指定起始位置和步长的循环:

<span style="color:#000000"><code class="language-python"><span style="color:#006666">>>> </span><span style="color:#000088">for</span> i <span style="color:#000088">in</span> range(<span style="color:#006666">1</span>, <span style="color:#006666">10</span>, <span style="color:#006666">2</span>):
    <span style="color:#000088">print</span> (i)


<span style="color:#006666">1</span>
<span style="color:#006666">3</span>
<span style="color:#006666">5</span>
<span style="color:#006666">7</span>
<span style="color:#006666">9</span></code></span>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

range(start, end[, step]) 
start表示开始位置、end表示结束位置、step表示每一次循环的步长。

python2:range() 是一个生成器,xrange()是一个数组,功能完全一样,性能后者优于前者; 
python3:range()和xrange()相同,都是一个数组。

3.4 数组与字典

3.4.1 数组

数组:用方括号[]表示,里面的每一项用逗号“,”分隔。

<span style="color:#000000"><code class="language-python"><span style="color:#006666">>>> </span>lists = [<span style="color:#006666">1</span>, <span style="color:#006666">2</span>, <span style="color:#006666">3</span>, <span style="color:#009900">'a'</span>, <span style="color:#006666">5</span>]
<span style="color:#006666">>>> </span>lists
[<span style="color:#006666">1</span>, <span style="color:#006666">2</span>, <span style="color:#006666">3</span>, <span style="color:#009900">'a'</span>, <span style="color:#006666">5</span>]
<span style="color:#006666">>>> </span>lists[<span style="color:#006666">0</span>]
<span style="color:#006666">1</span>
<span style="color:#006666">>>> </span>lists[<span style="color:#006666">4</span>]
<span style="color:#006666">5</span>
<span style="color:#006666">>>> </span>lists[<span style="color:#006666">4</span>] = <span style="color:#009900">'b'</span>
<span style="color:#006666">>>> </span>lists[<span style="color:#006666">4</span>]
<span style="color:#009900">'b'</span>
<span style="color:#006666">>>> </span>lists.append(<span style="color:#009900">'c'</span>)
<span style="color:#006666">>>> </span>lists
[<span style="color:#006666">1</span>, <span style="color:#006666">2</span>, <span style="color:#006666">3</span>, <span style="color:#009900">'a'</span>, <span style="color:#009900">'b'</span>, <span style="color:#009900">'c'</span>]</code></span>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

注意:

  • Python允许在数组里任意地防止数字或字符串
  • 数组下标是从0开始
  • append()函数可以向数组末尾追加新项

3.4.2 字典

字典:用花括号{}表示,里面的项是成对出现,一个key对应一个value,key与value之间用冒号分隔,不同的项之间用逗号“,”分隔。

<span style="color:#000000"><code class="language-python"><span style="color:#006666">>>> </span>dicts = {<span style="color:#009900">"username"</span>:<span style="color:#009900">"zhangsan"</span>,<span style="color:#009900">'password'</span>:<span style="color:#006666">123456</span>}
<span style="color:#006666">>>> </span>dicts.keys()
[<span style="color:#009900">'username'</span>, <span style="color:#009900">'password'</span>]
<span style="color:#006666">>>> </span>dicts.values()
[<span style="color:#009900">'zhangsan'</span>, <span style="color:#006666">123456</span>]
<span style="color:#006666">>>> </span>dicts.items()
[(<span style="color:#009900">'username'</span>, <span style="color:#009900">'zhangsan'</span>), (<span style="color:#009900">'password'</span>, <span style="color:#006666">123456</span>)]
<span style="color:#006666">>>> </span><span style="color:#000088">for</span> k,v <span style="color:#000088">in</span> dicts.items():
    <span style="color:#000088">print</span> (<span style="color:#009900">"dicts keys is %r"</span> % k)
    <span style="color:#000088">print</span> (<span style="color:#009900">"dicts values is %r"</span> % v)


dicts keys <span style="color:#000088">is</span> <span style="color:#009900">'username'</span>
dicts values <span style="color:#000088">is</span> <span style="color:#009900">'zhangsan'</span>
dicts keys <span style="color:#000088">is</span> <span style="color:#009900">'password'</span>
dicts values <span style="color:#000088">is</span> <span style="color:#006666">123456</span></code></span>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

注意: Python规定一个字典中的key必须独一无二,valuekey相同。

  • keys()函数:返回字典key的列表
  • values()函数:返回字典value的列表
  • items()函数:将所有的字典项以列表方式返回

按存放的顺序输出字典:

<span style="color:#000000"><code class="language-python"><span style="color:#880000"># 通过zip方法合并两个List为Dictionary</span>
<span style="color:#880000"># 遍历会按原先的顺序</span>
keys = [<span style="color:#009900">"b"</span>, <span style="color:#009900">"a"</span>, <span style="color:#009900">"c"</span>, <span style="color:#009900">"e"</span>, <span style="color:#009900">"d"</span>]
values = [<span style="color:#009900">"2"</span>, <span style="color:#009900">"1"</span>, <span style="color:#009900">"3"</span>, <span style="color:#009900">"5"</span>, <span style="color:#009900">"4"</span>]

<span style="color:#000088">for</span> key,value <span style="color:#000088">in</span> zip(keys, values):
    <span style="color:#000088">print</span> (key, value)</code></span>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

输出结果: 
b 2 
a 1 
c 3 
e 5 
d 4

3.5 函数、类和方法

3.5.1 函数

Python通过def关键字来定义函数:

<span style="color:#000000"><code class="language-python"><span style="color:#006666">>>> </span><span style="color:#000088">def</span> <span style="color:#009900">add</span><span style="color:#4f4f4f">(a, b)</span>:
    <span style="color:#000088">print</span> (a + b)


<span style="color:#006666">>>> </span>add(<span style="color:#006666">3</span>, <span style="color:#006666">5</span>)
<span style="color:#006666">8</span></code></span>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

通常函数不会直接打印结果,而是将结果通过return关键字返回:

<span style="color:#000000"><code class="language-python">>>><span style="color:#000088">def</span> <span style="color:#009900">add</span><span style="color:#4f4f4f">(a, b)</span>:
    <span style="color:#000088">return</span> a + b
>>>add(<span style="color:#006666">3</span>, <span style="color:#006666">5</span>)
<span style="color:#006666">8</span></code></span>
  • 1
  • 2
  • 3
  • 4

如果在调用函数时不想传参,可以为函数设置默认参数:

<span style="color:#000000"><code class="language-python"><span style="color:#006666">>>> </span><span style="color:#000088">def</span> <span style="color:#009900">add</span><span style="color:#4f4f4f">(a=<span style="color:#006666">1</span>, b=<span style="color:#006666">2</span>)</span>:
    <span style="color:#000088">return</span> a + b

<span style="color:#006666">>>> </span>add()
<span style="color:#006666">3</span>
<span style="color:#006666">>>> </span>add(<span style="color:#006666">3</span>, <span style="color:#006666">5</span>)
<span style="color:#006666">8</span></code></span>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

3.5.2 类和方法

在面向对象编程的世界里,一切皆为对象,抽象的一组对象就是类。

eg:汽车是一个类,而张三家的奇瑞汽车就是一个具体的对象。

Python使用class关键字来创建类。

<span style="color:#000000"><code class="language-python"><span style="color:#000088">class</span> <span style="color:#4f4f4f">A</span><span style="color:#4f4f4f">(object)</span>:

    <span style="color:#000088">def</span> <span style="color:#009900">add</span><span style="color:#4f4f4f">(self, a, b)</span>:
        <span style="color:#000088">return</span> a + b

count = A()
<span style="color:#000088">print</span> (count.add(<span style="color:#006666">3</span>, <span style="color:#006666">5</span>))</code></span>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

输出结果为:8

对上述代码分析:

  • 创建一个类A(在Python 3中object为所有类的基类,所有类在创建时默认继承object,所以不声明继承object也可以)
  • 在类下面创建一个add()方法,注意,方法的第一个参数必须是存在的,一般习惯命名为self,但在调用这个方法时不需要为这个参数传值

一般在创建类时会首先声明初始化方法__init__(),注意,init的两侧是双下划线,当我们在调用该类时,可以用来进行一下初始化工作:

<span style="color:#000000"><code class="language-python"><span style="color:#000088">class</span> <span style="color:#4f4f4f">A</span><span style="color:#4f4f4f">(object)</span>:

    <span style="color:#000088">def</span> <span style="color:#009900">__init__</span><span style="color:#4f4f4f">(self, a, b)</span>:
        self.a = int(a)
        self.b = int(b)

    <span style="color:#000088">def</span> <span style="color:#009900">add</span><span style="color:#4f4f4f">(self)</span>:
        <span style="color:#000088">return</span> self.a + self.b

count = A(<span style="color:#009900">'4'</span>, <span style="color:#006666">5</span>)
<span style="color:#000088">print</span> (count.add())</code></span>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

输出结果为:9

对上述代码分析:

  • 当调用A类时首先会执行它的__init__()方法,所以需要对其进行传参
  • 初始化的工作就是将输入的参数类型转化为int类型,保证程序容错性
  • add()方法可以直接拿初始化方法的self.a和self.b两个数进行计算
  • 所以在调用A类下面的add()方法时,不需要再传参

Python中类的继承:

<span style="color:#000000"><code class="language-python"><span style="color:#000088">class</span> <span style="color:#4f4f4f">A</span><span style="color:#4f4f4f">()</span>:

    <span style="color:#000088">def</span> <span style="color:#009900">add</span><span style="color:#4f4f4f">(self, a, b)</span>:
        <span style="color:#000088">return</span> a + b

<span style="color:#000088">class</span> <span style="color:#4f4f4f">B</span><span style="color:#4f4f4f">(A)</span>:

    <span style="color:#000088">def</span> <span style="color:#009900">sub</span><span style="color:#4f4f4f">(self, a, b)</span>:
        <span style="color:#000088">return</span> a - b

<span style="color:#000088">print</span> (B().add(<span style="color:#006666">4</span>, <span style="color:#006666">5</span>))</code></span>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

输出结果为:9

对上述代码分析:

  • 创建一个A类,在下面创建add()方法用于计算两个参数相加
  • 创建一个B类,继承A类,并且又继续创建sub()方法用于计算两个参数相减
  • 因为B类继承了A类,所以B类自然也拥有了add()方法,从而可以直接通过B类调用add()方法

3.6 模组

模组=类库、模块。

3.6.1 引用模块

通过:import…或者from…import…的方式引用模块,eg:

<span style="color:#000000"><code class="language-python"><span style="color:#006666">>>> </span><span style="color:#000088">import</span> time
<span style="color:#006666">>>> </span><span style="color:#000088">print</span> time.ctime()
Mon Mar <span style="color:#006666">19</span> <span style="color:#006666">16</span>:<span style="color:#006666">20</span>:<span style="color:#006666">26</span> <span style="color:#006666">2018</span></code></span>
  • 1
  • 2
  • 3

如果确定只需要使用time下面的ctime()方法,还可以这样引用,eg:

<span style="color:#000000"><code class="language-python"><span style="color:#006666">>>> </span><span style="color:#000088">from</span> time <span style="color:#000088">import</span> ctime
<span style="color:#006666">>>> </span><span style="color:#000088">print</span> ctime()
Mon Mar <span style="color:#006666">19</span> <span style="color:#006666">16</span>:<span style="color:#006666">22</span>:<span style="color:#006666">00</span> <span style="color:#006666">2018</span></code></span>
  • 1
  • 2
  • 3

现在使用时就不必告诉Python,ctime()方法是time模块所提供的了。 
但是实际情况,可能是我们还需要使用time模块下的sleep()方法,我们也可以这样引入进来,但是还有其他方法呢,所以我们可以一次性把time模块下的所有方法都引入进来,eg:

<span style="color:#000000"><code class="language-python"><span style="color:#000088">from</span> time <span style="color:#000088">import</span> *

<span style="color:#000088">print</span> ctime()
<span style="color:#000088">print</span> <span style="color:#009900">"休眠两秒"</span>
sleep(<span style="color:#006666">2</span>)
<span style="color:#000088">print</span> ctime()</code></span>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

最终输出结果是:

<span style="color:#000000"><code class="language-shell"><span style="color:#000000">Mon</span> <span style="color:#000000">Mar</span> 19 16<span style="color:#000000">:46</span><span style="color:#000000">:22</span> 2018
休眠两秒
<span style="color:#000000">Mon</span> <span style="color:#000000">Mar</span> 19 16<span style="color:#000000">:46</span><span style="color:#000000">:24</span> 2018</code></span>
  • 1
  • 2
  • 3

其中,星号(*),代表了模块下的所有方法。通过导入模块后,可以使用help查看模块的doc,eg:

<span style="color:#000000"><code class="language-python"><span style="color:#000088">import</span> time
help(time)</code></span>
  • 1
  • 2

pip所安装的Python第三方库或框架,都可以使用这种方式来查看。

3.6.2 模块调用

一个软件项目不可能把所有代码都放在一个文件中实现,一般会按照一定规则在不同的目录和文件中实现。

创建一个目录project,并在目录下创建两个文件,结构如下:

<span style="color:#000000"><code><span style="color:#880000">project/</span>
    <span style="color:#880000">|</span><span style="color:#006666">-</span><span style="color:#006666">-</span><span style="color:#880000">pub</span><span style="color:#009900">.</span><span style="color:#880000">py</span>
    <span style="color:#880000">|</span><span style="color:#006666">-</span><span style="color:#006666">-</span><span style="color:#880000">count</span><span style="color:#009900">.</span><span style="color:#880000">py</span></code></span>
  • 1
  • 2
  • 3

在pub.py文件中创建add函数:

<span style="color:#000000"><code class="language-python"><span style="color:#000088">def</span> <span style="color:#009900">add</span><span style="color:#4f4f4f">(a, b)</span>:
    <span style="color:#000088">return</span> a + b</code></span>
  • 1
  • 2

在count.py文件中调用pub.py文件中的add()函数:

<span style="color:#000000"><code class="language-python"><span style="color:#000088">from</span> pub <span style="color:#000088">import</span> add

<span style="color:#000088">print</span> add(<span style="color:#006666">4</span>, <span style="color:#006666">5</span>)</code></span>
  • 1
  • 2
  • 3

输出结果为:9

这样就实现了跨文件的函数调用。

注意: 以下情况会在你使用Python3.5版本中出现,在project目录下,多了一个__pycache__/pub.cpython-35.pyc文件,它的作用是为了提高模块加载的速度,每个模块都会在__pycache__文件夹中放置该模块的预编译模块,命名为module.version.pyc,version是模块的预编译版本编码,通常会包含Python的版本号,例如在CPython发行版3.5中,pub.py文件的预编译文件就是:__pycache__/pub.cpython-35.pyc。

3.6.3 跨目录模块调用

如果调用文件与被调用文件在一个目录下面,那么可以使用上面的方法,但是如果不在同一个目录下,假设文件目录结构如下:

<span style="color:#000000"><code><span style="color:#880000">project/</span>
    <span style="color:#880000">|</span><span style="color:#006666">-</span><span style="color:#006666">-</span><span style="color:#880000">model/</span>
        <span style="color:#880000">|</span><span style="color:#006666">-</span><span style="color:#006666">-</span><span style="color:#880000">pub</span><span style="color:#009900">.</span><span style="color:#880000">py</span>
    <span style="color:#880000">|</span><span style="color:#006666">-</span><span style="color:#006666">-</span><span style="color:#880000">count</span><span style="color:#009900">.</span><span style="color:#880000">py</span></code></span>
  • 1
  • 2
  • 3
  • 4

如果还还想在count.py中调用add方法,则需要将目录的完整路径补全,eg:

<span style="color:#000000"><code class="language-python"><span style="color:#000088">from</span> model.pub <span style="color:#000088">import</span> add

<span style="color:#000088">print</span> add(<span style="color:#006666">4</span>, <span style="color:#006666">5</span>)</code></span>
  • 1
  • 2
  • 3

运行结果,依然是:9

3.6.4 进一步讨论跨目录模块调用

目录结构更加复杂的情况:

<span style="color:#000000"><code><span style="color:#880000">project/</span>
    <span style="color:#880000">|</span><span style="color:#006666">-</span><span style="color:#006666">-</span><span style="color:#880000">model/</span>
        <span style="color:#880000">|</span><span style="color:#006666">-</span><span style="color:#006666">-</span><span style="color:#880000">count</span><span style="color:#009900">.</span><span style="color:#880000">py</span>
        <span style="color:#880000">|</span><span style="color:#006666">-</span><span style="color:#006666">-</span><span style="color:#880000">new_count</span><span style="color:#009900">.</span><span style="color:#880000">py</span>
    <span style="color:#880000">|</span><span style="color:#006666">-</span><span style="color:#006666">-</span><span style="color:#880000">test</span><span style="color:#009900">.</span><span style="color:#880000">py</span></code></span>
  • 1
  • 2
  • 3
  • 4
  • 5

count.py代码如下:

<span style="color:#000000"><code class="language-python"><span style="color:#000088">class</span> <span style="color:#4f4f4f">A</span><span style="color:#4f4f4f">()</span>:

    <span style="color:#000088">def</span> <span style="color:#009900">add</span><span style="color:#4f4f4f">(self, a, b)</span>:
        <span style="color:#000088">return</span> a + b</code></span>
  • 1
  • 2
  • 3
  • 4

new_count.py代码如下:

<span style="color:#000000"><code class="language-python"><span style="color:#000088">from</span> count <span style="color:#000088">import</span> A

<span style="color:#000088">class</span> <span style="color:#4f4f4f">B</span><span style="color:#4f4f4f">(A)</span>:

    <span style="color:#000088">def</span> <span style="color:#009900">sub</span><span style="color:#4f4f4f">(self, a, b)</span>:
        <span style="color:#000088">return</span> a - b
resule = B().add(<span style="color:#006666">2</span>, <span style="color:#006666">5</span>)
<span style="color:#000088">print</span> resule</code></span>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

输出结果:7

上述结果没问题,接下来与model目录平级创建test.py文件:

<span style="color:#000000"><code class="language-python"><span style="color:#000088">from</span> model <span style="color:#000088">import</span> new_count

test = new_count()
test.add(<span style="color:#006666">2</span>, <span style="color:#006666">5</span>)</code></span>
  • 1
  • 2
  • 3
  • 4

输出结果,会出现:ImportError: No module named 'count'

通过提示信息,在new_count.py文件中,找不到“count”模块,可刚才在执行new_count.py时是可以正常运行的,那么,要想弄清楚错误的原因,首先要知道当Python执行import时到底做了哪些操作?

重点:

当Python在执行import语句时,执行了如下操作:

  • 第1步:创建一个新的module对象(它可能包含多个module);

  • 第2步:把这个module对象插到sys.module中;

  • 第3步:装载module的代码(如果需要,则必须先编译);

  • 第4步:执行新的module中对应的代码;

在执行第3步的时候,首先需要找到module程序所在的位置,搜索的顺序是:

当前路径(以及从当前目录指定的sys.path),PythonPATH,再后是Python安装时设置的相关的默认路径。正因为存在这样的顺序,所以如果当前路径或PythonPATH中存在于标准module同样的module,则会覆盖标准module。也就是说,如果当前目录下存在xml.py,那么在执行import xml时导入的就是当前目录下的module,而不是系统标准的xml。

了解了这些后,我们就可以先构建一个package,以普通module的方式导入,这样即可直接访问此package中各个module,注意,Python2中的package必须包含一个__init__.py的文件。

所以上面问题的错误原因就是:

站在new_count.py的位置,执行from count import A,可查看当前目录下是否存在“count”名字的文件或目录,是可以找到的,但是站在test.py的位置,执行from count import A时,在当前目录下是找不到“count”名字的文件或目录的,所以抛出异常。

解决办法:

最简单的办法就是将导入方法修改为from .count import A,在“count”前面加个点,用来告诉程序count是相对于new_content.py的一个导入。

上面解决办法引入的新的问题:

修改new_count.py代码如下:

<span style="color:#000000"><code class="language-python"><span style="color:#000088">from</span> .count <span style="color:#000088">import</span> A

<span style="color:#000088">class</span> <span style="color:#4f4f4f">B</span><span style="color:#4f4f4f">(A)</span>:

    <span style="color:#000088">def</span> <span style="color:#009900">sub</span><span style="color:#4f4f4f">(self, a, b)</span>:
        <span style="color:#000088">return</span> a - b

result = B().add(<span style="color:#006666">2</span>, <span style="color:#006666">5</span>)
<span style="color:#000088">print</span> result</code></span>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

当再次执行test.py代码时,出现了新的错误:

<span style="color:#000000"><code class="language-syslog">Traceback (most recent <span style="color:#000088">call</span> <span style="color:#000088">last</span>):
  File <span style="color:#009900">"/tmp/project/model/new_count.py"</span>, line <span style="color:#006666">1</span>, <span style="color:#000088">in</span> <<span style="color:#000088">module</span>>
    <span style="color:#000088">from</span> .<span style="color:#009900">count</span> import A
[Finished <span style="color:#000088">in</span> <span style="color:#006666">0.1</span>s <span style="color:#000088">with</span> exit code <span style="color:#006666">1</span>]SystemError: Parent <span style="color:#000088">module</span> <span style="color:#009900">''</span> <span style="color:#000088">not</span> loaded, cannot perform <span style="color:#000088">relative</span> import</code></span>
  • 1
  • 2
  • 3
  • 4

这句话的意思是:“未加载父模块,不能执行相对导入”。

解决办法:

需要将导入模块所在目录添加到系统环境变量PATH目录下才可以。

修改test.py的代码:

<span style="color:#000000"><code class="language-python"><span style="color:#000088">import</span> sys
sys.path.append(<span style="color:#009900">"./model"</span>)  <span style="color:#880000">#将model目录添加到系统环境变量path下</span>
<span style="color:#000088">from</span> model <span style="color:#000088">import</span> new_count

test = new_count()
test.add(<span style="color:#006666">2</span>, <span style="color:#006666">5</span>)</code></span>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

输出结果:7,注意如果是python2版本需要在model目录下创建init文件才行。

3.7 异常

Python用异常对象(exception object)来表示异常情况。遇到错误后,会引发异常,如果异常对象并未被处理或者捕捉,则程序就会用所谓的回溯(Traceback,一种错误信息)来终止执行。

3.7.1 认识异常

看下面的代码:

<span style="color:#000000"><code class="language-python"><span style="color:#006666">>>> </span>open(<span style="color:#009900">"abc.txt"</span>, <span style="color:#009900">'r'</span>)
Traceback (most recent call last):
  File <span style="color:#009900">"<stdin>"</span>, line <span style="color:#006666">1</span>, <span style="color:#000088">in</span> <module>
IOError: [Errno <span style="color:#006666">2</span>] No such file <span style="color:#000088">or</span> directory: <span style="color:#009900">'abc.txt'</span></code></span>
  • 1
  • 2
  • 3
  • 4

错误很明显,我们根本没创建这个文件,自然也无法open操作。我们可以视线捕捉这个异常:Python通过try…except…语句来接收并处理这个异常。

<span style="color:#000000"><code class="language-python"><span style="color:#006666">>>> </span><span style="color:#000088">try</span>:
<span style="color:#006666">... </span>    open(<span style="color:#009900">"abc.txt"</span>, <span style="color:#009900">"r"</span>)
<span style="color:#006666">... </span><span style="color:#000088">except</span> IOError:
<span style="color:#006666">... </span>    <span style="color:#000088">print</span> <span style="color:#009900">"异常了"</span>
<span style="color:#006666">... </span>
异常了</code></span>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

注意: 我们这里使用的仍然是Python2版本,所以和书中的Python3版本略有不同,以下都是按Python2版本进行演示的。

再来看下面的例子:

<span style="color:#000000"><code class="language-python"><span style="color:#006666">>>> </span><span style="color:#000088">try</span>:
<span style="color:#006666">... </span>    <span style="color:#000088">print</span> aa
<span style="color:#006666">... </span><span style="color:#000088">except</span> IOError:
<span style="color:#006666">... </span>    <span style="color:#000088">print</span> <span style="color:#009900">"异常了"</span>
<span style="color:#006666">... </span>
Traceback (most recent call last):
  File <span style="color:#009900">"<stdin>"</span>, line <span style="color:#006666">2</span>, <span style="color:#000088">in</span> <module>
NameError: name <span style="color:#009900">'aa'</span> <span style="color:#000088">is</span> <span style="color:#000088">not</span> defined</code></span>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

上面的例子,虽然捕捉异常,但是由于捕捉的异常和实际异常的错误类型并不相符,所以导致失效。

只需要更换一个正确的接收异常的类型就可以了:

<span style="color:#000000"><code class="language-python"><span style="color:#006666">>>> </span><span style="color:#000088">try</span>:
<span style="color:#006666">... </span>    <span style="color:#000088">print</span> aa
<span style="color:#006666">... </span><span style="color:#000088">except</span> NameError:
<span style="color:#006666">... </span>    <span style="color:#000088">print</span> <span style="color:#009900">"异常了"</span>
<span style="color:#006666">... </span>
异常了</code></span>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

那么,程序是怎么抛出不同类型的错误呢?

异常的抛出机制:

  1. 如果在运行时发生异常,则解释器会查找相应的处理语句(称为handler);
  2. 如果在当前函数里没有找到的话,则它会将异常传递给上层的调用函数,看看那里能不能处理;
  3. 如果在最外层(全局main)还是没有找到的话,那么解释器就会退出,同时打印出Traceback,以便让用户找到错误产生的原因。

注意: 异常不一定等于错误,有时候它只是一个警告,有时候它只是一个终止信号,例如退出循环等。

Python中所有异常都集成Exception,所以可以使用它来接收所有类型的异常:

<span style="color:#000000"><code class="language-python"><span style="color:#000088">try</span>:
    open(<span style="color:#009900">"abc.txt"</span>, <span style="color:#009900">"r"</span>)
<span style="color:#000088">except</span> Exception:
    <span style="color:#000088">print</span> <span style="color:#009900">"异常了"</span>

异常了</code></span>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

从Python 2.5之后,所有的异常类都有了新的基类BaseException,Exception同样也继承自BaseException,所以我们可以使用BaseException来接收所有类型的异常:

<span style="color:#000000"><code class="language-python"><span style="color:#006666">>>> </span><span style="color:#000088">try</span>:
<span style="color:#006666">... </span>    open(<span style="color:#009900">"abc.txt"</span>, <span style="color:#009900">"r"</span>)
<span style="color:#006666">... </span>    <span style="color:#000088">print</span> aa
<span style="color:#006666">... </span><span style="color:#000088">except</span> BaseException:
<span style="color:#006666">... </span>    <span style="color:#000088">print</span> <span style="color:#009900">"异常了"</span>
<span style="color:#006666">... </span>
异常了</code></span>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

对于这个例子来说,只要其中一行出现了异常就会打印出异常信息,但是如何才能准确知道是哪一行代码引起的异常呢,又如何让Python直接告诉我们异常的原因呢?

<span style="color:#000000"><code class="language-python"><span style="color:#006666">>>> </span><span style="color:#000088">try</span>:
<span style="color:#006666">... </span>    open(<span style="color:#009900">"abc.txt"</span>, <span style="color:#009900">"r"</span>)
<span style="color:#006666">... </span>    <span style="color:#000088">print</span> aa
<span style="color:#006666">... </span><span style="color:#000088">except</span> BaseException, e:
<span style="color:#006666">... </span>    <span style="color:#000088">print</span> e
<span style="color:#006666">... </span>
[Errno <span style="color:#006666">2</span>] No such file <span style="color:#000088">or</span> directory: <span style="color:#009900">'abc.txt'</span></code></span>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

这样就可以打印出异常的详细信息了。

注意: Python 2中使用“, e”这种方式来捕捉异常详细信息,而Python 3中使用“as msg”的方式,这是两者的区别。

Python常见的异常

异常 描述
BaseException 新的所有异常类的基类
Exception 所有异常类的基类,但继承BaseException类
AssertionError assert语句失败
FileNotFoundError 试图打开一个不存在的文件或目录
AttributeError 试图访问的对象没有属性
OSError 当系统函数返回一个系统相关的错误,包括I/O故障,如“找不到文件”或“磁盘已满”时,引发此异常
NameError 使用一个还未赋值对象的变量
IndexError 当一个序列超出了范围
SyntaxError 当解析器遇到一个语法错误时引发
KeyboardInterrupt Ctrl+C被按下,程序被强行终止
TypeError 传入的对象类型与要求不符

3.7.2 更多异常用法

异常的更多用法:try...except...else

<span style="color:#000000"><code class="language-python"><span style="color:#000088">try</span>:
    aa = <span style="color:#009900">"异常测试:"</span>
    <span style="color:#000088">print</span> aa
<span style="color:#000088">except</span> Exception <span style="color:#000088">as</span> msg:
    <span style="color:#000088">print</span> msg
<span style="color:#000088">else</span>:
    <span style="color:#000088">print</span> <span style="color:#009900">"没有异常!"</span></code></span>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

输出结果:

<span style="color:#000000"><code>异常测试:
没有异常!</code></span>
  • 1
  • 2

上面代码是因为没有异常所以执行了else,但是例如文件的关闭、锁的释放、把数据库连接返还给连接池等操作,这些操作无论是否异常都希望可以被执行,就需要用到:try...except...finally...

<span style="color:#000000"><code class="language-python"><span style="color:#000088">try</span>:
    <span style="color:#000088">print</span> aa
<span style="color:#000088">except</span> Exception <span style="color:#000088">as</span> e:
    <span style="color:#000088">print</span> e
<span style="color:#000088">finally</span>:
    <span style="color:#000088">print</span> <span style="color:#009900">"不管是否异常,我都会被执行。"</span></code></span>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

输出结果:

<span style="color:#000000"><code>name <span style="color:#009900">'aa'</span> is <span style="color:#000088">not</span> <span style="color:#000088">defined</span>
不管是否异常,我都会被执行。</code></span>
  • 1
  • 2

修改上述代码,定义aa变量:

<span style="color:#000000"><code class="language-python"><span style="color:#000088">try</span>:
    aa = <span style="color:#009900">"异常测试:"</span>
    <span style="color:#000088">print</span> aa
<span style="color:#000088">except</span> Exception <span style="color:#000088">as</span> e:
    <span style="color:#000088">print</span> e
<span style="color:#000088">finally</span>:
    <span style="color:#000088">print</span> <span style="color:#009900">"不管是否异常,我都会被执行。"</span></code></span>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

输出结果:

<span style="color:#000000"><code class="language-python">异常测试:
不管是否异常,我都会被执行。</code></span>
  • 1
  • 2

3.7.3 抛出异常

print方法只是打印异常,而raise方法可以抛出一个异常信息。

<span style="color:#000000"><code class="language-python"><span style="color:#000088">from</span> random <span style="color:#000088">import</span> randint

<span style="color:#880000"># 生成一个1到9之间的随机整数</span>
number = randint(<span style="color:#006666">1</span>, <span style="color:#006666">9</span>)

<span style="color:#000088">if</span> number % <span style="color:#006666">2</span> == <span style="color:#006666">0</span>:
    <span style="color:#000088">raise</span> NameError(<span style="color:#009900">"%d is even"</span> % number)
<span style="color:#000088">else</span>:
    <span style="color:#000088">raise</span> NameError(<span style="color:#009900">"%d is odd"</span> % number)</code></span>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

输出结果:

<span style="color:#000000"><code class="language-python">Traceback (most recent call last):
  File <span style="color:#009900">"<stdin>"</span>, line <span style="color:#006666">4</span>, <span style="color:#000088">in</span> <module>
NameError: <span style="color:#006666">3</span> <span style="color:#000088">is</span> odd</code></span>
  • 1
  • 2
  • 3

判断奇偶数与NameError之间没有任何关系,这里只是为了演示如何通过raise方法抛出各种类型的异常。

注意: raise只能使用Python中所提供的异常类,如果自定义一个abcError,会提示错误abcError未定义。

总结

本章内容只是Python语法的入门的入门,如果想要开始后面的教程,还需要有Python基础,而最佳快速入门的就是《笨方法学Python》了,有兴趣的同学可以搜索并学习。

猜你喜欢

转载自blog.csdn.net/ppw001/article/details/81408975