L3F.WIN

Github及Hexo的使用

0%

Python 基础教程

前言
Python: 一种解释型的,面向对象的,带有动态语义的高级程序设计语言。
由于IDLE所使用的字体导致我们程序的结果出现参差不齐,所以这里推荐使用Yahei Consolas Hybrid字体 密码: qbgc。

第1章 基础值是

本章将介绍如何获得所需要的软件,及简单的算法。

安装Python

下载地址

Windows

windows的安装方法很简单,双击下载后的文件,按照提示进行安装即可。
成功后,我们就可以启动IDLE了,如下图,同时按F1键可以调出完整的Python文档。
Python安装成功

Linux 和 UNIX

默认会安装Python的解释器。所以一般可以不用特意去安装。
查看Linux是否安装了Python

如果没有安装可以使用

1
2
3
apt-get install python

yum install python

来进行安装。

  1. Python2

    1
    print "Hello, World!"
  2. Python3

    1
    print("Hello, World!")

算法是什么?

算法,是程序的另外一种悦耳的说法——详细描述如何做某事。如何完成一项任务的方法

数字和表达式

表达式是计算机程序的组成部分,他用于表示值。
交互式Python解释器可以当作非常强大的计算机使用。

1
2
3
4
5
6
7
8
>>>2+2
4
>>>53672+235253
288925
>>>1/2 #python2
0
>>>1/2
0.5 #python3

当整数相除的时候,会将小数点后面的结果省略掉,所以遇到这种情况的时候,可以使用实数进行相除或是让Python改变除法的执行方法

1
>>>from __future__ import division //希望python执行普通的除法

长整型数

普通整数不能大于2147483647(也不能小于-2147483648),这个在新版的Python中已经不是很重要了。
在旧版本中,在长整型数的后面添加一个 L 即可。

十六进制和八进制

  1. 十六进制

    1
    2
    >>>0xAF
    175
  2. 八进制

    1
    2
    3
    4
    >>>010 #python2
    8
    >>>0o10 #python3
    8

变量

变量基本上就是代表(或者引用)某值的名字。

1
2
3
>>>x=3
>>>x*2
6

语句

语句是使用关键字来组成命令,告诉Python需要做什么,语句可以有输出,也可以没有输出。

获取用户输入

非常有用的 input函数

1
2
3
>>> input("The meaning of line: ")
The meaning of line: 42
42

函数

函数就像可以用来实现特定功能的小程序一样。函数可以做很多事情,我们也可以自定义函数
例如

1
2
3
4
5
6
7
8
9
10
11
>>>2**3
8
>>>pow(2,3) #pow就是幂函数
8
>>> abs(-100) #绝对值函数
100
>>> round(3.1415926) #取整函数(四舍五入)
3
>>> import math
>>> math.floor(3.962) #取整函数,需引入math模块才可以使用
3

模块

可以把模块想象成导入到Python以增强其功能的扩展。需要使用import来导入模块。使用时使用 模块.函数 的格式来执行
为了能够不每次调用函数的时候,都要写模块的名字,可以使用 from 模块 import 函数 这种形式

1
2
3
>>> from math import floor
>>> floor(3.9888)
3

不过为了管理的方便和以后代码的易读性,推荐使用 模块.函数 的格式。

cmath 和复数

sqrt函数用于计算一个数字的平方根。如果数值为负数则会弹出错误提示

1
2
3
4
5
6
>>> from math import sqrt
>>> sqrt(-1)
Traceback (most recent call last):
File "<pyshell#11>", line 1, in <module>
sqrt(-1)
ValueError: math domain error

如何解决这个问题呢,使用cmath

1
2
3
>>> import cmath
>>> cmath.sqrt(-1)
1j #1j是个叙述,以j结尾

回到_future_

__future__是个神奇的模块在后面的章节将详细说明。

保存并执行程序

我们可以使用各种文本编辑器,如visual studio Code 或是 Atom 也可以是 EditPlus等等,也可以使用 IDLE python自带的编辑功能
在窗口选择 File → New File就会打开一个新窗口,而且没有交互式提示符,你可以在这里写入您的代码
并保存到你指定的文件夹。保存好后,你可以使用 Ctrl + F5来执行你的代码,在你第一个打开的IDLE中将会显示结果。

使用IDLE来保存并执行程序

1
2
3
4
5
6
# name = raw_input("What is your name")  python3 已经取消了raw_input, 通用Input
name = input("What is your name:")
print( "Hello. " + name + "!")
=============================== RESTART: D:\D\python\test\hello.py ===============================
What is your name:winbug
Hello. winbug!

也不用担心raw_input 和 input 的区别了,再Python3中已经将两者统合了。

也可以在命令提示符(windows)和 终端 (Linux)下,直接使用 python + filename.py运行程序

注释

python下使用 # 进行注释,作为程序员,注释是非常有用的,它帮助程序员去理解程序代码

字符串

字符串一般用引号包围,需要转义的时候,使用转义符 \ 进行转义

1
2
3
4
5
name = input("What is your name:")
print( "\"Hello. " + name + "!\", I said that")
=============================== RESTART: D:\D\python\test\hello.py ===============================
What is your name:winbug
"Hello. winbug!", I said that

如何 拼接字符串
在python里面,和Javascript的拼接方式相同,大家都是使用加号来拼接字符串

1
2
3
x = "Hello. "
y = "World!"
print( x + y ) #Hello. World!

学习 str函数 和 repr函数
str函数,它会把值转换成为合理形式的字符串。
repr函数,它会创建一个字符串,它以合法的Python表达式的形式来表示值。
(需要注意,再python3中长整型已经不需要在数字的后面加L了,否则会出错)

1
2
3
4
5
6
7
8
9
10
x = "Hello, World!"
y = 1000000000000000000000000000000000000000000
z = str(x)
print(z)
z= str(y)
print(z)
z = repr(x)
print(z)
z = repr(y)
print(z)

(需要注意,phthon3 之后已经可以不适用反引号来读取变量了)

长字符串
使用三个引号,也可以使用反斜线进行转义

1
2
3
4
5
6
7
8
9
10
11
12
13
14
print("""This is a very long string
It continues here.
And it's not over yet.
'Hello, world!'""")

print("Hello, \
world!\
I am Chinese")
=============================== RESTART: D:\D\python\test\hello.py ===============================
This is a very long string
It continues here.
And it's not over yet.
'Hello, world!'
Hello, world!I am Chinese

原始字符串
在普通字符串中,反斜线有特殊的作用,他会转义。
如换行符 \n 还有很多,在反斜线混入的情况下怎么办,可以使用双反斜线,或是在字符串前加个字母r

1
2
3
4
5
6
7
8
9
10
print("This is a very long string\nIt continues here.\nAnd it's not over yet.\n'Hello, world!'")
print("C:\\windows\\info")
print(r"C:\192.168.0.121\backupHD\nikon\nikonplaza\psd\bj")
=============================== RESTART: D:\D\python\test\hello.py ===============================
This is a very long string
It continues here.
And it's not over yet.
'Hello, world!'
C:\windows\info
C:\192.168.0.121\backupHD\nikon\nikonplaza\psd\bj

Unicode字符串
为了表示更多的字符串,包括世界上大多数语言的特殊字符,需要使用Unicode字符串,在字符串的前面加个字母u


第1章的新函数

函数 描述
abs(number) 返回数字的绝对值
cmath.sqrt(number) 返回平方根,也可以应用于负数
float(object) 将字符串和数字转换成为浮点数
help() 提供交互式帮助
input(prompt) 获取用户输入
int(object) 将字符串和数字转换为整数
long(object) 将字符串和数字转换为长整型数
math.ceil(number) 返回数的上入整数,返回值的类型为浮点数
math.floor(number) 返回数的下舍整数,返回值的类型为浮点数
math.sqrt(number) 返回平方根,不适用于负数
pow(x,y[, z]) 返回x的y次幂
repr(object) 返回值的字符串表示形式
round(number[, ndigits]) 根据给定的精度对数字进行四舍五入
str(object) 将值转换为字符串

第2章 列表和元组

数据结构
是通过某种方式组织在一起的数据元素的集合,这些数据元素可以是数字或者字符,甚至是其他数据结构。

序列概览

Python 包含6种内建的序列

  1. 列表 ★
  2. 元组 ★
  3. 字符串
  4. Unicode字符串
  5. buffer对象
  6. xrange对象

列表和元组的区别,列别可以修改,元组则不能。

通用序列操作

所有序列都可以进行,索引,分片,加,乘,检查某个元素是否属于序列的成员。python还提供了对序列长度,最大元素和最小元素的函数。

索引

所有序列都是有编号的,从0开始递增。* -1 * 代表从最后一个元素开始计数

1
2
3
4
5
6
greeting = "Hello"  #字符串本身就是一个个字符组成。
print(greeting[0])
print(greeting[-1])
=============================== RESTART: D:\D\python\test\hello.py ===============================
H
o

如果一个函数调用返回一个序列,那么可以直接对返回结果进行索引操作。

1
2
3
4
5
fouth = input("Year: ")[3]
print(fouth)
=============================== RESTART: D:\D\python\test\hello.py ===============================
Year: 2018
8

经典小程序
输出日期

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
26
27
28
29
30
31
32
33
34
35
36
37
months = [
'January',
'February',
'March',
'April',
'May',
'June',
'July',
'August',
'September',
'October',
'November',
'December'
]

#以1~31的数字作为结尾的列表
endings = ['st', 'nd', 'rd'] + 17 * ['th'] \
+ ['st', 'nd', 'rd'] + 7 * ['th'] \
+ ['st']

year = input('Year: ')
month = input('Month(1-12): ')
day = input('Day(1-31): ')

month_number = int(month)
day_number = int(day)

#记得要将月份和天数减1,以获得正确的索引
month_name = months[month_number - 1]
ordinal = day + endings[day_number - 1]

print(month_name + ' ' + ordinal + '. ' + year)
=============================== RESTART: D:\D\python\test\hello.py ===============================
Year: 2018
Month(1-12): 5
Day(1-31): 21
May 21st. 2018

分片

与使用索引来访问单个元素类似,可以使用分片操作来访问一定范围内的元素。分片通过冒号相隔的两个索引来实现。

1
2
3
4
tag = "<a href='http://www.l3f.win'>Python web site</a>"
print(tag[9:27]) #第1个索引的元素是包含在分片内的,而第2个则不包含在分片内
=============================== RESTART: D:\D\python\test\hello.py ===============================
http://www.l3f.win
  1. 优雅的捷径
    访问后3个元素
    1
    2
    3
    4
    5
    numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9 ,10]
    print(numbers[7:10])
    print(numbers[-3:])
    =============================== RESTART: D:\D\python\test\hello.py ===============================
    [8, 9, 10]
  2. 更大的步长
    分片的最后一个参数是步长,步长通常都是隐式设置的,默认值为1
    步长不可以为0,但是可以为负数,即从右到左提取元素。
    1
    2
    3
    4
    5
    6
    7
    8
    numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9 ,10]
    print(numbers[0:10:2])
    =============================== RESTART: D:\D\python\test\hello.py ===============================
    [1, 3, 5, 7, 9]

    print(numbers[::-2])
    =============================== RESTART: D:\D\python\test\hello.py ===============================
    [10, 8, 6, 4, 2]

序列相加

通过使用加号可以进行序列的连接操作:

1
2
3
4
number = [1,2,3,4,5]
print(number + [6,7,8,9,10])
=============================== RESTART: D:\D\python\test\hello.py ===============================
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

乘法

用数字x乘以一个序列会生成新的序列,新的序列中,原来的序列将被重复x次

1
2
3
print("python" * 5)
=============================== RESTART: D:\D\python\test\hello.py ===============================
pythonpythonpythonpythonpythonssss

初始化一个长度为10的列表,内容为空

1
2
3
4
sequence = [None] * 10
print(sequence)
=============================== RESTART: D:\D\python\test\hello.py ===============================
[None, None, None, None, None, None, None, None, None, None]

经典小程序
创建一个带边框的文字

1
2
3
4
5
6
7
8
9
10
11
12
sentence = input("Sentence: ")
screen_width = 80
text_width = len(sentence)
box_width = text_width + 6
left_margin = (screen_width - box_width) // 2

print('\n' +
' ' * left_margin + '+' + '-' * (box_width - 2) + '+ \n' +
' ' * left_margin + '| ' + ' ' * text_width + ' |\n' +
' ' * left_margin + '| ' + sentence + ' |\n' +
' ' * left_margin + '| ' + ' ' * text_width + ' | \n' +
' ' * left_margin + '+' + '-' * (box_width - 2) + '+ \n')

成员资格(是否存在元素)

为了检查一个值是否在序列种,使用in运算符

1
2
3
4
permissions = 'rw'
print('w' in permissions)
=============================== RESTART: D:\D\python\test\hello.py ===============================
True

简单用户认证
通过序列来认证用户登录

1
2
3
4
5
6
7
8
9
10
11
12
database = [
['albert', '1234'],
['winbug','0000'],
['jone','2345']
]
username = input('User name: ')
password = input("Pin code:")
if [username, password] in database : print('Access Granted')
=============================== RESTART: D:\D\python\test\hello.py ===============================
User name: winbug
Pin code:0000
Access Granted

长度,最小值,最大值

内建函数len, min, max非常有用

1
2
3
4
5
6
7
8
number = [100, 34, 678]
print(len(number)) #序列长度
print(min(number)) #序列中最小值
print(max(number)) #序列中最大值
=============================== RESTART: D:\D\python\test\hello.py ===============================
3
34
678

列表

list函数

因为字符串不能像列表一样被修改,所以有时根据字符串创建列表会很有用。

1
2
3
4
string = list("Hello")
print(string)
=============================== RESTART: D:\D\python\test\hello.py ===============================
['H', 'e', 'l', 'l', 'o']

(list函数适用于所有类型的序列,而不只是字符串)

基本的列表操作

列表可以使用所有适用于序列的标准操作,索引,分片,连接,惩罚。列表是可修改的。

  1. 改变列表: 元素赋值
    列表通过使用索引标记来为某个元素赋值
    1
    2
    3
    4
    5
    x = [1,1,1]
    x[1] = 2
    print(x)
    =============================== RESTART: D:\D\python\test\hello.py ===============================
    [1, 2, 1]
  2. 删除元素
    使用del语句
    1
    2
    3
    4
    5
    name = ['winbug', 'admin', 'lijianguo']
    del name[2]
    print(name)
    =============================== RESTART: D:\D\python\test\hello.py ===============================
    ['winbug', 'admin']
  3. 分片赋值
    程序可以一次为多个元素赋值
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    name = list("winbug")
    print(name)
    name[3:] = list('dows')
    print(name)
    name[3:] = []
    print(name)
    =============================== RESTART: D:\D\python\test\hello.py ===============================
    ['w', 'i', 'n', 'b', 'u', 'g']
    ['w', 'i', 'n', 'd', 'o', 'w', 's']
    ['w', 'i', 'n']

列表方法

方法: 与某些对象有紧密联系的函数
方法的调用: 对象.方法(参数)

  1. append
    用于在列表末尾追加新的对象
    1
    2
    3
    4
    5
    lst = [1,2,3]
    lst.append(4)
    print(lst)
    =============================== RESTART: D:\D\python\test\hello.py ===============================
    [1, 2, 3, 4]
  2. count
    统计某个元素在列表中出现的次数
    1
    2
    3
    4
    5
    6
    7
    8
    9
    lis = ['to','be','or','not','to','be']
    print(lis.count('to'))
    x = [[1,2],1,1,[2,1,[1,2]]]
    print(x.count(1))
    print(x.count([1,2]))
    =============================== RESTART: D:\D\python\test\hello.py ===============================
    2
    2
    1
  3. extend
    可以在列表的末尾一次性追加两一个序列中的多个值
    1
    2
    3
    4
    5
    6
    a = [1,2,3]
    b = [4,5,6]
    a.extend(b)
    print(a)
    =============================== RESTART: D:\D\python\test\hello.py ===============================
    [1, 2, 3, 4, 5, 6]
    extend和连接很像,但是有着本质的区别,extend是扩展原有的列表,而连接则是创建一个原有列表的副本
  4. index
    用于从列表中找出某个值第一个匹配项的索引位置
    1
    2
    3
    4
    knights = ['We', 'are', 'the', 'knights', 'Who', 'say', 'ni']
    print(knights.index('Who'))
    =============================== RESTART: D:\D\python\test\hello.py ===============================
    4
  5. insert
    用于将对象插入到列表中
    1
    2
    3
    4
    5
    numbers = [1,2,3,5,6,7]
    numbers.insert(3,'four')
    print(numbers)
    =============================== RESTART: D:\D\python\test\hello.py ===============================
    [1, 2, 3, 'four', 5, 6, 7]
  6. pop
    移除列表中的一个元素(默认为最后一个),并返回该元素的值
    1
    2
    3
    4
    5
    6
    7
    numbers = [1,2,3,5,6,7]
    x = numbers.pop(4)
    print(numbers)
    print(x)
    =============================== RESTART: D:\D\python\test\hello.py ===============================
    [1, 2, 3, 5, 7]
    6
  7. remove
    用于移除列表中某个值的第一个匹配项,它不同于pop,不会返回值
    1
    2
    3
    4
    5
    numbers = [1,2,3,5,6,3,7]
    numbers.remove(3)
    print(numbers)
    =============================== RESTART: D:\D\python\test\hello.py ===============================
    [1, 2, 5, 6, 3, 7]
  8. reverse
    将列表中的元素反向存放
    1
    2
    3
    4
    5
    numbers = [1,2,3,5,6,3,7]
    numbers.reverse()
    print(numbers)
    =============================== RESTART: D:\D\python\test\hello.py ===============================
    [7, 3, 6, 5, 3, 2, 1]
  9. sort
    用于在原位置对列表进行排序。
    1
    2
    3
    4
    5
    numbers = [17,5,2,9,20]
    numbers.sort()
    print(numbers)
    =============================== RESTART: D:\D\python\test\hello.py ===============================
    [2, 5, 9, 17, 20]
    如果想不影响原位置的值进行索引,我们可以使用sorted函数。
    1
    2
    3
    4
    5
    6
    7
    x = [4,6,2,1,7,9]
    y = sorted(x)
    print(x)
    print(y)
    =============================== RESTART: D:\D\python\test\hello.py ===============================
    [4, 6, 2, 1, 7, 9]
    [1, 2, 4, 6, 7, 9]
  10. 高级排序
    cmp函数(python3后不能使用)
    sort方法的两个可选参数key和reverse
    1
    2
    3
    4
    5
    6
    7
    8
    x = ['aardvark','abalone','acme','add','aerate']
    x.sort(key=len)
    print(x)
    x.sort(reverse=True)
    print(x)
    =============================== RESTART: D:\D\python\test\hello.py ===============================
    ['add', 'acme', 'aerate', 'abalone', 'aardvark']
    ['aerate', 'add', 'acme', 'abalone', 'aardvark']

元组:不可变序列

元组与列表一样,也是一种序列,唯一的不同就是不能修改
创建方法,用逗号分隔开一些值,就自动的创建了元组,一般表示用括号()

1
2
3
4
5
6
7
8
9
10
x = 1,2,3 #使用,号创建元组
print(x)
y = () #使用括号,创建空元组
print(y)
z=4, #使用值 + , 创建单元组
print(z)
=============================== RESTART: D:\D\python\test\hello.py ===============================
(1, 2, 3)
()
(4,)

tuple函数

tuple函数与list函数基本上一样,以一个序列作为参数并把它转换成为元组,如果参数就是元组会被原样返回

1
2
3
4
5
print(tuple([1,3,4]))
print(tuple(("a","b","c")))
=============================== RESTART: D:\D\python\test\hello.py ===============================
(1, 3, 4)
('a', 'b', 'c')

基本元组操作

除了创建和访问元组元素之外,基本没有什么其他操作。

1
2
3
4
number = 2,3,4,5,6
print(number[3])
=============================== RESTART: D:\D\python\test\hello.py ===============================
5

元组的意义

  1. 元组可以在映射中当作键使用,而列表则不行。
  2. 元组作为很多内建函数和方法的返回值存在。

第2章的新函数

函数 描述
cmp(x, y) 比较两个值,python3之后停止使用
len(seq) 返回序列的长度
list(seq) 把序列转换成列表
max(args) 返回序列或者参数集合中的最大值
min(args) 返回序列或者参数集合中的最小值
reversed(seq) 对序列进行反向迭代
sorted(seq) 返回已排序的包含seq所有元素的列表
tuple(seq) 靶序列转换成远足

第3章 使用字符串

基本字符串操作

所有标准的序列操作对字符串同样使用,字符串是不可以修改的

字符串格式化:精简版

字符串操作符 百分号%来实现

1
2
3
4
5
forma = "Hello, %s, %s enough for ya?"
values = ("world", "Hot")
print(forma % values)
=============================== RESTART: D:\D\python\test\hello.py ===============================
Hello, world, Hot enough for ya?

(如果在格式化的字符串里面包含%号的话,必须使用%%)

字符串格式化:完整版

字符串格式化右侧是元组的情况下,则其中的每一个元素都会被单独格式化,每个值都需要一个对应的转化说明符

基本的转换说明符
(1) %字符: 标记转换说明符的开始。
(2) 转换标记(可选): -表示左对齐, +表示在转换值之前要加上正负号, “”(空白字符)表示正数之前保留空格,0表示转换值若位数不够则用0填充
(3) 最小字段宽度(可选): 转换后的字符串至少应该具有该值指定的宽度。
(4) 点(.)后跟精度值(可选): 如果转换的是实数,精度值就表示出现在小数点后的位数。
(5) 转换类型

转换类型 含义
d, i 带符号的十进制整数
o 不带符号的八进制
u 不带符号的十进制
x 不带符号的十六进制(小写)
X 不带符号的十六进制(大写)
e 科学记数法表示的浮点数(小写)
E 科学记数法表示的浮点数(大写)
f, F 十进制浮点数
g 如果指数大于-4或者小于精度值则和e相同,其他情况与f相同
G 如果指数大于-4或者小于进度值则和E相同,其他情况则于F相同
C 单字符(接受整数或者单字符字符串)
r 字符串(使用repr转换任意Python对象)
s 字符串(使用str转换任意Python对象)

简单转换

1
2
3
4
5
print( 'Price of eggs: $%d' %42)
print( 'Using str: %s' %42)
=============================== RESTART: D:\D\python\test\hello.py ===============================
Price of eggs: $42
Using str: 42

字段宽度和精度

转换说明符可以包括字段宽度和精度

1
2
3
4
5
6
7
8
9
10
from math import pi
print('%10f' % pi) #字段宽10
print('%10.2f' % pi) #字段宽10,精度2
print('%.2f' % pi) #精度2
print('%.*s' % (5, 'Guido van Rossum')) #使用*号最为字段宽度或精度,此时数值会从元组中读出
=============================== RESTART: D:\D\python\test\hello.py ===============================
3.141593
3.14
3.14
Guido

符号,对齐和0填充

1
2
3
4
from math import pi
print('%-10.2f' % pi)
=============================== RESTART: D:\D\python\test\hello.py ===============================
3.14

字符串格式化示例
使用给定的宽度打印格式化后的价格表

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
26
27
28
29
width = int(input('Please enter width:')) #确保输入的内容转化为数值

price_width = 10
item_width = width - price_width

header_format = '%-*s%*s'
formats = '%-*s%*.2f'

print('=' * width)
print(header_format % (item_width, 'Item', price_width, 'Price'))
print('-' * width)
print(formats % (item_width, 'Apples', price_width, 0.4))
print(formats % (item_width, 'Pears', price_width, 0.5))
print(formats % (item_width, 'Cantaloupes', price_width, 1.92))
print(formats % (item_width, 'Dried Apricots(16 oz.)', price_width, 8))
print(formats % (item_width, 'Prunes (4 1bs.)', price_width, 12))

print('=' * width)
=============================== RESTART: D:\D\python\test\hello.py ===============================
Please enter width:35
===================================
Item Price
-----------------------------------
Apples 0.40
Pears 0.50
Cantaloupes 1.92
Dried Apricots(16 oz.) 8.00
Prunes (4 1bs.) 12.00
===================================

字符串方法

  1. find
    find方法可以在一个较长得字符串中查找子字符串。它返回子串所在位置得最左端索引。如果没有则返回-1
    1
    2
    3
    4
    5
    6
    kotoba = "With a moo-moo here, and a moo-moo there"
    print(kotoba.find('moo'))
    print(kotoba.find('my'))
    =============================== RESTART: D:\D\python\test\hello.py ===============================
    7
    -1
    find方法不返回布尔值,所以返回0得时候,是发现得位置
  2. join
    join方法是split方法的逆方法,用来在队列中添加元素
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    #seq = [1,2,3,4,5]
    sep = '+'
    #print(sep.join(seq)) #连接数字列表会报错

    seq = ['1','2','3','4','5']
    print(sep.join(seq))

    dirs = '', 'usr', 'bin', 'env'
    print('/'.join(dirs))

    print('C:' + '\\'.join(dirs))
    =============================== RESTART: D:\D\python\test\hello.py ===============================
    1+2+3+4+5
    /usr/bin/env
    C:\usr\bin\env
  3. lower
    返回字符串的小写字母版
    1
    2
    3
    4
    strs = 'Trondheim Hammer Dance'
    print(strs.lower())
    =============================== RESTART: D:\D\python\test\hello.py ===============================
    trondheim hammer dance
  4. replace
    返回某个字符串的所有匹配项均被提花之后的字符串
    1
    2
    3
    4
    strs = 'This is a test'
    print(strs.replace('is', 'eez'))
    =============================== RESTART: D:\D\python\test\hello.py ===============================
    Theez eez a test
  5. split
    他是join的逆方法,用来将字符串分割成序列
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    strs = "1+2+3+4+5"
    print(strs.split('+'))

    dirs = "/usr/bin/env"
    print(dirs.split('/'))

    dirs = "C:\\usr\\bin\\env"
    print(dirs.split('\\'))
    =============================== RESTART: D:\D\python\test\hello.py ===============================
    ['1', '2', '3', '4', '5']
    ['', 'usr', 'bin', 'env']
    ['C:', 'usr', 'bin', 'env']
  6. strip
    返回去除两侧(不包括内部)空格的字符串
    1
    2
    3
    4
    strs = "   Hi i am a good man    "
    print(strs.strip())
    =============================== RESTART: D:\D\python\test\hello.py ===============================
    Hi i am a good man
  7. translate
    replace方法一样,可以替换字符串中的某些部分,但是和前者的不同的是,translate方法只处理单个字符。优点是效率快
    1
    2
    3
    4
    5
    table = str.maketrans('cs', 'kz') #python3之前都在使用 from string import maketrans python3之后使用内建函数str.maketrans
    strs = "this is an incredible test"
    print(strs.translate(table))
    =============================== RESTART: D:\D\python\test\hello.py ===============================
    thiz iz an inkredible tezt

第4章 字典:当索引不好用时

通过名字引用值得数据结构,这种结构类型被称为映射。字典是python中唯一内建得映射类型

字典的使用

  1. 表征游戏棋盘的状态,每个键都是由坐标值组成的元组
  2. 存储文件修改次数,用文件名作为键
  3. 数字电话/地址簿

创建和使用字典

字典由多个键及对应的值(项)构成的对组成

1
2
3
4
phonebook = {'Alice':'2341', 'winbug':'9012','Cecil':'3258'}
print(phonebook['winbug'])
=============================== RESTART: D:\D\python\test\hello.py ===============================
9012

——字典中的键是唯一的,而值并不唯一——

dict函数

一般可以通过dict函数对有一定规则的序列或是通过关键字参数创建字典。

1
2
3
4
5
6
7
8
item = [('name','Gumby'),('age', 42)]
d = dict(item)
print(d)
d = dict(name='Gumby', age=42)
print(d)
=============================== RESTART: D:\D\python\test\hello.py ===============================
{'name': 'Gumby', 'age': 42}
{'name': 'Gumby', 'age': 42}

基本字典操作

字典的基本操作与序列类似

  1. len(d)返回d中项的数量
  2. d[k]返回相关联到键k上的值
  3. d[k]=v将值v关联到键k上
  4. del d[k]删除键为k的项
  5. k in d检查d中是否有含有键为k的项

字典中查找的是键,列表中查找的是值

字典的特点
第一点,键可以为任何不可变类型
第二点,将值连接到指定位置

电话本简单示例
使用简单的数据库,进行查找

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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
people = {
'Alice':{
'phone': '2341',
'addr':'Foo drive 23'
},
'Winbug':{
'phone': '9012',
'addr':'Beijing street 42'
},
'Cecil':{
'phone': '3158',
'addr':'Baz avenue 90'
}
}

labels = {
'phone': 'phone number',
'addr': 'address'
}

name = input("Name: ")

request = input("Phone number(p) or address(a)?")
#使用正确的键,查找电话号码还是住址
if request == 'p' : key = 'phone'
if request == 'a' : key = 'addr'

#如果名字有效才打印信息
if name in people : print("%s's %s is %s." % (name, labels[key], people[name][key]))

=============================== RESTART: D:\D\python\test\hello.py ===============================
Name: Winbug
Phone number(p) or address(a)?p
Winbug's phone number is 9012.
>>>
=============================== RESTART: D:\D\python\test\hello.py ===============================
Name: Winbug
Phone number(p) or address(a)?a
Winbug's address is Beijing street 42.

字典的格式化字符串

字典的格式化字符串,在%号后面可以加上(键),后面再跟上其他说明元素。

1
2
3
4
phonebook = {'Alice':'2341', 'winbug':'9012','Cecil':'3258'}
print("Cecil's phone number is %(Cecil)s." % phonebook)
=============================== RESTART: D:\D\python\test\hello.py ===============================
Cecil's phone number is 3258.

字典方法

  1. clear
    清除字典中所有的项。无返回值
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    phonebook = {'Alice':'2341', 'winbug':'9012','Cecil':'3258'}
    c_phonebook = phonebook
    phonebook = {} #将phonebook指向新的字典
    print(c_phonebook)
    phonebook = c_phonebook #将phonebook重新指向c_phonebook的字典
    phonebook.clear()
    print(c_phonebook)
    =============================== RESTART: D:\D\python\test\hello.py ===============================
    {'Alice': '2341', 'winbug': '9012', 'Cecil': '3258'}
    {}
  2. copy
    返回一个具有相同键值的薪字典(浅复制)
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    x = {'username': 'admin',
    'machines':['foo','bar','baz']
    }
    y = x.copy()
    y['username'] = 'winbug'
    y['machines'].remove('bar')
    print(y)
    print(x)
    =============================== RESTART: D:\D\python\test\hello.py ===============================
    {'username': 'winbug', 'machines': ['foo', 'baz']}
    {'username': 'admin', 'machines': ['foo', 'baz']}
    当在副本中替换值的时候,原始字典不受影响,如果修改了某个值,原始的字典也会改变,因为同样的值也存储在原字典中。
    为了避免浅复制带来的这种问题。可以使用deepcopy来解决
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    from copy import deepcopy
    x = {'username': 'admin',
    'machines':['foo','bar','baz']
    }
    y = deepcopy(x)
    x['machines'].append('supper')
    print(x)
    print(y)
    =============================== RESTART: D:\D\python\test\hello.py ===============================
    {'username': 'admin', 'machines': ['foo', 'bar', 'baz', 'supper']}
    {'username': 'admin', 'machines': ['foo', 'bar', 'baz']}
  3. fromkeys
    使用给定的键建立新的字典,每个键默认对应的值为none
    1
    2
    3
    4
    5
    newd = {}.fromkeys(['name', 'age'],'Unknown') #默认值为None,指定的场合,加参数
    print(newd)
    =============================== RESTART: D:\D\python\test\hello.py ===============================
    {'name': None, 'age': None}
    {'name': 'Unknown', 'age': 'Unknown'}
  4. get
    是一个很宽松的访问字典项的方法,如果试图访问字典中不存在的项时不会报错
    1
    2
    3
    4
    5
    6
    newd =  {'username': 'admin', 'machines': ['foo', 'bar', 'baz']}
    print(newd.get('name', 'N/A')) #默认为None,也可以自己添加参数
    print(newd.get('username'))
    =============================== RESTART: D:\D\python\test\hello.py ===============================
    N/A
    admin
  5. has_key(python3 已经删除此方法)
    可以检查字典中是否含有给出的键
    1
    2
    3
    4
    5
    newd =  {'username': 'admin', 'machines': ['foo', 'bar', 'baz']}
    #print(newd.has_key('name')) #python3之后已经不存在has_key方法
    print('machines' in newd)
    =============================== RESTART: D:\D\python\test\hello.py ===============================
    True
  6. items和iteritems
    items将所有的字典项以列表的方式返回
    1
    2
    3
    4
    newd =  {'username': 'admin', 'machines': ['foo', 'bar', 'baz']}
    print(newd.items())
    =============================== RESTART: D:\D\python\test\hello.py ===============================
    dict_items([('username', 'admin'), ('machines', ['foo', 'bar', 'baz'])])
    iteritems和items的作用大致相同,返回一个迭代对象而不是列表
  7. keys和iterkeys
    将字典中的键以列表的形式返回。而iterkeys则返回针对键的迭代器
    1
    2
    3
    4
    5
    newd =  {'username': 'admin', 'machines': ['foo', 'bar', 'baz']}
    print(newd.keys())
    #print(newd.iterkeys()) #python3中iterkeys已经删除
    =============================== RESTART: D:\D\python\test\hello.py ===============================
    dict_keys(['username', 'machines'])
  8. pop
    用来获得对应于给定键的值,然后将这个键-值对从字典中移除
    1
    2
    3
    4
    5
    6
    newd =  {'username': 'admin', 'machines': ['foo', 'bar', 'baz']}
    print(newd.pop('username'))
    print(newd)
    =============================== RESTART: D:\D\python\test\hello.py ===============================
    admin
    {'machines': ['foo', 'bar', 'baz']}
  9. popitem
    popitem会弹出随机项,因为字典没有“最后的元素”或者其他有关顺序的概念
    1
    2
    3
    4
    5
    6
    newd =  {'username': 'admin', 'machines': ['foo', 'bar', 'baz']}
    print(newd.popitem())
    print(newd)
    =============================== RESTART: D:\D\python\test\hello.py ===============================
    ('machines', ['foo', 'bar', 'baz'])
    {'username': 'admin'}
  10. setdefault
    类似与get方法,能够获得给定键相关的值,除此之外,setdefault还能在字典中不含有给定值的情况下设定相应的键值
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    d = {}
    print(d.setdefault('name', '啥都没有'))
    print(d)
    d['name'] = 'winbug'
    print(d.setdefault('name'))
    print(d)
    =============================== RESTART: D:\D\python\test\hello.py ===============================
    啥都没有
    {'name': '啥都没有'}
    winbug
    {'name': 'winbug'}
  11. update
    可以利用一个字典项更新另外一个字典
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    d={
    'title': 'Python Web Site',
    'url': 'https://www.l3f.win',
    'changed': 'Mar 14 22:09:15 MET 2018'
    }
    x={'title': 'Python Language Website'}

    d.update(x)
    print(d)
    =============================== RESTART: D:\D\python\test\hello.py ===============================
    {'title': 'Python Language Website', 'url': 'https://www.l3f.win', 'changed': 'Mar 14 22:09:15 MET 2018'}
  12. values和itervalues
    以列表的形式返回字典中的值,与返回键的列表不同,返回值可以包含重复的元素
    1
    2
    3
    4
    5
    6
    7
    8
    d={}
    d[1] = 1
    d[2] = 2
    d[3] = 3
    d[4] = 1
    print(d.values())
    =============================== RESTART: D:\D\python\test\hello.py ===============================
    dict_values([1, 2, 3, 1])

第5章 条件,循环和其他语句

使用逗号输出

print使用逗号可以打印多个表达式。

1
2
3
print(1, 2, 3, "I am a people")
=============================== RESTART: D:\D\python\test\hello.py ===============================
1 2 3 I am a people

把某件事作为另一件事导入

1
2
3
4
5
6
7
8
9
10
import somemodule
from somemodule import somefunction
from somemodule import somefunction, anotherfunction, yetanotherfunction
from somemodule * #只有确认自己想要从给定的模块导入所有功能时,才应该使用最后一个版本。
#如果两个模块都有同名方法,使用以下方法
module1.open(...)
module2.open(...)
#或者在导入的时候提供别名
import math as foobar
foobar.sqrt(4)

赋值魔法

序列解包

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#多个赋值操作
x, y, z = 1, 2, 3

print(x, y, z)
#交换变量
x, y = y, x
print(x, y, z)
#序列解包
values = 1, 2, 3
print(values)
x, y ,z = values
print(x)
scoundrel = {'name': 'Robin', 'girlfriend': 'Mrion'}
key, value = scoundrel.popitem()
print(key)
print(value)
=============================== RESTART: D:\D\python\test\hello.py ===============================
1 2 3
2 1 3
(1, 2, 3)
1
girlfriend
Mrion

链式赋值

将同一个值赋给多个变量

1
2
3
x=y= somefunction()
x = somefunction()
y = x

增量赋值

+=, -=, *= 等计算

语句块:缩排的乐趣

python语句中使用冒号开始: 块中的每个语句都是缩进的。当回退到和已经闭合的块一样的缩进量时,就表示当前块已经结束

条件和条件语句

bool函数 可以转换其他值为布尔值

1
2
3
4
5
6
7
8
9
10
11
12
13
temp = "I think, therefore I am"
print(bool(temp))
temp = 42
print(bool(temp))
temp = ''
print(bool(temp))
temp = 0
print(bool(temp))
=============================== RESTART: D:\D\python\test\hello.py ===============================
True
True
False
False

条件执行和if语句

1
2
3
4
5
6
7
8
9
10
name = input("What is your name:")
if name.endswith('Gumby'):
print("Hello, Mr. Gumby")
else:
print("Hello, " + name)
=============================== RESTART: D:\D\python\test\hello.py ===============================
What is your name:winbug Gumby
Hello, Mr. Gumby
What is your name:winbug
Hello, winbug

elif子句

如需检查多个条件的时候使用

1
2
3
4
5
6
7
8
9
10
11
12
13
num = int(input('Enter a number: '))
if num > 0:
print("The number is positive")
elif num < 0:
print("The number is negative")
else:
print("The number is Zero")
=============================== RESTART: D:\D\python\test\hello.py ===============================
Enter a number: 25
The number is positive
=============================== RESTART: D:\D\python\test\hello.py ===============================
Enter a number: 0
The number is Zero

更复杂的条件

Python中的比较运算符
表达式 描述
x == y x等于y
x < y x小于y
x > y x大于y
x >= y x大于等于y
x <= y x小于等于y
x != y x不等于y
x is y x和y是同一个对象
x is not y x和y是不同的对象
x in y x是y容器的成员
x not in y x不是y容器的成员

断点

再编程过程中需要通过在指定位置增加断点来提示我们这个地方出错

1
2
3
4
5
6
7
8
9
age = 10
assert 0 < age < 100
age = -1
assert 0 < age < 100, '这里要大于0'
=============================== RESTART: D:\D\python\test\hello.py ===============================
Traceback (most recent call last):
File "D:\D\python\test\hello.py", line 4, in <module>
assert 0 < age < 100, '这里要大于0'
AssertionError: 这里要大于0

循环

while循环

1
2
3
4
5
6
7
8
x = 1
while x <= 100:
print(x)
x += 1
=============================== RESTART: D:\D\python\test\hello.py ===============================
1
2
*****100

for循环

1
2
3
4
5
6
7
8
9
words = ['this', 'is', 'an', 'ex', 'parrot']
for word in words:
print(word)
=============================== RESTART: D:\D\python\test\hello.py ===============================
this
is
an
ex
parrot

Range函数类似于分片,它包含下限,但不包含上限

1
2
3
4
5
6
for number in range(1, 101):
print( number )
=============================== RESTART: D:\D\python\test\hello.py ===============================
1
2
*****100

循环遍历字典元素

1
2
3
4
5
6
7
8
9
10
d = {'x': 1,
'y': 2,
'z': 3}

for key in d:
print('Key ' + key + 'corresponds to ' + str(d[key]))
=============================== RESTART: D:\D\python\test\hello.py ===============================
Key xcorresponds to 1
Key ycorresponds to 2
Key zcorresponds to 3

迭代工具

  1. 并行迭代
    zip函数,可以进行并行迭代,把两个序列“压缩”在一起,然后返回一个元组的列表
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    names = ['anne', 'beth', 'george', 'damon']
    ages = [12, 45, 32, 102]

    for name, age in zip(names, ages):
    print(name , " is " , age , "years old")
    =============================== RESTART: D:\D\python\test\hello.py ===============================
    anne is 12 years old
    beth is 45 years old
    george is 32 years old
    damon is 102 years old
  2. 编号迭代
    enumerate函数, 这个函数可以提供索引的地方迭代索引值对
    1
    2
    3
    4
    5
    6
    7
    8
    9
    stri = ['winbug', 'xxx','zzz']
    for index, string in enumerate(stri):
    if 'xxx' in string:
    print('在', index+1,'处修改了',stri[index],'为censored')
    stri[index] = 'censored'
    print(stri)
    =============================== RESTART: D:\D\python\test\hello.py ===============================
    在 2 处修改了 xxx 为censored
    ['winbug', 'censored', 'zzz']
  3. 翻转和排序迭代
    reversed函数,将列表元素全部反转
    sorted函数,将列表元素全部按字母排序

跳出循环

  1. break
    结束跳出循环
    1
    2
    3
    4
    5
    6
    7
    8
    from math import sqrt
    for n in range(99, 0, -1):
    root = sqrt(n)
    if root == int(root):
    print(n)
    break
    =============================== RESTART: D:\D\python\test\hello.py ===============================
    81 #获得100以内最大平方数
  2. continue
    跳到下一轮循环开始
  3. while True/break习语
    while True实现了一个永远不会自己停止的循环。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    while True:
    word = input('Please enter a word: ')
    if not word: break
    #处理word
    print("The word was " + word)
    =============================== RESTART: D:\D\python\test\hello.py ===============================
    Please enter a word: winbug
    The word was winbug
    Please enter a word: face
    The word was face
    Please enter a word: you
    The word was you
    Please enter a word:
    >>>

循环中的else子句

1
2
3
4
5
6
7
8
9
10
from math import sqrt
for n in range(99, 81, -1):
root = sqrt(n)
if root == int(root):
print(n)
break
else: #注意这里的else的位置,他不是上一个语句if的 else 而是 for的 else
print("Didn't find it!")
=============================== RESTART: D:\D\python\test\hello.py ===============================
Didn't find it!

列表推导式——轻量级循环

列表推导式:是通过其他列表来创建新列表的一种方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
number = [x*x for x in range(10)]
print(number)
#x*x并且能被3整除的序列
number = [x*x for x in range(10) if x%3 == 0]
print(number)
lists = [(x, y) for x in range(3) for y in range(3)]
print(lists)
girls = ['alice', 'bernice', 'clarice']
boys = ['chris', 'arnold', 'bob']
names = [b + '+' + g for b in girls for g in boys if b[0]==g[0]]
print(names)
=============================== RESTART: D:\D\python\test\hello.py ===============================
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
[0, 9, 36, 81]
[(0, 0), (0, 1), (0, 2), (1, 0), (1, 1), (1, 2), (2, 0), (2, 1), (2, 2)]
['alice+arnold', 'bernice+bob', 'clarice+chris']

三人行 pass, del, exec

pass

pass多用于测试的时候,它可以作为一个占位符,不引起python的错误

1
2
3
4
5
6
7
if xxxxx:
code.....
elif xxxx:
#没有写代码
pass
else:
xxxxxxx

del

使用del语句移除一个对象的引用

1
2
3
x = 1
del x
print(x) #出错

第5章的新函数

函数 描述
chr(n) 当传入序号n时,返回n所代表的包含一个字符的字符串
eval(source[, globals[, locals]]) 将字符串作为表达式计算,并且返回值
enumerate(seq) 产生用于迭代的(索引, 值)对
ord(c) 返回单字符字符串的int值
range([start,] stop[, step]) 创建整数的列表
reversed(seq) 产生seq中值的反向版本,用于迭代
sorted(seq[, cmp][, key][, reverse]) 返回seq中值排序后的列表
xrange([start,] stop[,step]) 创造xrange对象用于迭代
zip(seq1,seq2…) 创造用于并行迭代的新序列

第6章 抽象(函数)

本章介绍函数及其参数作用域的概念。

在程序中懶惰即美德

通过自定义函数等方法,提高编程速度。减少代码。

抽象和結構

创建函数

函数 是可以调用执行某种行为并且返回一个值,一般来说,内建的callable函数可以用来判断是否可以调用。

1
2
3
4
5
6
7
8
import math
x = 1
y = math.sqrt
print(callable(x))
print(callable(y))
=============================== RESTART: D:\D\python\test\hello.py ===============================
False
True

函数 由def语句创建

1
2
3
4
5
def hello(name):
return 'Hello, ' + name + '!'
print(hello('winbug'))
=============================== RESTART: D:\D\python\test\hello.py ===============================
Hello, winbug!

记录函数

为了代码便于理解,创建说明文档

1
2
3
4
5
def hello(name):
'This is a commit for hello'
return 'Hello, ' + name + '!'
>>> hello.__doc__
'This is a commit for hello'

内建的help函数也是非常有用的

1
2
3
4
5
>>> help(hello)
Help on function hello in module __main__:

hello(name)
This is a commit for hello

参数魔法

值从哪里来

一般函数的值来源于参数, 卸载def语句中函数名后面的变量通常叫做函数的形式参数(形参),而调用函数的时候提供的为实际参数(实参)

参数能改变么?

在函数内为参数赋予新值不会改变外部任何变量的值。

1
2
3
4
5
6
7
8
9
def try_to_change(n):
n = "Mr. Gumby"

name = "Mrs. Winbug"
try_to_change(name)

print(name)
=============================== RESTART: D:\D\python\test\hello.py ===============================
Mrs. Winbug

特殊情况, 当同时引用列表的时候会改变外部的值

1
2
3
4
5
6
7
8
9
10
def change(n):
n[0] = 'Mr. winbug'

names = ['Mr. Gumby', 'Mrs. Thing']

change(names)

print(names)
=============================== RESTART: D:\D\python\test\hello.py ===============================
['Mr. winbug', 'Mrs. Thing']

关键字参数和默认值

  1. 关键字参数
    有些时候(参数多的情况下),参数的顺序很难记住。为了让事情变的简单,可以提供参数的名字,这类使用参数名提供的参数叫关键字参数
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    def hello(greeting = 'hello', name= 'world'):
    print("%s, %s" % (greeting, name))

    hello()
    hello('Greeting')
    hello(name = 'winbug')
    =============================== RESTART: D:\D\python\test\hello.py ===============================
    hello, world
    Greeting, world
    hello, winbug
  2. 默认值
    关键字参数最厉害的地方在于可以在函数中给参数提供默认值

收集数据(参数的任意数量)

使用 * 号即可实现

1
2
3
4
5
6
def print_params(title, *params):
print(title, params)

print_params("Params ", 1,2,3,4)
=============================== RESTART: D:\D\python\test\hello.py ===============================
Params (1, 2, 3, 4)

如果想在参数中输入不定量的关键字参数,使用 ** 即可

1
2
3
4
5
6
def print_params(title, **params):
print(title, params)

print_params("Params ", x=1, y=2, z=3, a=4)
=============================== RESTART: D:\D\python\test\hello.py ===============================
Params {'x': 1, 'y': 2, 'z': 3, 'a': 4}

作用域

变量存储在作用域(也叫做命名空间)中。Python中有两类主要的作用域——全局作用域和局部作用域。作用域可以嵌套

1
2
3
4
5
6
7
8
def foo():
x = 42 #此处的x的作用域是foo函数内,不能影响外部变量
x = 1
foo()

print(x)
=============================== RESTART: D:\D\python\test\hello.py ===============================
1

重绑定全局变量

利用global来重新在其他作用域绑定全局变量

1
2
3
4
5
6
7
8
9
x = 1
def change_global():
global x #此处重绑定全局变量
x = x+1
change_global()
print(x)

=============================== RESTART: D:\D\python\test\hello.py ===============================
2

递归

函数可以调用自身——如果它这么做了就叫做递归。一切用递归实现的功能都可以用循环实现,但是有些时候递归函数更易读

阶乘和幂

阶乘
普通版

1
2
3
4
5
6
7
8
9
def factorial(n):
result = n
for i in range(1,n):
result *= i
return result

print(factorial(5))
=============================== RESTART: D:\D\python\test\hello.py ===============================
120

递归版

1
2
3
4
5
6
7
8
9
def factorial(n):
if n == 1:
return 1
else:
return n*factorial(n-1)

print(factorial(5))
=============================== RESTART: D:\D\python\test\hello.py ===============================
120


普通版

1
2
3
4
5
6
7
8
9
def power(x, n):
result = 1
for i in range(n):
result *= x
return result

print(power(2,3))
=============================== RESTART: D:\D\python\test\hello.py ===============================
8

递归版

1
2
3
4
5
6
7
8
9
def power(x, n):
if n==0:
return 1
else:
return x * power(x, n-1)

print(power(2,3))
=============================== RESTART: D:\D\python\test\hello.py ===============================
8

第6章的新函数

函数 描述
map(func, seq[,seq,….]) 对序列中的每个元素应用函数
filter(func, seq) 返回其函数为真的元素的列表
reduce(func, seq[, initial]) 等同于 func(func(func(seq[0], seq[1], seq[2])))
sum(seq) 返回seq中所有元素的和
apply(func[, args[, kwargs]]) 调用函数,可以提供参数

第7章 更加抽象(对象)

对象的魔力

对象 对象包括特性和方法。特性只是作为对象的一部分的变量,方法则是存储在对象内的函数。方法和其他函数的区别在于方法总是将对象作为自己的第一个参数,这个参数一般称为self。
对象的优点
本书中提到的特性,其实就是对象中的属性

  1. 多态(Plymorphism): 意味着可以对不同类的对象使用同样的操作。
  2. 封装(Encapsulation): 对外部世界隐藏对象的工作细节。
  3. 继承(Inheritance): 以普通的类为基础建立专门的类对象。

多态

多态 是实现将不同类型和类的对象进行同样对待的特性
多态代表变量所引用的对象不知道是什么类型

  1. 多态及方法 绑定到对象特性上面的函数称为方法
  2. 多态的多钟形态 任何不知道对象到底是什么类型,但是又要对对象做点什么的时候,都会用到多态。这不仅限于方法,很多内建运算符和函数都有多态的性质。

封装

封装 对象可以将他们的内部状态隐藏起来。在一些语言中,这意味着对象的状态只对自己的方法可用。在Python中,所有的特性都是公开可用的
对全局作用域中其他区域隐藏多余的信息

继承

继承 一个类可以是一个或者多个类的子类。子类从超类继承所有方法。可以使用多个超类。

类和类型

类代表对象的集合,每个对象都有一个类。类的主要任务是定义它的实例会用到的方法
实例 所有的对象都属于某一个类,称为类的实例
子类 当一个对象所属的类是另一个对象所属类的子集时,前者就被称为后者的子类

创建类

self可以叫做自身,也可以理解为其他语言的this

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
__metaclass__ = type #确定使用新式类

class Person:
def setName(self, name):
self.name = name

def getName(self):
return self.name

def greet(self):
print("Hello, World! I'm %s." % self.name)
=============================== RESTART: D:\D\python\test\class.py ===============================
>>> foo = Person()
>>> bar = Person()
>>> foo.setName("winbug")
>>> bar.setName('Anakin Skywalker')
>>> foo.greet()
Hello, World! I'm winbug.
>>> bar.greet()
Hello, World! I'm Anakin Skywalker.

设置私有函数

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
__metaclass__ = type #确定使用新式类

class Secetive:

def __inaccessible(self):
print("Bet you can't see me..")
def accessible(self):
print("The secret message is:")
self.__inaccessible()
=============================== RESTART: D:\D\python\test\class.py ===============================
>>> s = Secetive
>>> s.accessible()
Traceback (most recent call last):
File "<pyshell#5>", line 1, in <module>
s.accessible()
TypeError: accessible() missing 1 required positional argument: 'self'
>>> s = Secetive()
>>> s.accessible()
The secret message is:
Bet you can't see me..
>>> s.__inaccessible()
Traceback (most recent call last):
File "<pyshell#8>", line 1, in <module>
s.__inaccessible()
AttributeError: 'Secetive' object has no attribute '__inaccessible'

使用 __ (两个下划线后)我们无法直接从外部直接访问类内的方法了。不过如果使用以下方法,还是可以访问的,不过不推荐使用

1
2
>>> s._Secetive__inaccessible()
Bet you can't see me..

类的命名空间

类命名空间,所有位于class语句中的代码都在特殊的命名空间中执行

指定超类(父类)

在所有class语句后面的括号内可以指定超类

调查继承

如果想查看一个类是否是另一个的子类,可以使用内建的issubclass函数查看
如果想要知道已知类的基类(们),可以使用他的特殊特性 bases查看
同样,还可以使用isinstance方法检查一个对象是否是一个类的实例

多个超类

例如

1
2
3
4
5
6
7
8
9
10
class Calculator:
def calculate(self):
....

class Talker:
def talk(self):
....

class TYalkingCalculator(calculator, Talker): #同时继承了两个类
pass

关于面向对象设计的思考

  1. 将属于一类的对象放在一起
  2. 不要让对象过于亲密,方法应该只关心自己实例的特性。让其他实例管理自己的状态
  3. 要小心继承,尤其是多继承。
  4. 简单就好。 让你的方法小巧。

第7章的新函数

函数 描述
callable(object) 确定对象是否可以调用
getattr(object, name[, default]) 确定特性(属性)的值
hasattr(object, name) 去顶对象是否有给定的特性(属性)
isinstance(object, class) 确定对象是否是类的实例
issubclass(A, B) 确定A是否是B的子类
random.choice(sequence) 从非空序列中随机选择元素
setattr(object, name, value) 设定对象的给定特性(属性)的值
type(object) 返回对象的类型

第8章 异常

什么是异常

Python用异常对象(exception object)来表示异常情况。遇到错误后,会引发异常。

按自己的方式出错

raise语句

raise语句可以创建一个错误实例

1
2
3
4
5
6
7
8
9
10
>>> raise Exception
Traceback (most recent call last):
File "<pyshell#0>", line 1, in <module>
raise Exception
Exception
>>> raise Exception('hyperdrive overload') #添加一个错误信息
Traceback (most recent call last):
File "<pyshell#1>", line 1, in <module>
raise Exception('hyperdrive overload')
Exception: hyperdrive overload #此处显示

一些内建异常

类名 描述
Exception 所有异常的基类
AttributeError 特性引用或赋值失败时引发
IOError 试图打开不存在的文件时引发
IndexError 在使用序列中不存在的索引时引发
KeyError 在使用映射中不存在的键时引发
NameError 在找不到名字(变量)时引发
SyntaxError 在代码为错误形式时引发
TypeError 在内建操作或者函数应用于错误类型的对象时引发
ValueError 在内建操作或者函数应用于正确类型的对象,但该对象使用不合适的值时引发
ZeroDivisionError 在除法的第二个参数为0时引发

自定义异常类

class SomeCustomException(Excption): 这样我们就定义了一个自定义异常类

捕捉异常

可以通过try/except来捕捉异常

1
2
3
4
5
6
7
8
9
10
try:
x = int(input("Enter the first number: "))
y = int(input("Enter the second number: "))
print( x/y )
except ZeroDivisionError:
print("The second number can't be Zero!")
=============================== RESTART: D:\D\python\test\error.py ===============================
Enter the first number: 1
Enter the second number: 0
The second number can't be Zero!

except可以根据情况设置多个,而且可以用一个块捕捉两个异常

1
except (ZeroDivisionError, TypeError, NameError):

真正的全部捉

有些异常是我们不能预见的,所以可以使用以下代码,直接捕捉全部的异常,统一显示出错内容

1
2
3
4
5
6
try:
x = int(input("Enter the first number: "))
y = int(input("Enter the second number: "))
print( x/y )
except:
print("Something wrong happened")

完整版的异常捕捉

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
while True:
try:
x = int(input('Enter the first number: '))
y = int(input('Entre the second number: '))
value = x/y
print('x / y is ', value)
except Exception as e: #在python3以后已经不支持 Exception.e这种形式,需要使用 as e
print('Invalid input:', e)
print('Please try again')
else:
break
=============================== RESTART: D:\D\python\test\error.py ===============================
Enter the first number:
Invalid input: invalid literal for int() with base 10: ''
Please try again
Enter the first number: 20
Entre the second number: 0
Invalid input: division by zero
Please try again
Enter the first number:

Finally子句

Finally子句一般和try/except联合使用,finally子句一定会被执行,不管是否发生异常

第9章 魔法方法,属性和迭代器

绝不要在自己的程序中以__命名变量。在python中有这些名字组成的集合所包含的方法称为魔法方法

准备工作

为了确保类是最新型的,应该把赋值语句metaclass = type放在模块的最开始。(python3.0之后没有旧式类,所以可以不用显式的写

构造方法

构造方法, 这是面向对象的语言共有的,可能要为自己写的每个类实现构造方法。构造方法被命名为init并且在对象被创建后立即自动调用

在python中创建一个构造方法很容易。只要把init方法的名字从简单的init修改为魔法版本 init即可。

1
2
3
4
5
6
class Foobar:
def __init__(self):
self.somevar = 42
>>> v=Foobar()
>>> v.somevar
42

重写及特殊的构造方法

重写, 一个类能通过实现方法来重写它的超类中定义的这些方法和属性。如果新方法要调用重写版本的方法,可以从超类直接调用未绑定的版本或者使用super函数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class A:
def hello(self):
print("Hello, I'm A.")

class B(A):
def hello(self): #重写超类的hello方法
print("Hello, I'm B.")
=============================== RESTART: D:\D\python\test\class.py ===============================
>>> a = A()
>>> a.hello()
Hello, I'm A.
>>> b = B()
>>> b.hello()
Hello, I'm B.

构造方法的重写比较特殊,构造方法被重写,但新的构造方法没有任何关于初始化属性的代码。为了达到预期的效果,就要调用超类构造方法的未绑定版本或者使用super函数

调用未绑定的超类构造方法

调用超类的构造方法很容易。一般构造方法都是未绑定的,所以可以使用此方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
class Bird:
def __init__(self):
self.hungry = True
def eat(self):
if self.hungry:
print("Aaaah...")
self.hungry = False
else:
print("No, Thanks.")

class SongBird(Bird):
def __init__(self):
Bird.__init__(self) #调用了超类的构造方法
self.sound = 'Squawk!'
def sing(self):
print(self.sound)
=============================== RESTART: D:\D\python\test\class.py ===============================
>>> sb = SongBird()
>>> sb.eat()
Aaaah...
>>> sb.sing()
Squawk!
>>> sb.eat()
No, Thanks.

使用super函数

在新版Python中,我们可以直接使用super函数来调用超类的构造方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
class Bird:
def __init__(self):
self.hungry = True
def eat(self):
if self.hungry:
print("Aaaah...")
self.hungry = False
else:
print("No, Thanks.")

class SongBird(Bird):
def __init__(self):
super(SongBird, self).__init__() #在新版python中直接使用super
self.sound = 'Squawk!'
def sing(self):
print(self.sound)
=============================== RESTART: D:\D\python\test\class.py ===============================
>>> sb = SongBird()
>>> sb.eat()
Aaaah...
>>> sb.sing()
Squawk!
>>> sb.eat()
No, Thanks.

成员访问

基本的序列和映射规则

序列和映射是对象的集合

_len(self): 这个方法应该返回集合中所含项目的数量。如果len返回0,而且没有设置nonzero,对象会被当作一个布尔值变量中的假值进行处理
getitem(self.key) 这个方法返回与所给键对应的值。
setitem(self, key, value) 这个方法应该按一定的方式存储和key相关的value。
delitem(self, key) 这个方法在对一部分对象使用del语句时被调用,同时必须删除和元素相关的键。

property函数

property函数非常简单,它创建一个属性,并把访问器函数用作参数。使处理属性更简单方便

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class Rectangle:
def __init__(self):
self.width = 0
self.height = 0
def setSize(self, size):
self.width, self.height = size
def getSize(self):
return self.width, self.height

size = property(getSize, setSize)
=============================== RESTART: D:\D\python\test\class.py ===============================
>>> r = Rectangle()
>>> r.width = 10
>>> r.height = 5
>>> r.size
(10, 5)
>>> r.size = 150, 100
>>> r.width
150

迭代器

迭代器, 是带有next方法的简单对象。迭代器能在一系列的值上进行迭代。当没有值可供迭代时,next方法就会引发StopIteration异常。可迭代对象有一个返回迭代器的iter方法,他能像序列那样在for循环中使用。一般来说,迭代器本身也是可以迭代的,即迭代器有返回他自己的next方法。

1
2
3
4
5
6
7
8
9
10
11
12
class TestIterator:
value = 0
def __next__(self): #python3之后 next()停用,使用__next__()
self.value += 1
if self.value > 10: raise StopIteration
return self.value
def __iter__(self):
return self
=============================== RESTART: D:\D\python\test\class.py ===============================
>>> ti = TestIterator()
>>> list(ti)
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

生成器

生成器是python新引入的概念,它可以帮助程序人员写出非常优雅的代码,它是一种用普通的函数语法定义的迭代器。任何包含yield语句的函数称为生成器,生成器返回一个迭代器。每次请求一个值,就会执行生成器中的代码,直到遇到一个yield或return语句。

创建生成器

创建生成器和创建函数一样简单

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
nested = [[1,2],[3,4],[5]]
def flatten(nested):
for sublist in nested:
for element in sublist:
yield element

for num in flatten(nested):
print(num)
=============================== RESTART: D:\D\python\test\class.py ===============================
1
2
3
4
5
>>> list(flatten(nested))
[1, 2, 3, 4, 5]

第9章的新函数

函数 描述
iter(obj) 从一个可选迭代的对象得到迭代器
property(fget, fset, fdel, doc) 返回一个属性,所有的参数都是可选的
super(class, obj) 返回一个类的超类的绑定实例

第10章 充电时刻(模块)

Python模块

本章学习如何自己创建模块
模块: 从基本上来说,模块就是子程序,它的主函数则用于定义,包括定义函数,类和变量。

模块就是程序

模块用于定义

模块在第一次导入到程序中时被执行。真正的用处在于它们像类一样可以保持自己的作用域。这就意味着定义的所有类和函数以及赋值后的变量都成为了模块的属性(特性)

  1. 在模块中定义函数
1
2
3
4
5
6
def hello():
print("Hello, world!")
=========================== RESTART: D:\D\python\test\module\hello2.py ===========================
>>> import hello2
>>> hello2.hello()
Hello, world!

我们可以使用同样的方法来使用任何在模块的全局作用域中定义的名称。模块的主要功能就是为了代码的重用。避免没有必要的代码重复。

让你的模块可用

  1. 将模块放置在正确的位置
    a. 放置到Python解释器放置模块的位置
    b. 告诉解释器去哪里查找

    我们可以通过sys模块中的path变量查找
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    >>> import sys, pprint
    >>> pprint.pprint(sys.path)
    ['D:\\D\\python\\test\\module',
    'D:\\D\\Program Files\\Python\\Lib\\idlelib',
    'D:\\D\\Program Files\\Python\\python36.zip',
    'D:\\D\\Program Files\\Python\\DLLs',
    'D:\\D\\Program Files\\Python\\lib',
    'D:\\D\\Program Files\\Python',
    'C:\\Users\\winbug\\AppData\\Roaming\\Python\\Python36\\site-packages',
    'D:\\D\\Program Files\\Python\\lib\\site-packages']
    *pprint 是非常好用的打印函数,能够更加智能的打印输出* 一般可以放置在site-packages目录中。就可以直接使用import进行调用了 也可以告诉编译器去哪里找,通过在系统环境变量中追加自己的模块位置

包:包是包含有其他模块的模块。包是作为包含init.py文件的目录来实现的。

探索模块

模块中有什么

1. 使用dir(), 会将模块的所有特性列出。一些名字以下划线开始,表示他们并不是为在模块外使用而准备的。所以可以忽略
1
2
3
4
5
>>> dir(copy)
['Error', '__all__', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', '_copy_dispatch', '_copy_immutable', '_deepcopy_atomic', '_deepcopy_dict', '_deepcopy_dispatch', '_deepcopy_list', '_deepcopy_method', '_deepcopy_tuple', '_keep_alive', '_reconstruct', 'copy', 'deepcopy', 'dispatch_table', 'error']

>>> [n for n in dir(copy) if not n.startswith('_')] #过滤掉以下划线开头的特性
['Error', 'copy', 'deepcopy', 'dispatch_table', 'error']
2. __all__ 变量 这个变量包含一个列表,该列表定义了模块的公有接口
1
2
>>> copy.__all__
['Error', 'copy', 'deepcopy']

用help获取帮助

使用help函数可以获得相应函数的说明

1
2
3
4
5
6
7
8
9
10
11
>>> help(copy.copy)
Help on function copy in module copy:

copy(x)
Shallow copy operation on arbitrary Python objects.

See the module's __doc__ string for more info.
>>> print(copy.copy.__doc__)
Shallow copy operation on arbitrary Python objects.

See the module's __doc__ string for more info.

文档

所有的Python标准文档

使用源代码

阅读源代码事实上是学习python最好的方法。如果想找到标准模块的源代码位置,可以使用file属性

1
2
>>> copy.__file__
'D:\\D\\Program Files\\Python\\lib\\copy.py'

标准库

sys模块

sys模块能够让你访问与python解释器联系紧密的变量和函数。

函数 描述
argv 命令行参数, 包含脚本名称
exit([arg]) 退出当前的程序,可选参数为给定的返回值或者错误信息
modules 映射模块名字到载入模块的字典
path 查找模块所在目录的目录名列表
platform 类似sunos5或者win32平台标识符
stdin 标准输入流 —— 一个类文件对象
stdout 标准输出流 —— 一个类文件对象
stderr 标准错误流 —— 一个类文件对象

os模块

os模块提供了访问多个操作系统服务的功能。

函数 描述
environ 对环境变量进行映射
system(command) 在子shell中执行操作系统命令
sep 路径中的分隔符
pathsep 分割路径的分隔符
linesep 行分隔符(‘\n’, ‘\r’)
urandom(n) 返回n字节的加密强随机数据

fileinput模块

fileinput模块让你能够轻松地遍历文本文件的所有行。

函数 描述
input([files[, inplace[, backup]]]) 便于遍历多个输入流中的行
filename() 返回当前文件的名称
lineno() 返回当前(累计)的行数
filelineno() 放回当前文件的行数
isfirstline() 检查当前行是否是文件的第一行
isstdin() 检查最后一行是否来自sys.stdin
nextfile() 关闭当前文件,移动到下一个文件
close() 关闭序列

time模块

time模块包括,获得当前的时间,操作时间和日期,从字符串读取时间以及格式化时间为字符串。

time.asctime将当前时间格式化为字符串

1
2
3
>>> import time
>>> time.asctime()
'Mon Jun 25 14:19:48 2018'
函数 描述
asctime([tuple]) 将时间元祖转换为字符串
localtime([secs]) 将秒数转换为日期元组,以本地时间为准
mktime(tuple) 将时间元祖转换为本地时间
sleep(secs) 休眠 secs秒
strptime(string[, format]) 将字符串解析为时间元组
time() 当前时间(新纪元开始后的秒数,以UTC为准)

random模块

random模块返回随机数的函数,可以用于模拟或者用于任何产生随机输出的程序。

函数 描述
random() 返回 0 ≤ n < 1之前得随机实数n
getrandbits(n) 以长整型形式返回n个随机位
uniform(a, b) 返回随机实数n, 其中 a ≤ n < b
randrange([start], stop, [step]) 返回range(start,stop,step)中的随机数
choice(seq) 从序列seq中返回随意元素
shuffle(seq[, random]) 原地指定序列seq
sample(seq, n) 从序列seq中选择n个随机且独立的元素

第11章 文件和素材

打开文件

open函数
open(name[, mode[, buffering]])

1
>>> f = open(r'd:\d\python\test\file\test.txt') #打开指定文件

文件模式

描述
‘r’ 读模式
‘w’ 写模式
‘a’ 追加模式
‘b’ 二进制模式
‘+’ 读/写模式

缓冲

open的第三个参数控制着文件的缓冲, 如果参数是0就是无缓冲,如果是1或大于1开启缓冲,数字代表着缓冲区的大小(单位字节), -1代表使用默认的缓冲区大小。

基本文件方法

读和写

写入

1
2
3
4
5
6
>>> f = open(r'd:\d\python\test\file\test.txt', 'w') #不加r的情况,将反斜线换成斜线  d:/d/python/test/file/test.txt
>>> f.write('Hello. ')
7
>>> f.write('World!')
6
>>> f.close()

读取

1
2
3
4
5
>>> f = open('d:/d/python/test/file/test.txt', 'r')
>>> f.read(4)
'Hell'
>>> f.read()
'o. World!'

在调用open时,r是默认的

读写行

可以使用file.readline读取单独的一行

1
2
3
4
>>> f = open('d:/d/python/test/file/test.txt', 'r')
>>> f.readline()
'Hello. World!'
>>> f.close()

关闭文件

使用close()方法

对文件内容进行迭代

按字节处理

1
2
3
4
5
6
f=open(filename)
char = f.read(1)
while char:
process(char) #输出读取的内容
char = f.read(1)
f.close()

按行操作

1
2
3
4
5
6
f=open(filename)
while True:
line = f.readline()
if not line: break
process(line) #输出读取的内容
f.close()

第12章 图形用户界面

推荐GUI工具 wxPython

安装wxPython

先确认pip 是否安装,未安装的话,请按照下面步骤处理

  1. 打开windows的PowerShell或是命令提示符,输入以下内容
    1
    curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py
  2. 等待下载完成后,输入
    1
    python get-pip.py
    完成pip的安装

确认pip安装完成后,在windows的PowerShell或是命令提示符下输入

1
pip install -U wxPython

创建GUI界面

提示安装成功后,我们就可以开始学习Python的图形编程了。

Hello World界面

1
2
3
4
5
6
7
8
9
import wx #导入wx模块

app = wx.App() #界面初始化

frm = wx.Frame(None, title="Hello, World!")

frm.Show()

app.MainLoop()

创建两个按钮及两个文本框

目标样式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import wx

app = wx.App()

frm = wx.Frame(None, title="Hello, World!", size=(417, 343)) #默认尺寸
frm.Show()

loadbtn = wx.Button(frm, label='Open',
pos=(225, 5), size=(80, 25))
savebtn = wx.Button(frm, label='Save', #标签label, pos坐标
pos=(315, 5), size=(80, 25))
filename = wx.TextCtrl(frm, pos=(5, 5), size=(210, 25))
contents = wx.TextCtrl(frm, pos=(5, 36), size=(390, 260),
style=wx.TE_MULTILINE | wx.HSCROLL)


app.MainLoop()

更智能的布局

利用背景组件wx.Panel,创建一些嵌套的wx.BoxSizer,解决固定高宽的问题。

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
import wx

app = wx.App()

frm = wx.Frame(None, title="Hello, World!", size=(417, 343))
bkg = wx.Panel(frm)

loadbtn = wx.Button(bkg, label='Open')
savebtn = wx.Button(bkg, label='Save')
filename = wx.TextCtrl(bkg)
contents = wx.TextCtrl(bkg, style=wx.TE_MULTILINE | wx.HSCROLL)

hbox = wx.BoxSizer()
hbox.Add(filename, proportion=1, flag=wx.EXPAND)
hbox.Add(loadbtn, proportion=0, flag=wx.LEFT, border=5)
hbox.Add(savebtn, proportion=0, flag=wx.LEFT, border=5)

vbox = wx.BoxSizer(wx.VERTICAL)
vbox.Add(hbox, proportion=0, flag=wx.EXPAND | wx.ALL, border=5)
vbox.Add(contents, proportion=1,
flag=wx.EXPAND | wx.LEFT | wx.BOTTOM | wx.RIGHT, border=5)
bkg.SetSizer(vbox)

frm.Show()
app.MainLoop()

wx.BoxSizer函数,它决定窗体是按照垂直还是水平进行设置(wx.HORIZONTAL | wx.VERTICAL),默认为水平
Add函数,proportion参数根据在窗口改变大小事所分配的空间设置比例
flag参数可以使用按位或运算符链接构成位置,wx.EXPAND标记确保组件会扩展到所分配的空间中。

事件处理

使用.Bind来关联事件
loadbtn.Bind(wx.EVT_BUTTON, load)

完成版代码

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
26
27
28
29
30
31
32
33
34
35
36
37
38
import wx

#读取文件并写入contents区域
def load(event):
file = open(filename.GetValue(), 'r')
contents.SetValue(file.read())
file.close()

def save(event):
file = open(filename.GetValue(), 'w')
file.write(contents.GetValue())
file.close()

app = wx.App()

frm = wx.Frame(None, title="Hello, World!", size=(417, 343))
bkg = wx.Panel(frm)

loadbtn = wx.Button(bkg, label='Open')
loadbtn.Bind(wx.EVT_BUTTON, load)
savebtn = wx.Button(bkg, label='Save')
savebtn.Bind(wx.EVT_BUTTON, save)
filename = wx.TextCtrl(bkg)
contents = wx.TextCtrl(bkg, style=wx.TE_MULTILINE | wx.HSCROLL)

hbox = wx.BoxSizer()
hbox.Add(filename, proportion=1, flag=wx.EXPAND)
hbox.Add(loadbtn, proportion=0, flag=wx.LEFT, border=5)
hbox.Add(savebtn, proportion=0, flag=wx.LEFT, border=5)

vbox = wx.BoxSizer(wx.VERTICAL)
vbox.Add(hbox, proportion=0, flag=wx.EXPAND | wx.ALL, border=5)
vbox.Add(contents, proportion=1,
flag=wx.EXPAND | wx.LEFT | wx.BOTTOM | wx.RIGHT, border=5)
bkg.SetSizer(vbox)

frm.Show()
app.MainLoop()

第13章 数据库连接(MySQL)

PyMySQL (支持python3.0)

PyMySQL安装

1
pip install PyMySQL

MySQL连接

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import pymysql

# 打开数据库连接
db = pymysql.connect("localhost","root","password","TESTDB" )

# 使用 cursor() 方法创建一个游标对象 cursor
cursor = db.cursor()

# 使用 execute() 方法执行 SQL 查询
cursor.execute("SELECT VERSION()")

# 使用 fetchone() 方法获取单条数据.
data = cursor.fetchone()

print ("Database version : %s " % data)

# 关闭数据库连接
db.close()

创建数据库表

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import pymysql

# 打开数据库连接
db = pymysql.connect("localhost","root","","TESTDB" )

# 使用 cursor() 方法创建一个游标对象 cursor
cursor = db.cursor()

# 使用 execute() 方法执行 SQL,如果表存在则删除
cursor.execute("DROP TABLE IF EXISTS EMPLOYEE")

# 使用预处理语句创建表
sql = """CREATE TABLE EMPLOYEE (
FIRST_NAME CHAR(20) NOT NULL,
LAST_NAME CHAR(20),
AGE INT,
SEX CHAR(1),
INCOME FLOAT )"""

cursor.execute(sql)

# 关闭数据库连接
db.close()

数据库截图

对数据库进行插入操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import pymysql

# 打开数据库连接
db = pymysql.connect("localhost","testuser","test123","TESTDB" )

# 使用cursor()方法获取操作游标
cursor = db.cursor()

# SQL 插入语句
sql = """INSERT INTO EMPLOYEE(FIRST_NAME,
LAST_NAME, AGE, SEX, INCOME)
VALUES ('Mac', 'Mohan', 20, 'M', 2000)"""
try:
# 执行sql语句
cursor.execute(sql)
# 提交到数据库执行
db.commit()
except:
# 如果发生错误则回滚
db.rollback()

# 关闭数据库连接
db.close()

数据库查询操作

fetchone() 获取下一个查询结果集
fetchall() 接收全部的返回结果行
rowcount 返回执行exeecute()方法后影响的行数

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
26
27
28
29
30
import pymysql

# 打开数据库连接
db = pymysql.connect("localhost","testuser","test123","TESTDB" )

# 使用cursor()方法获取操作游标
cursor = db.cursor()

# SQL 查询语句
sql = "SELECT * FROM EMPLOYEE \
WHERE INCOME > '%d'" % (1000)
try:
# 执行SQL语句
cursor.execute(sql)
# 获取所有记录列表
results = cursor.fetchall()
for row in results:
fname = row[0]
lname = row[1]
age = row[2]
sex = row[3]
income = row[4]
# 打印结果
print ("fname=%s,lname=%s,age=%d,sex=%s,income=%d" % \
(fname, lname, age, sex, income ))
except:
print ("Error: unable to fetch data")

# 关闭数据库连接
db.close()

数据库更新操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import pymysql

# 打开数据库连接
db = pymysql.connect("localhost","testuser","test123","TESTDB" )

# 使用cursor()方法获取操作游标
cursor = db.cursor()

# SQL 更新语句
sql = "UPDATE EMPLOYEE SET AGE = AGE + 1 WHERE SEX = '%c'" % ('M')
try:
# 执行SQL语句
cursor.execute(sql)
# 提交到数据库执行
db.commit()
except:
# 发生错误时回滚
db.rollback()

# 关闭数据库连接
db.close()

数据库的删除操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import pymysql

# 打开数据库连接
db = pymysql.connect("localhost","testuser","test123","TESTDB" )

# 使用cursor()方法获取操作游标
cursor = db.cursor()

# SQL 删除语句
sql = "DELETE FROM EMPLOYEE WHERE AGE > '%d'" % (20)
try:
# 执行SQL语句
cursor.execute(sql)
# 提交修改
db.commit()
except:
# 发生错误时回滚
db.rollback()

# 关闭连接
db.close()