[关闭]
@hainingwyx 2017-11-07T09:47:19.000000Z 字数 55852 阅读 2747

Python入门

Python


第1章 Python概述

1.1 初识Python

TIOBE排行榜:http://www.tiobe.com/tiobe-index//
Python的特性 :简单易学、开源的、免费的、高可移植性全面支持面向对象的程序设计思想高可扩展性支持嵌入式编程、功能强大的开发库

1.2 开始Python编程

执行Python脚本文件

cmd执行命令:访问F盘,只需要输入F:进入文件夹,输入cd filedicname。查看目录结构,输入dir。返回上一层目录,输入 cd..。切换到程序目录之后输入python xxx.py即可。

第2章 Python语言基础

2.1 标量类型

命名

常量 :常量命名全部大写。
变量:标识符名字是区分大小写的。变量名使用小写字母,驼峰命名法:numberOfStudents, radius。

变量赋值就是将对象(该变量的地址)指向赋值给它的常量或者变量的地址。

字符串
字符串和元组是不可变的。换行字符串可以使用三重引号。
2.7版本的Python不能print汉字。解决办法

  1. a = u"我是中文"
  2. print a

常用转义字符

\n——换行
\r——回车
\''——''
\——\

  1. s = r"this\has\no" #原生字符串,等价于"this\\has\\no"
  2. print '%.2f %s are wortg $%d' %(4.555, 'test', 2) #字符串格式化

字符串处理函数

函数 具体说明
str.lower() 将字符串str中的字母转换为小写字母
str.upper() 将字符串str中的字母转换为大写字母
str.swapcase() 将字符串str中的字母大小写互换
str.capitalize () 将字符串str中的首字母大写
str. title() 将字符串str中的首字母大写,其余为小写
str.find(substr, [start, [end]]) 返回字符串str中出现子串substr的第一个字母的位置,如果str中没有substr,则返回-1。搜索范围从start至end
str.index(substr, [start, [end]]) 与find()函数相同,只是在str中没有substr时,index()函数会返回一个运行时错误
str.rfind(substr, [start, [end]]) 返回从右侧算起,字符串str中出现子串substr的第一个字母的位置,如果str中没有substr,则返回-1。搜索范围从start至end
str.rindex (substr, [start,[end]]) 与rfind()函数相同,只是在str中没有substr时,rindex()函数会返回一个运行时错误
str.count(substr, [start,[end]]) 计算substr在str中出现的次数。统计范围从start至end
str.replace(oldstr, newstr, [count]) 把str中的oldstr替换为newstr,count为替换次数
str.strip([chars]) 把字符串str中前后chars中有的字符全部去掉。如果不指定参数chars,则会去掉空白符(包括'\n', '\r', '\t'和' ')
str.lstrip([chars]) 把字符串str中前面包含的chars中有的字符全部去掉。如果不指定参数chars,则会去掉空白符(包括'\n', '\r', '\t'和' ')
str.rstrip([chars]) 把字符串str中前面包含的chars中有的字符全部去掉。如果不指定参数chars,则会去掉空白符(包括'\n', '\r', '\t'和' ')
str. expandtabs([tabsize]) 把字符串str中的tab字符替换为空格,每个tab替换为tabsize个空格,默认是8个

数据类型转换

  1. list(str) #字符串转列表
  2. tuple(str) #字符串转元组
  3. "".join(lists) #列表转字符串
  4. "".join(tuples) #元组转字符串
  5. int()
  6. long()
  7. float()
  8. eval() #计算字符串中的有效Python表达式,并返回结果
  9. str()
  10. repr() #将对象转换为可打印字符串
  11. chr () #将一个整数转换为可对应ASCII的字符
  12. ord() #将一个字符转换为对应的ASCII
  13. hex() #将一个整数转换为一个十六进制字符串
  14. oct() #将一个整数转换为一个八进制字符串

2.2 运算符和表达式

运算符

python2中整数相除结果不保留小数位。可以添加以下解决:

  1. from __future__ import division

运算符优先级

运算符 说明
** 指数运算的优先级最高
~ + - 逻辑非运算符和正数/负数运算符。
* / % // 乘、除、取模和取整除
+ - 加和减
>> << 位右移运算和位左移运算
& 按位与运算
^ | 按位异或运算和按位或运算
> == != 大于、等于和不等于
%= /= //= -= += *= **= 赋值运算符
is is not 身份运算符
in not in 成员运算符
not or and 逻辑运算符

三元表达式

  1. value = true-expr if condition else fasle-expr

2.3 常用语句

循环语句

  1. for i in range(start, end):
  2. break #只能跳出一重循环
  3. continue #提前进入下一个循环
  4. fruits = [‘banana’, apple’]
  5. for fruit in fruits:
  6. print fruit

while结构中存在可选部分else,当循环体执行结束后,会执行else语句块。但是当break语句和else语句相结合,while会因为break语句而终止。

range和xrange

  1. range(a, b) #a - b-1
  2. range(b) #0 - b-1
  3. range(a, b, k) #范围a, a+k, …b-x,
  4. range(a, b, -1) #范围a, a-1, …b-(-1)
  5. #对于非常长的范围,建议使用xrange,不会预先产生所有的值并将它们保存到列表中,而是返回用于逐个产生整数的迭代器
  6. sum = 0
  7. for i in xrange(10000):
  8. if i % 3 == 0 or i % 5 == 0:
  9. sum += i

异常处理

  1. try:
  2. <try语句块>
  3. # 不同的异常处理,可以使用多个except
  4. except [<异常处理类>, <异常处理类>,….] as <异常处理对象>:
  5. <异常处理代码>
  6. finally:
  7. <最后执行的代码>

例子:

  1. try:
  2. i = 10
  3. print(30 / (i - 10))
  4. except Exception as e:
  5. print(e);
  6. finally:
  7. print("执行完成")
  8. def attempt_float(x):
  9. try:
  10. return float(x)
  11. except (TypeError, ValueError):
  12. return x

raise ValueError可以手动触发Error。主要包括:NameError,ZeroDiVisionError,IndexError, KeyError, IOError, ValueError, EOFError, TypeError, AtrributeError

pass:空操作。可以用于没有任何功能的代码块。

2.4 序列数据结构

列表

列表(List)是一组有序存储的数据。变长,可修改。遍历列表时,不能删除其中的元素,可以保留要删除的元素到新的列表中,然后再处理,否则会引起不可预测的后果。

  1. menulist = ['红烧肉', '熘肝尖', '西红柿炒鸡蛋', '油焖大虾']
  2. len(menulist) # 获取列表长度
  3. print(menulist[0])
  4. menulistr.append('北京烤鸭') # 添加列表元素
  5. menulist.insert(4, '北鸭') # 插入列表元素
  6. popitem = menulist.pop(4) # 移除元素,并返回指定索引处的值
  7. print '红烧肉' in menulist
  8. menulist1.extend (menulist2) # 合并列表
  9. menulist3 = menulist1 + menulist2 #列表合并,保留重合
  10. del menulist[0]
  11. print(menulist.index('红烧肉')) # 获取列表中某个元素的索引
  12. # 遍历
  13. list2 = [["CPU", "内存"], ["硬盘","声卡"]]
  14. for i in range(len(list2)):
  15. for j in range(len(list2[i])):
  16. print(list2[i][j])
  17. #使用sort()函数对列表进行升序排列,修改列表
  18. a = [7, 2, 5, 1, 3]
  19. a.sort()
  20. b = ['saw', 'small', 'He', 'foxes', 'six']
  21. b.sort(key=len)
  22. # reverse()函数对列表进行反序排列
  23. listobj.reverse()
  24. # sorted 不修改列表
  25. a = [7, 1, 2, 6, 0, 3, 2]
  26. b = sorted(a)
  27. sorted('horse race')
  28. sorted(set('this is just some string'))
  29. # 二分搜索和维护有序列表
  30. import bisect
  31. c = [1, 2, 2, 2, 3, 4, 7]
  32. bisect.bisect(c, 2) #二分搜索
  33. bisect.bisect(c, 5)
  34. bisect.insort(c, 6) #二分插入
  35. #切片
  36. seq = [7, 2, 3, 7, 5, 6, 0, 1]
  37. seq[1:5] # 索引[2, 3, 7, 5]
  38. seq[3:4] = [6, 3] # 赋值[7, 2, 3, 6, 3, 5, 6, 0, 1]
  39. seq[:5]
  40. seq[3:]
  41. seq[-4:] # [5, 6, 0, 1]
  42. seq[-6:-2] # [6, 3, 5, 6]
  43. seq[::2] # 步长为2 [7, 3, 3, 6, 1]
  44. seq[::-1] # 反序排列
  45. #内置的序列函数
  46. # enumerate逐个返回序列的(i,value)元组
  47. for i, value in enumerate(collection):
  48. # do something with value
  49. # 例子:将序列值映射到其所在位置的字典
  50. # 结果:mapping {'bar': 1, 'baz': 2, 'foo': 0}
  51. some_list = ['foo', 'bar', 'baz']
  52. mapping = dict((v, i) for i, v in enumerate(some_list))
  53. #序列配对:产生新的元组列表,最短的序列决定yuanzu长度
  54. #例子1
  55. #结果: [('foo', 'one'), ('bar', 'two'), ('baz', 'three')]
  56. seq1 = ['foo', 'bar', 'baz']
  57. seq2 = ['one', 'two', 'three']
  58. zip(seq1, seq2)
  59. # 例子2
  60. # 结果:[('foo', 'one', False), ('bar', 'two', True)]
  61. seq3 = [False, True]
  62. zip(seq1, seq2, seq3)
  63. # 例子3
  64. # 结果
  65. #0: foo, one
  66. #1: bar, two
  67. #2: baz, three
  68. for i, (a, b) in enumerate(zip(seq1, seq2)):
  69. print('%d: %s, %s' % (i, a, b))
  70. # 解压
  71. # 例子3
  72. # 结果:first_names ('Nolan', 'Roger', 'Schilling')
  73. # 结果:last_names ('Ryan', 'Clemens', 'Curt')
  74. pitchers = [('Nolan', 'Ryan'), ('Roger', 'Clemens'),
  75. ('Schilling', 'Curt')]
  76. first_names, last_names = zip(*pitchers)
  77. #逆序迭代
  78. list(reversed(range(10)))
  79. # 常用函数
  80. max(seq)
  81. min(seq)
  82. sum(seq)
  83. seq.pop()
  84. seq.count(value)

变量传递

is和==

  1. is是比较两个引用是否指向了同一个对象(引用比较)比较的是内存地址。
  2. ==是比较两个对象是否相等它会直接进行值比较。
  1. a=[1, 2, 3]
  2. b=a#两者指向同一对象
  3. c = list(a)
  4. print Are they same?” , a is b #True a的引用复制给b,他们在内存中其实是指向了用一个对象
  5. print Are they same?”, [4, 5, 6] is [4, 5, 6] # 结果为假
  6. b == a # True 值相等
  7. b = a[:] # b通过a切片获得a的部分,这里的切片操作重新分配了对象,
  8. b is a #False 指向的不是同一个对象
  9. b == a # True 值相等

元组

一经定义,元组的内容不能改变。元组元素可以是不同类型的数据,可以是字符串、数字,甚至是元组。

  1. # 创建
  2. tup = 1,2,3,4
  3. nested_tup = (4, 5, 6), (7, 8)
  4. tuple([4, 0, 2])
  5. t = (1, 2, 3, 4)
  6. print(t[0])
  7. print(len(t))
  8. # 'sdr'
  9. s =('s''d''r')
  10. # error!不可修改
  11. s[1]=’w
  12. # 元组的遍历
  13. t = ('王二', '张三', '李四', '王五');
  14. for i in range(len(t)):
  15. print(t[i]);
  16. list = ['王二', '张三', '李四', '王五'];
  17. for index,value in enumerate(list):
  18. print("第%d个元素值是[%s]" %(index, value));
  19. # 元组和List的转换
  20. listobj = list(tupleobj)
  21. tupleobj = tuple(listobj)
  22. # 连接
  23. (4, None, 'foo') + (6, 0) + ('bar',)
  24. ('foo', 'bar') * 4
  25. # 拆包
  26. tup = (4, 5, 6)
  27. a, b, c = tup
  28. tup = 4, 5, (6, 7)
  29. a, b, (c, d) = tup
  30. # 交换值简写
  31. tmp = a
  32. a = b
  33. b = tmp
  34. b, a = a, b
  35. seq = [(1, 2, 3), (4, 5, 6), (7, 8, 9)]#元组迭代时候拆包
  36. for a, b, c in seq:
  37. pass
  38. # 方法
  39. a = (1, 2, 2, 2, 3, 4, 2)
  40. a.count(2)

字典

更常见的名字:哈希映射,是一种大小可变的键值对集。可以在定义字典时指定里面的元素,每个元素由键和值组成,键和值之间由冒号(:)分割,元素间由逗号(,)分割。
特点:

  1. 字典查找和插入的速度极快,不会随着键的增加而增加
  2. 需要占用大量内存
  3. 无序对象的集合。
  1. d={'name':'小明', 'sex':'男','age':'18', 'score':'80'}
  2. print(len(d))
  3. print(d['name']) # 对字典元素的访问
  4. d.pop('score') # 删除指定的字典元素
  5. d['height'] = '170' # 插入元素
  6. 'name' in d # 判断是否存在某个键
  7. del d['height'] # 删除值
  8. ret = d.pop('age')
  9. print ret # 18
  10. print d.keys() # 返回一个包含所有键的列表,python3返回迭代器
  11. print d.values() # 返回一个包含所有值的列表,python3返回迭代器
  12. d.update(d2) # 将2个字典合并,d2中的键值对覆盖进去d中
  13. mapping = dict(zip(range(5), reversed(range(5)))) # 从序列创建字典
  14. # 默认值
  15. value = some_dict.get(key, default_value) # 省略了if-else块
  16. words = ['apple', 'bat', 'bar', 'atom', 'book']
  17. by_letter = {}
  18. for word in words:
  19. letter = word[0]
  20. if letter not in by_letter:
  21. by_letter[letter] = [word]
  22. else:
  23. by_letter[letter].append(word)
  24. # if-else可以用以下代替,解决了初始不在字典的问题
  25. by_letter.setdefault(letter, []).append(word)
  26. # 也可以生成字典值的默认值
  27. from collections import defaultdict
  28. by_letter = defaultdict(list)
  29. for word in words:
  30. by_letter[word[0]].append(word)
  31. # 字典键的有效性
  32. # 字典值可以是任意对象,但是键必须是不可变对象。通过hash判断是否可作为键
  33. hash((1, 2, (2, 3)))
  34. hash((1, 2, [2, 3])) # fails because lists are mutable
  35. # 字典嵌套
  36. d={'name':{'first':'Johney','last':'Lee'},'age':40}
  37. print(d['name'][ 'first'])
  38. # 遍历字典的键
  39. d={'age': '18', 'name': '小明', 'score': '80', 'sex': '男'}
  40. for key in d.keys():
  41. print('键'+key+ '的值:'+ d[key]);
  42. # 遍历字典的值
  43. for value in d.values():
  44. print(value);
  45. #清空指定的字典所有元素
  46. d. clear()
  47. # 判断是否存在元素
  48. d={'age': '18', 'name': '小明', 'score': '80', 'sex': '男'}
  49. if 'name1' in d:
  50. print(d['name1'])
  51. else:
  52. print('不包含键位name1的元素')
  53. # 检查字典中是否存在某一键
  54. has_key()
  55. # 返回一个由(key, value)组成的列表
  56. items()
  57. counts = dict()
  58. names = ['csev', 'cwen', 'csev', 'zqian', 'cwen']
  59. for name in names :
  60. #get 根据键返回值,当间不存在的时候返回0并增加一个键
  61. counts[name] = counts.get(name, 0) + 1#计数,开始为0
  62. print counts

集合

集合是由唯一元素组成的无序集。集合由一组无序排列的元素组成,可以分为可变集合(set)和不可变集合(frozenset)。可变集合创建后可以添加元素,修改元素和删除元素。而不可变集合创建后则不能改变。

  1. # 创建的两种方法
  2. set([2, 2, 2, 1, 3, 3])
  3. {2, 2, 2, 1, 3, 3}
  4. # 数学运算
  5. a = {1, 2, 3, 4, 5}
  6. b = {3, 4, 5, 6, 7, 8}
  7. a | b # union (or)
  8. a & b # intersection (and)
  9. a - b # difference
  10. a ^ b # symmetric difference (xor)
  11. s = s1.union(s2)
  12. s = s1.intersection (s2)
  13. s = s1.difference(s2)
  14. # 集合之间的关系
  15. a_set = {1, 2, 3, 4, 5}
  16. {1, 2, 3}.issubset(a_set)
  17. a_set.issuperset({1, 2, 3})
  18. # 集合运算
  19. a.add(x) # 将x添加到集合a
  20. a.remove(x) # 从a中删除元素x
  21. a.isdisjoint(b) # 没有公共元素,则为True
  22. s = set('python') #可变集合
  23. print s # 无序
  24. print len(s)
  25. s.add('0') # 添加元素
  26. s.update([4, 5, 6]) # 另外一个集合的元素添加到指定集合中
  27. s.remove('p') # 清除指定元素
  28. if 2 in s: #判断集合是否存在元素
  29. print '存在'
  30. # 遍历集合
  31. for e in s:
  32. print(e);
  33. # 清除所有元素
  34. s.clear()
  35. fs = frozenset('python') # 不可变集合
  36. print(type(fs)) # <type 'frozenset'>
  37. print(fs) # frozenset(['h', 'o', 'n', 'p', 't', 'y'])
实例 判断描述
A==B A等于B
A!=B A不等于B
A< B A是B的真子集
A<=B A是B的子集
A>B A是B的真超集
A>=B A是B的超集

推导式

  1. expr for val in collection if condition

相当于

  1. result = []
  2. for val in collection:
  3. if condition:
  4. result.append(expr)

例子

  1. strings = ['a', 'as', 'bat', 'car', 'dove', 'python']
  2. [x.upper() for x in strings if len(x) > 2]
  1. dict_comp = {key-expr: value-expr for value in collection if condition}

例子

  1. loc_mapping = {val : index for index, val in enumerate(strings)}
  2. # 或者
  3. loc_mapping = dict((val, idx) for idx, val in enumerate(strings))
  1. set_comp = {expr for value in collection if condition}

例子

  1. unique_lengths = {len(x) for x in strings}
  1. all_data = [['Tom', 'Billy', 'Jefferson', 'Andrew', 'Wesley', 'Steven', 'Joe'],
  2. ['Susie', 'Casey', 'Jill', 'Ana', 'Eva', 'Jennifer', 'Stephanie']]
  3. names_of_interest = []
  4. for names in all_data:
  5. enough_es = [name for name in names if name.count('e') > 2]
  6. names_of_interest.extend(enough_es)
  7. # for 可以用以下代替
  8. result = [name for names in all_data for name in names
  9. if name.count('e') >= 2]
  10. # 扁平化整数列表
  11. some_tuples = [(1, 2, 3), (4, 5, 6), (7, 8, 9)]
  12. # 顺序和for写是一样的
  13. flattened = [x for tup in some_tuples for x in tup]

第3章 函数

3.1 声明和调用函数

3.1.1 自定义函数

关键字参数:通常用于指定默认值或可选参数。其余为位置参数。关键字参数必须位于位置参数之后。

  1. """
  2. ===================================
  3. Demo of xxx algorithm
  4. ===================================
  5. 功能说明
  6. """
  7. print(__doc__)
  8. def PrintString(str):
  9. '''
  10. 说明
  11. '''
  12. print(str)
  13. def my_function(x, y, z=1.5):
  14. if z > 1:
  15. return z * (x + y)
  16. else:
  17. return z / (x + y)
  18. my_function(5, 6, z=0.7)
  19. my_function(3.14, 7, 3.5)

当编写func(a, b, c, d=some, e=value)时,位置参数和关键字参数分别被打包成元组和字典。函数实际接收的是一个元组args和一个字典kwargs,并进行一些错误检查。

  1. a, b, c = args#内部转化
  2. d = kwargs.get('d', d_default_value)
  3. e = kwargs.get('e', e_default_value)
  1. def say_hello_then_call_f(f, *args, **kwargs):
  2. print 'args is', args
  3. print 'kwargs is', kwargs
  4. print("Hello! Now I'm going to call %s" % f)
  5. return f(*args, **kwargs)
  6. def g(x, y, z=1):
  7. return (x + y) / z
  8. In [8]: say_hello_then_call_f(g, 1, 2, z=5.)
  9. args is (1, 2)
  10. kwargs is {'z': 5.0}
  11. Hello! Now I'm going to call <function g at 0x2dd5cf8>
  12. Out[8]: 0.6

3.1.2 作用域

  1. a = 100; # 全局变量
  2. def setNumber():
  3. a = 10; # 局部变量
  4. print(a); # 打印局部变量a
  5. setNumber();
  6. print(a); # 打印全局变量a
  7. # 全局变量声明使用global!!!
  8. a = None
  9. def bind_a_variable():
  10. global a
  11. a = []
  12. bind_a_variable()
  13. print a
  14. def outer_function(x, y, z):#局部函数
  15. def inner_function(a, b, c):
  16. pass
  17. pass

设置断点,运行时可以查看变量的值。

柯里化:部分参数应用

通过“部分参数应用”从现有函数派生出新函数的技术。如:

  1. def add_numbers(x, y):
  2. return x + y
  3. add_five = lambda y: add_numbers(5, y)

内置的functools模块可以用partial函数将此过程简化:

  1. from functools import partial
  2. add_five = partial(add_numbers, 5)

例子:

  1. # compute 60-day moving average of time series x
  2. ma60 = lambda x: pandas.rolling_mean(x, 60)
  3. # Take the 60-day moving average of of all time series in data
  4. data.apply(ma60)

3.2 参数和返回值

3.2.1 在函数中传递参数

  1. def outer_function(x, y, z):
  2. def inner_function(a, b, c):
  3. pass
  4. pass
  5. def f():#返回多个值
  6. a = 5
  7. b = 6
  8. c = 7
  9. return a, b, c
  10. a, b, c = f()
  11. def f():#返回字典
  12. a = 5
  13. b = 6
  14. c = 7
  15. return {'a' : a, 'b' : b, 'c' : c}
  16. #####################函数是对象#####################
  17. states = [' Alabama ', 'Georgia!', 'Georgia', 'georgia', 'FlOrIda',
  18. 'south carolina##', 'West virginia?']
  19. def remove_punctuation(value):
  20. return re.sub('[!#?]', '', value)
  21. clean_ops = [str.strip, remove_punctuation, str.title]
  22. def clean_strings(strings, ops):
  23. result = []
  24. for value in strings:
  25. for function in ops:
  26. value = function(value)
  27. result.append(value)
  28. return result
  29. clean_strings(states, clean_ops)
  30. # 在一组数据上应用一个函数
  31. map(remove_punctuation, states)
  1. def func(num):
  2. print("形参num的地址", id(num))
  3. a = 10
  4. func(a);
  5. print("实参a的地址", id(a));

运行结果如下:
形参num的地址 1557053600
实参a的地址 1557053600
地址竟然是一样的!!!

默认参数:
在Python中,可以为函数的参数设置默认值。可以在定义函数时,直接在参数后面使用“=”为其设置默认值。在调用函数时可以不指定拥有默认值的参数的值,此时在函数体中以默认值作为该参数。

  1. def say(message, times = 1):
  2. print(message * times)
  3. say('hello')
  4. say('Python', 3)

有默认值的参数放在没有默认值的参数前面,可能会报错
关键参数:
可以任意顺序指定参数。

  1. def func(a, b=5, c=10):
  2. print a, b, c
  3. func(3, 7)
  4. func(25, c=24)
  5. func(c=50, a=100)

Python还支持可变长度的参数列表。可变长参数可以是元祖或字典。当参数以*开头时,表示可变长参数将被视为一个元祖,格式如下:
def func(*t):
在func ()函数中t被视为一个元祖,使用t[index]获取每一个可变长参数。
def func1(*t):
print("可变长参数数量如下:")
print(len(t))
print("依次为:")
for x in range(len(t)):
print(t[x]);
调用:func1(1,2,3,4);

以字典为可变长参数:
def sum(**t):
print(t);
sum(a=1,b=2,c=3);
运行结果如下:
{'a': 1, 'c': 3, 'b': 2}

3.3内置函数

3.3.1数学运算函数

函数 具体说明
abs(x) 返回 x 的绝对值
pow(x, y) 返回x的y次幂
round(x[, n]) 返回浮点数x的四舍五入值,参数n指定保留的小数位数
divmod(a, b) 返回商和余数组成的元组。如divmod(a, b)返回 (a / b, a % b)

3.3.2其他常用内置函数

help()函数
help()函数用于显示指定参数的帮助信息,语法如下:
help(para)
如果para是一个字符串,则会自动搜索以para命名的模块,方法等。如果para是一个对象,则会显示这个对象的类型的帮助信息。

type()函数用于显示指定对象的数据类型,语法如下:
type(obj)
obj是一个常量、变量或对象 

第4章 Python面向对象程序设计

4.2 定义和使用类

4.2.1 声明类

  1. class Person:
  2. name = zhou
  3. def SayHello(self):
  4. print("Hello!")

在成员函数SayHello()中有一个参数self。这也是类的成员函数(方法)与普通函数的主要区别。类的成员函数必须有一个参数self,而且位于参数列表的开头。self就代表类的实例(对象)自身,可以使用self引用类的属性和成员函数。
xxx表示系统定义名字。
xxx表示类中的私有属性,私有属性不能通过类名和对象名访问。共有属性可以通过类名和对象名两种方式访问。
**构造函数**是类的一个特殊函数,它拥有一个固定的名称,即__init

析构函数有一个固定的名称,即del ()

  1. class MyString:
  2. def __init__(self): #构造函数
  3. self.str = "MyString"
  4. def __del__(self): #析构函数
  5. print("byebye~")
  6. def output(self):
  7. print(self.str);
  8. s = MyString()
  9. s.output()
  10. del s #删除对象

4.2.2 静态变量

Python不需要显式定义静态变量,任何公有变量都可以作为静态变量使用。

  1. class Users (object):
  2. online_count = 0;
  3. def __init__(self):# 构造函数,创建对象时Users.online_count1
  4. Users.online_count+=1;
  5. def __del__(self):# 析构函数,释放对象时Users.online_count1
  6. Users.online_count-= 1;
  7. a = Users();创建Users对象
  8. a.online_count += 1
  9. print(Users.online_count);

4.2.3 方法

对象方法
如果在方法名前面加上了两个下划线,表示为私有方法。私有方法只能在对象的公有方法中通过self调用。
静态方法
静态方法不需要参数。只能通过类名调用。
1. 静态方法无需传入self参数,因此在静态方法中无法访问属于对象的成员,只能访问属于类的成员。
2. 在静态方法中不可以直接访问类的静态变量,但可以通过类名引用静态变量。

因为不能直接访问类的静态变量,所以静态方法与定义它的类没有直接关系,而是起到了类似函数工具库的作用。

  1. class 类名:
  2. @staticmethod
  3. def 静态方法名():
  4. 方法体
  5. @classmethod
  6. def 类方法名(cls):
  7. 方法体

类方法
1. 类方法可以使用类名调用类方法。
2. 类成员方法也无法访问实例变量,但可以访问类的静态变量。
3. 类方法需传入代表本类的cls参数

4.2.4 instance()函数判断对象类型

isinstance(对象名, 类名或类型名)

4.3 类的继承和多态

4.3.1 继承

从类A派生一个类B,代码如下:

  1. class B(A) :
  2. propertyB; # 类B的成员变量
  3. def functionB(): # 类B的成员函数

支持多重继承,需要以逗号分隔。

  1. class UserLogin(Users):
  2. def __init__(self, uname, lastLoginTime):
  3. Users.__init__(self, uname) #调用父类Users的构造函数
  4. self.lastLoginTime = lastLoginTime
  5. def dispLoginTime (self):
  6. print(" 登录时间为:" + self.lastLoginTime);
  7. #获取当前时间
  8. now = time.strftime('%Y-%m-%d%H:%M:%S',time.localtime(time.time()))

4.3.2 抽象类和多态

Python通过类库abc实现抽象类,因此在定义抽象类之前需要从类库abc导入ABCMeta类和abstractmethod类。

  1. from abc import ABCMeta, abstractmethod

ABCMeta是 Metaclass for defining Abstract Base Classes的缩写,也就是抽象基类的元类。所谓元类就是创建类的类。在定义抽象类时只需要在类定义中增加如下代码:

  1. __metaclass__ = ABCMeta

即指定该类的元类是ABCMeta。例如:

  1. class myabc(object):
  2. __metaclass__ = ABCMeta

在抽象类里面可以定义抽象方法。定义抽象方法时需要在前面加上下面的代码:

  1. @abstractmethod

因为抽象方法不包含任何实现的代码,所以其函数体通常使用pass。例如,在抽象类myabc中定义一个抽象方法abcmethod(),

  1. class myabc(object):
  2. __metaclass__ = ABCMeta
  3. @abstractmethod
  4. def abcmethod (self):pass

重载
子类中使用与父类完全相同的方法名,从而重载父类的方法。

4.4 复制对象

新对象名 = 原有对象名 

第5章 Python模块

5.1 Python标准库中的常用模块

模块是Python语言的一个重要概念,它可以将函数按功能划分到一起,以便日后使用或共享给他人。可以使用Python标准库中的模块,也可以下载和使用第三方模块。

5.1.1 sys模块

sys模块是Python标准库中最常用的模块之一。通过它可以获取命令行参数,从而实现从程序外部向程序传递参数的功能;也可以获取程序路径和当前系统平台等信息。

5.1.2 platform模块

CPython:默认的Python实现。脚本大多数情况下都运行在这个解释器中。 CPython是官方的python解释器,完全按照Python的规格和语言定义来实现,所以被当作其他版本实现的参考版本。CPython是用C语言写的,当执行代码的时候Python代码会被转化成字节码。因此CPython是个字节码解释器。
PyPy:由Python写成的解释器。很多地方都和CPython很像的实现。这个解释器的代码先转化成C,然后再编译。PyPy比CPython性能更好。因为CPython会把代码转化成字节码,PyPy会把代码转化成机器码。

5.1.3 与数学有关的模块

math

方法 具体说明
math.asin (x) 返回 x 的反正弦
math.asinh(x) 返回 x 的反双曲正弦
math.atan(x) 返回 x 的反正切
math.atan2(y,x) 返回 y/x 的反正切
math.atanh(x) 返回 x 的反双曲正切
math.ceil(x) 返回大于等于x的最小整数
math.copysign(x,y) 返回与 y 同号的 x 值
math.cos(x) 返回 x 的余弦
math.cosh(x) 返回 x 的双曲余弦
math.degrees(x) 将x(弧长)转成角度,与radians为反函数
math.exp(x) 返回 ex
math.fabs(x) 返回x的绝对值
math.factorial(x) 返回 x!

random

方法 具体说明
random.random() 生成一个0到1的随机浮点数: 0 <= n < 1.0
random.uniform(a, b) 用于生成一个指定范围内的随机符点数,两个参数其中一个是上限,另一个是下限。如果a > b,则生成的随机数n满足a <= n <= b。如果 a
random.randint(a, b) 用于生成一个指定范围内的整数。其中参数a是下限,参数b是上限,生成的随机数n: a <= n <= b
random.randrange([start], stop[, step])(y,x) 从指定范围内,按指定基数递增的集合中获取一个随机数。如:random.randrange(1, 10, 2),结果相当于从[2, 4, 6, 8]序列中获取一个随机数
random.choice (sequence) 从序列中获取一个随机元素。参数sequence表示一个有序类型,可以是列表、元祖或字符串
random.shuffle(x[, random]) 用于将一个列表中的元素打乱。x是一个列表
random.sample(sequence, k) 从指定序列中随机获取指定长度(k)的片断。原有序列不会被修改

decimal
浮点数缺乏精确性,decimal模块提供了一个Decimal 数据类型用于浮点数计算。与内置的二进制浮点数实现float相比,Decimal 数据类型更适用于金融应用和其他需要精确十进制表达的情况。
使用下面的方法可以定义Decimal类型的数据:

  1. from decimal import Decimal
  2. Decimal(数字字符串)

fractions模块
fractions模块用于表现和处理分数。

  1. import fractions
  2. x = fractions.Fraction(分子, 分母)
  3. Fraction对象将会自动进行约分。

5.1.4 time模块

  1. from datetime import datetime, date, time
  2. dt = datetime(2011, 10, 29, 20, 30, 21)
  3. print dt.day#29
  4. print dt.minute#30
  5. print dt.date()#2011-10-29
  6. print dt.time()#20:30:21
  7. print dt.strftime('%m/%d/%Y %H:%M')#10/29/2011 20:30 格式化变成了字符串
  8. print datetime.strptime('20091031', '%Y%m%d')#2009-10-31 00:00:00
  9. print dt.replace(minute=0, second=0)#2011-10-29 20:00:00
  10. dt2 = datetime(2011, 11, 15, 22, 30)
  11. delta = dt2 - dt
  12. print delta#17 days, 1:59:39
  13. type(delta)#datetime.timedelta
  14. print dt + delta#2011-11-15 22:30:00
  15. time.time()#获取当前时间的时间戳
  16. time.localtime()#将一个时间戳转换成一个当前时区的struct_time
  17. time.ctime()#可以返回当前时间的字符串。

5.2 自定义和使用模块

5.2.1创建自定义模块

5.2.2导入模块

  1. #mymodule.py
  2. def PrintString(str):
  3. print(str);
  4. #求和
  5. def sum(num1, num2):
  6. print(num1 + num2);
  7. import mymodule # 导入mymodule模块
  8. mymodule.PrintString("Hello Python")#调用PrintString()函数
  9. mymodule.sum(1,2) #调用sum()函数

第6章 函数式编程

一种编程的基本风格。将计算过程看作是数学函数,使用表达式编程。
函数式编程的优点

  1. 便于进行单元测试
  2. 便于调试
  3. 适合并行执行

6.1 函数式编程

6.1.1 匿名函数 lambda

lambda表达式的函数体只能有一条语句,也就是返回值表达式语句。其语法如下:

  1. func = lambda input1, ...inputn : return_expr

例如

  1. sum = lambda x,y,z : x+y+z #求和
  2. sum(1,2,3)#调用

可以将lambda 表达式作为数组元素(也可以是列表或字典),从而实现跳转表的功能(函数的列表)。lambda 表达式数组的定义方法如下:

  1. arrObject = [(lambda expr1), (lambda expr2), …]
  2. Arr= [(lambda x: x**2), (lambda x: x**3), (lambda x: x**4)]
  3. # 下面分别调用列表函数
  4. print (Arr[0](2), Arr[1](2), Arr[2](2)) #2的平方、立方和四次方组成的元组

可以将lambda 表达式作为函数的返回值:

  1. def math(o):
  2. if(o==1):
  3. return lambda x,y : x+y
  4. if(o==2):
  5. return lambda x,y : x-y
  6. if(o==3):
  7. return lambda x,y : x*y
  8. if(o==4):
  9. return lambda x,y : x/y
  10. action = math(1)#返回加法Lambda表达式
  11. print("10+2", action(10,2))
  12. action = math(2)#返回减法Lambda表达式
  13. print("10-2=",action(10,2))
  14. action = math(3)#返回乘法Lambda表达式
  15. print("10*2,=",action(10,2))
  16. action = math(4)#返回除法Lambda表达式
  17. print("10/2,=",action(10,2))
  18. #############lambda函数是一个对象################
  19. def apply_to_list(some_list, f):
  20. return [f(x) for x in some_list]
  21. ints = [4, 0, 1, 5, 6]
  22. apply_to_list(ints, lambda x: x * 2)
  23. strings = ['foo', 'card', 'bar', 'aaaa', 'abab']
  24. strings.sort(key=lambda x: len(set(list(x))))#根据单词中字母多少来排序
  25. strings

6.2.2 map()

map()函数用于将指定序列中的所有元素作为参数调用指定函数,并将结果构成一个新的序列返回。map函数的语法如下:

  1. 结果序列 = map(映射函数, 序列1[, 序列2,…])

例子

  1. arr = map(lambda x: x ** 2, [2, 4, 6, 8, 10])
  2. for e in enumerate(arr):
  3. print(e)
  4. arr = map(lambda x,y: x + y, [1, 3, 5, 7, 9] ,[2, 4, 6, 8, 10])
  5. for e in enumerate(arr):
  6. print(e)

6.2.3 filter()

filter()函数可以对指定序列执行过滤操作,具体定义如下:

  1. filter(函数function, 序列sequence)
  2. #函数function接受一个参数,返回布尔值True或False。序列sequence可以是列表、元组或字符串

例子

  1. def is_even(x):
  2. return x %2 == 0
  3. arr = filter(is_even, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
  4. print arr #[2, 4, 6, 8, 10]

6.2.4 reduce()

reduce()函数用于将指定序列中的所有元素作为参数按一定的规则调用指定函数。reduce函数的语法如下:

  1. 计算结果= reduce(映射函数, 序列)

映射函数的必须有2个参数。reduce()函数首先以序列的第1和第2个元素为参数调用映射函数,然后将返回结果与序列的第3个元素为参数调用映射函数。以此类推,直至应用到序列的最后一个元素,将计算结果作为reduce()函数的返回结果。

  1. from functools import reduce#python 3.0之后不被集成到内置函数中
  2. def myadd(x,y):
  3. return x+y
  4. sum=reduce(myadd,(2,4,6,8,10))
  5. print(sum)

6.2.5 zip()

zip()函数以一系列列表作为参数,将列表中对应的元素打包成一个个元组,然后返回由这些元组组成的列表。

  1. a = [1,2,3]
  2. b = [4,5,6,7,8,9]
  3. zipped = zip(a,b)#[(1, 4), (2, 5), (3, 6)]
  4. for element in zipped:
  5. print(element)
  6. a = [1,2,3]
  7. b = [4,5,6]
  8. zipped = zip(a,b)
  9. unzipped = zip(*zipped)#解压[(1, 2, 3), (4, 5, 6)]
  10. for element in unzipped:
  11. print(element)

6.2.6 对比

函数式编程:

  1. 代码更简单。
  2. 数据,操作,返回值都放在一起。
  3. 没有循环体,几乎没有临时变量,也就不用劳神去分析程序的流程行尾数据变化过程了。
  4. 代码用来要做什么,而不是怎么去做。
  1. list1 =[2, -6, 11, -7, 8, 15, -14, -1, 10, -13, 18]
  2. sum = 0
  3. for i in range(len(list)):
  4. if list [i]>0:
  5. sum += list1[i]
  6. print(sum)
  7. #######################################
  8. from functools import reduce
  9. list1 =[2, -6, 11, -7, 8, 15, -14, -1, 10, -13, 18]
  10. sum = filter(lambda x: x>0, list1)
  11. s = reduce(lambda x,y: x+y, sum)
  12. print(s)

6.3 闭包和递归函数

闭包:闭包指函数的嵌套。可以在函数内部定义一个嵌套函数,将嵌套函数视为一个对象,所以可以将嵌套函数作为定义它的函数的返回结果。被返回的函数可以访问其创建者的局部命名空间中的变量。

  1. def func_lib():
  2. def add(x, y):
  3. return x+y
  4. return add # 返回函数对象
  5. fadd = func_lib()
  6. print(fadd(1, 2))
  7. ##
  8. def make_closure(a):
  9. def closure():
  10. print 'I know the secret: %d' % a
  11. return closure
  12. closure = make_closure(5)
  13. closure()
  14. ## 记录曾经传入的一切参数
  15. def make_watcher():
  16. have_seen = {}
  17. def has_been_seen(x):
  18. if x in have_seen:
  19. return True
  20. else:
  21. have_seen[x] = True
  22. return False
  23. return has_been_seen
  24. watcher = make_watcher()
  25. vals = [5, 6, 1, 5, 1, 6, 3, 5]
  26. [watcher(x) for x in vals]
  27. ## 15位字符串浮点数格式化器
  28. def format_and_pad(template, space):
  29. def formatter(x):
  30. return (template % x).rjust(space)
  31. return formatter
  32. fmt = format_and_pad('%.4f', 15)
  33. fmt(1.756)

递归函数:递归函数是指直接或间接调用函数本身的函数。

  1. def fact(n):
  2. if n==1:
  3. return 1
  4. return n * fact(n - 1)
  5. print(fact(5))

6.4 迭代器和生成器

6.4.1 迭代器

迭代器是访问集合内元素的一种方式。迭代器对象从序列(列表、元组、字典、集合)的第一个元素开始访问,直到所有的元素都被访问一遍后结束。迭代器不能回退,只能往前进行迭代。
1.iter()函数
使用内建的工厂函数iter(iterable)可以获取序列的迭代器对象,方法如下:迭代器对象 = iter(序列对象)
使用next()函数可以获取迭代器的下一个元素,方法如下:next(迭代器对象)

  1. list = [111, 222, 333]
  2. it = iter(list)
  3. print(next(it))
  4. print(next(it))
  5. print(next(it))

2、enumerate ()函数
使用enumerate ()函数可以将列表或元组生成一个有序号的序列。

  1. list = [111, 222, 333]
  2. for index , val in enumerate(list):
  3. print("第%d个元素是%s" %(index+1, val))

6.4.2 生成器

生成器是构造新的可迭代对象的一种简单方式。以延迟的方式返回一个值序列,每返回一个值之后暂停,直到下一个值被请求时再继续。创建只需要将函数中的return替换为yield即可。 生成器是一个特殊的函数,它具有如下特点:

  1. 生成器函数都包含一个yield语句,当执行到yield语句时函数返回;
  2. 生成器函数可以记住上一次返回时在函数体中的位置,对生成器函数的下一次调用跳转至该函数中间,而上次调用的所有局部变量都保持不变。
  1. #addlist()是一个生成器,它会遍历列表参数alist中的每一个元素,然后将其加1,并使用yield语句返回。生成器的返回值有一个__next__()方法,它可以恢复生成器执行,直到下一个yield表达处
  2. # Python 3
  3. def addlist(alist):
  4. for i in alist:
  5. yield i + 1
  6. alist = [1, 2, 3, 4]
  7. x = addlist(alist)#生成器
  8. x= x.__next__();
  9. print(x);
  10. x= x.__next__();
  11. print(x);
  12. x= x.__next__();
  13. print(x);
  14. x= x.__next__();
  15. print(x);

第7章 IO编程

7.1 输入和显示数据

7.1.1 输入数据

用户输入的数据 = input( 提示字符串)

  1. a = eval(raw_input("Enter a value:")) #字符串转换为数字

7.1.2 输出数据

  1. for i in range(0,10):
  2. print(i, end='')#不会换行

科学计数法:123.456表示成1.23456E2
不换行打印:print(item, end =’ ’) print(‘BBB’, end = ‘ ‘ )
格式化浮点数:print(format(57.3, “10.2f”)):10位长度2位小数
“10.2%”:写成百分数形式
“<10.2f”:左对齐

7.2 文件操作

与文件相关的模块:
os模块:对目录和文件进行操作
os.path模块:文件的属性获取
shutil模块:日常的文件和目录管理任务

7.2.1 打开文件

在读写文件之前,需要打开文件。调用open()函数可以打开指定文件,语法如下:
文件对象 = open(文件名,访问模式,buffering)
也可以使用file()函数打开文件,file()函数和open()函数的用法完全相同。
访问模式参数的可取值

可取值 含 义
r 以读方式打开
w 以写方式打开,此时文件内容会被清空。如果文件不存在则会创建新文件
a 以追加的模式打开,从文件末尾开始,必要时创建新文件
r+ 以读写模式打开
w+ 以读写模式打开
a+ 以追加的读写模式打开
rb 以二进制读模式打开
wb 以二进制写模式打开
ab 以二进制追加模式打
rb+ 以二进制读写模式打开
wb+ 以二进制读写模式打开
ab+ 以二进制读写模式打开

7.2.2 关闭文件

  1. f.close()

7.2.3 读取文件内容

1.read()

  1. str = f.read([b]) #b读取的字节数

2.readlines()

  1. list= f.readreadlines() # 读取文件中的所有行,返回行字符串列表

3.readline()

  1. str= f.readline() #逐行读取文件的内容

4.使用in关键字

  1. for line in f:
  2. # 处理行数据line

7.2.4 写入文件

1.write()方法

  1. f. write(str)

2.追加写入
以a或a+为参数调用open()方法打开文件。
3.writelines()方法

  1. f.writelines(sequence_of_strings) #写入字符串序列

7.2.5 文件指针

1.获取文件指针的位置
文件指针是指向一个文件的指针变量,用于标识当前读写文件的位置,通过文件指针就可对它所指的文件进行各种操作。打开一个文件时,文件指针的位置为0。

  1. pos = f.tell() #获取文件指针的位置

2.移动文件指针

  1. f.seek((offset,where))

offset:移动的偏移量,单位为字节。等于正数时向文件尾方向移动,等于负数时向文件头方向移动文件指针。
where:指定从何处开始移动。等于0时从起始位置移动,等于1时从当前位置移动,等于2时从结束位置移动。

7.2.6截断文件

可以使用truncate()方法从文件头开始截取文件

  1. f.truncate([size])

参数size指定要截取的文件大小,单位为字节,size字节后面的文件内容将被丢弃掉。

7.2.7 文件属性

使用os模块的stat()函数可以获取文件的创建时间、修改时间、访问时间、文件大小等文件属性。

  1. 文件属性元组 = os.stat(文件路径)

os.stat()返回的文件属性元组元素的含义

索引 含 义
0 权限模式
1 inode number,记录文件的存储位置。inode是指在许多“类Unix文件系统”中的一种数据结构。每个inode保存了文件系统中的一个文件系统对象(包括文件、目录、设备文件、socket、管道等)的元信息数据,但不包括数据内容或者文件名
2 存储文件的设备编号
3 文件的硬连接数量。硬链接是Linux中的概念,指为文件创建的额外条目.使用时, 与文件没有区别;删除时,只会删除链接,不会删除文件
4 文件所有者的用户ID(user id)
5 文件所有者的用户组ID(user id)
6 文件大小,单位为字节
7 最近访问的时间
8 最近修改的时间
9 创建的时间

sta模块中定义的文件属性元组索引对应的常用常量

索引 常量
0 stat.ST_MODE
6 stat.ST_SIZE
7 stat.ST_MTIME
8 stat.ST_ATIME
9 stat.ST_CTIME
  1. import os, stat
  2. fileStats = os.stat('test.txt') #获取文件/目录的状态
  3. print(fileStats[stat.ST_SIZE])
  4. print(fileStats[stat.ST_MTIME])
  5. print(fileStats[stat.ST_ATIME])
  6. print(fileStats[stat.ST_CTIME])

7.2.8 复制文件

  1. shutil.copy("C:\\Python34\\LICENSE.txt", "D:\\LICENSE.txt")

7.2.9 移动文件

  1. move(src, dst)

7.2.10 删除文件

  1. os.remove(src) # src指定要删除的文件

7.2.11 重命名文件

  1. os.rename(原文件名, 新文件名)

7.3 目录编程

7.3.1 获取当前目录

  1. os.getcwd()

7.3.2 获取目录内容

  1. os.listdir(path)

7.3.3 创建目录

  1. os.mkdir(path)

7.3.4 删除目录

  1. os.rmdir(path)

第8章 图形界面编程

Python提供了一些用于图形界面编程的模块,包括Tkinter模块、wxWidgets模块、easygui模块和wxpython模块。
Tkinter模块:是Python的标准T看GUI工具包的接口。
wxPython:开源软件,GUI图形库,下载:wxpython.org/download.php

8.1 常用Tkinter组件的使用

  1. import Tkinter #导入Tkinter模块
  2. import Tkinter as tk #导入Tkinter为tk
  3. from tkinter import * #导入Tkinter所有内容
  4. form tkinter import func1 #导入模块的某一函数

8.1.1 弹出消息框

  1. from tkinter.messagebox import *
  2. showinfo(title=‘标题’,message=‘内容’) # 提示消息框
  3. showwarning(title=‘标题’,message=‘内容’) # 警告消息框
  4. showerror(title=‘标题’,message=‘内容’) # 错误消息消息框
  5. askquestion (title=‘标题’,message=‘内容’) #是否疑问消息框,“是” 返回字符串'yes', “否” ,'no'
  6. askyesnocancel(title=‘标题’,message=‘内容’) # “是否”疑问消息框:返回True, False
  7. askokcancel(title=‘标题’,message=‘内容’) # “确定”“取消”疑问消息框:返回True, False
  8. askretrycancel(title=‘标题’,message=‘内容’) #重试取消疑问消息框:返回True, False

8.1.2 创建Windows窗口

  1. #1.导入Tkinter模块
  2. from tkinter import *
  3. #2.创建窗口对象
  4. win = Tk();
  5. #3.显示Windows窗口
  6. win.mainloop();
  7. #4.设置窗口标题
  8. win.title(titlestr)
  9. #5.设置窗口大小
  10. win.geometry(“宽度x高度”)
  11. #或者
  12. win.minsize(minWidth, minHeight)

8.1.3 Label组件

  1. # 1.创建和显示Label对象
  2. LabelObject = Label(Tkinter WindowsObject,text =“display text”)
  3. LabelObject.pack()
  4. # 2.使用Label组件显示图片
  5. # hourglass-沙漏图标
  6. # info-信息图标
  7. # questhead-信息图标
  8. # question-疑问图标
  9. # warning-警告图标
  10. # gray12/25/50/75-灰度背景图标
  11. #显示自定义图片
  12. # bm = PhotoImage(file = 'C:\Python34\Lib\idlelib\Icons\idle_48.png')
  13. # label = Label(win,image = bm)
  14. # label.pack()#显示Label组件
  15. l1 = Label(win,bitmap = 'error')# 显示错误图标
  16. 3.设置Label组件的颜色
  17. label = Label(win, fg = 'red',bg = 'blue', text='字符串')

其他常用的Lable组件属性

属 性 说明
width 宽度
height 高度
compound 指定文本与图像如何在Label上显示,缺省为None。当指定image/bitmap时,文本(text)将被覆盖,只显示图像。可以使用的值如下: left,Right,top,bottom,center
wraplength 指定多少单位后开始换行,用于多行显示文本
justify 指定多行的对齐方式,可以使用的值为LEFT(左对齐)或RIGHT(右对齐)
ahchor 指定文本(text)或图像(bitmap/image)在Label中的显示位置。可用值如下:e,w,n,s,ne,se,sw,nw,center

8.1.4 Button组件

  1. 1.创建和显示Button对象
  2. ButtonObject= Button (Tkinter WindowsObject,text =“ ”, command=func1)
  3. ButtonObject.pack()
  4. 2.使用Button组件显示图片
  5. bm = PhotoImage(file =”C:\pic.jpg”)
  6. b = Button (win,text = ' ', command=func,image = bm)
  7. 3.设置Button组件的大小
  8. b = Button (win,text = '点我啊', command=CallBack, width=100, height=50)

常用的Button组件属性

属 性 说明
bitmap 指定按钮上显示的位图
compound 指定文本与图像如何在Label上显示,缺省为None。当指定image/bitmap时,文本(text)将被覆盖,只显示图像。可以使用的值如下:left,Right,top,bottom,center
wraplength 指定多少单位后开始换行,用于多行显示文本
bg 设置背景颜色
fg 设置前景颜色
state 设置组件状态。可以取值为正常(NORMAL)、激活(ACTIVE)和禁用(DISABLED)
bd 设置按钮的边框大小;缺省为1或2个像素

8.1.5 Canvas画布组件

  1. # 1.创建和显示Canvas对象
  2. CanvasObject= Canvas (WindowObject,width, height, …)
  3. CanvasObject.pack()

Canvas对象时的常用选项

属 性 说明
bd 指定画布的边框宽度,单位是像素
bg 指定画布的背景颜色
confine 指定画布在滚动区域外是否可以滚动。默认为True,表示不能滚动
cursor 指定画布中的鼠标指针,例如arrow, circle, dot
highlightcolor 选中画布时的背景色
relief 指定画布的边框样式,可选值包括SUNKEN, RAISED, GROOVE, and RIDGE
scrollregion 指定画布的滚动区域的元组(w, n, e, s)
  1. # 2.绘制线条
  2. line = canvas.create_line(x0, y0, x1, y1, ..., xn, yn, 选项)

创建矩形对象时的常用选项

属 性 说明
width 指定线段的宽度
arrow 指定直线是否使用箭头,可:'none','first','last','both'
arrowshape 设置箭头的形状,由3个整数构成,分别代表填充长度、箭头长度和箭头宽度。如,arrowshape = '40 40 10'
fill 指定线段的颜色
dash 指定线段为虚线
  1. # 3.绘制矩形
  2. CanvasObject. create_rectangle(x0,y0,x4,y4, 选项, ...)

创建矩形对象时的常用选项

属 性 说明
outline 指定边框颜色
fill 指定填充颜色
width 指定边框的宽度
dash 指定边框为虚线
stipple 使用指定自定义画刷填充矩形
  1. # 4.绘制弧
  2. Canvas. create_arc(弧对应圆外切矩形左上角的x0, y0, 弧外框矩形右下角的x4, y4, 选项, ...)

创建弧对象时的常用选项

属 性 说明
outline 指定边框颜色
fill 指定填充颜色
width 指定边框的宽度
start 起始弧度
extent 终止弧度
  1. # 5.绘制多边形
  2. CanvasObject. create_polygon (x0, y0, x1, y1, …, xn, yn, 选项, ...)
  3. 创建多边形对象时的常用选项
属 性 说明
outline 指定边框颜色
fill 指定填充颜色
width 指定边框的宽度
smooth 指定多边形的平滑程度。等于0表示多边形的边是折线。等于1表示多边形的边是平滑曲线
  1. # 6.绘制椭圆
  2. CanvasObject. create_oval(x0, y0, width, height, 选项, ...)

创建椭圆对象时的常用选项

属 性 说明
outline 指定边框颜色
fill 指定填充颜色
width 指定边框的宽度
  1. # 7.绘制文字
  2. TextObject = CanvasObject.create_text((文本左上角的x0,y0), 选项, ...)
  3. CanvasObject select_from(文字对象, 选中文本的起始位置)
  4. CanvasObject. select_to(文字对象, 选中文本的结束位置)

创建文字对象时的常用选项

属 性 说明
text 文字对象的文本内容
fill 指定文字颜色
anchor 控制文字对象的位置,'w','e','n','s','nw', 'sw', 'se', 'ne', 'center'。默认值为'center'
justify 设置文字对象中文本的对齐方式。'left','right','center'。默认值为'center'
  1. # 8.绘制图像
  2. # 绘制位图
  3. CanvasObject. create_bitmap((位图左上角的x0, y0),bitmap =’error’)
  4. d = {1:'error',2:'info',3:'question',4:'hourglass'}
  5. for in d:
  6. cv.create_bitmap((20*i,20*i),bitmap = d[i])
  7. # 绘制图片
  8. img = PhotoImage(file = 'C:\\python.gif')
  9. cv.create_image((100,50),image=img)
  1. # 9.修改图形对象的坐标
  2. CanvasObject.coords(FigureObject, (图形左上角的x0, y0, x4, 图形右下角的y4))
  1. # 10.移动指定图形对象
  2. Canvas对象. move (FigureObject, x, y)
  1. # 11.删除图形对象
  2. cv.delete(rt1)
  1. 12.缩放图形对象
  2. CanvasObject.scale(FigureObject, x, y ,x轴缩放比例,y轴缩放比例)
  1. #13.为图形对象指定标记(tag)
  2. rt1 = cv.create_rectangle(10,10,110,110, tags = 'r1')
  3. rt2 = cv.create_rectangle(10,10,110,110, tags = ('r1','r2','r3'))
  4. Canvas.find_withtag(tag名)
  5. # find_withtag()方法返回一个图形对象数组,其中包含所有具有tag名的图形对象。
  6. Canvas. find_withtag(图形对象, 属性1=值1, 属性2=值2…… )

8.1.6 Checkbutton组件

  1. from tkinter import *
  2. root = Tk()
  3. #将一字符串与Checkbutton的值绑定,每次点击Checkbutton,将打印出当前的值
  4. v = StringVar()
  5. def callCheckbutton():
  6. print(v.get())
  7. Checkbutton(root,
  8. variable = v,
  9. text = 'checkbutton value',
  10. onvalue = 'python', #设置On的值
  11. offvalue = 'tkinter', #设置Off的值
  12. command = callCheckbutton).pack()
  13. b = Button (root,text = '获取Checkbutton状态', command=callCheckbutton, width=20)#创建Button组件
  14. v.set('python')
  15. b.pack()#显示Button组件
  16. root.mainloop()

8.1.7 Entry组件

  1. from tkinter import *
  2. root = Tk()
  3. #将一字符串与Entry的值绑定
  4. e = StringVar()
  5. def callbutton():
  6. print(e.get())
  7. root.title("使用Entry组件的简单例子")#设置窗口标题
  8. entry = Entry(root, textvariable = e).pack()
  9. b = Button(root,text = '获取Entry组件的内容', command=callbutton, width=20)#创建Button组件
  10. e.set('python')
  11. b.pack()#显示Button组件
  12. root.mainloop()

8.1.8 Frame组件

  1. # 1.创建和显示Frame对象
  2. FrameObject = Frame (Tkinter WindowsObject, height = 高度,width = 宽度,bg = 背景色)
  3. Frame对象.pack()
  4. # 2.向Frame组件中添加组件
  5. Label(fm,text = 'Hello Python').pack()
  6. Button(fm,text = 'OK').pack()
  7. # 3.LabelFrame组件
  8. LabelFrame (Tkinter Windows窗口对象, height = 高度,width = 宽度,text = 标题).pack()

8.1.9 Listbox组件

  1. # 1.创建和显示Listbox对象
  2. ListboxObject= Listbox (Tkinter WindowsObject)
  3. ListboxObject.pack()
  4. ListboxObject.insert(index,item)
  5. # 2.设置多选的列表框
  6. lb = Listbox(root, selectmode = MULTIPLE)
  7. # 3.获取Listbox组件的内容
  8. from tkinter import *
  9. root = Tk()
  10. # 将一字符串与Listbox的值绑定
  11. l = StringVar()
  12. def callbutton():
  13. print(l.get())
  14. root.title("使用Entry组件的简单例子")#设置窗口标题
  15. lb = Listbox(root, listvariable =l)
  16. for item in ['北京','天津','上海']:
  17. lb.insert(END,item)
  18. lb.pack()
  19. b = Button (root,text = '获取Listbox组件的内容', command=callbutton, width=20)#创建Button组件
  20. b.pack()#显示Button组件
  21. root.mainloop()

8.1.10Menu组件

  1. # 1.创建和显示Menu对象
  2. MenuObject = Menu(Tkinter WindowsObject)
  3. Tkinter WindowsObject['menu'] = menubar
  4. Tkinter WindowsObject.mainloop()
  5. m = Menu(root)
  6. for item in ['系统','操作','帮助']:
  7. m.add_command(label =item, command = hello)
  8. # 2.添加下拉菜单
  9. MenuObject1.add_cascade(label = ’,menu = MenuObject2)
  10. root = Tk()
  11. m = Menu(root)
  12. filemenu = Menu(m)
  13. for item in ['打开','关闭','退出']:
  14. filemenu.add_command(label =item, command = hello)
  15. m.add_cascade(label ='文件', menu = filemenu)
  16. root['menu'] = m
  17. # 3.在菜单中添加复选框
  18. MenuObject.add_checkbutton(label = ”,command =func1,variable = 与复选框绑定的变量)
  19. def hello():
  20. print(v.get())
  21. root = Tk()
  22. v = StringVar()
  23. m = Menu(root)
  24. filemenu = Menu(m)
  25. for item in ['打开','关闭','退出']:
  26. filemenu.add_command(label =item, command = hello)
  27. m.add_cascade(label ='文件', menu = filemenu)
  28. filemenu.add_checkbutton(label = '自动保存',command = hello,variable = v)
  29. root['menu'] = m
  30. root.mainloop()
  31. # 4.在菜单中添加单选按钮
  32. menuObject.add_radiobutton(label = ”,command = func1,variable = 与单选按钮绑定的变量)
  33. from tkinter import *
  34. def hello():
  35. print(v.get())
  36. root = Tk()
  37. v = StringVar()
  38. m = Menu(root)
  39. filemenu = Menu(m)
  40. filemenu.add_command(label ='打开', command = hello)
  41. filemenu.add_command(label ='关闭', command = hello)
  42. filemenu.add_separator()#分割线
  43. filemenu.add_command(label ='退出', command = hello)
  44. m.add_cascade(label ='文件', menu = filemenu)
  45. root['menu'] = m
  46. root.mainloop()
  47. # 5.在菜单中的当前位置添加分隔符
  48. filemenu.add_separator()#分割线

8.1.11 Radiobutton单选组件

  1. from tkinter import *
  2. win = Tk() #创建窗口对象
  3. v = IntVar()
  4. v.set(1)
  5. win.title("使用Radiobutton组件的简单例子") #设置窗口标题
  6. r1 = Radiobutton(win,text = '男', value=1, variable = v)#创建Radiobutton组件
  7. r1.pack()#显示Radiobutton组件
  8. r2 = Radiobutton(win,text = '女',value=0, variable = v)#创建Radiobutton组件
  9. r2.pack()#显示Radiobutton组件
  10. win.mainloop();

8.1.12 Scale组件

  1. v = StringVar()
  2. Scale(root,
  3. from_ = -0, #设置最大值
  4. to = 100, #设置最小值
  5. resolution = 1, #设置步距值
  6. orient = HORIZONTAL, #设置水平方向
  7. variable =v
  8. ).pack()
  9. root.mainloop()

8.1.13 Text组件

  1. from tkinter import *
  2. root = Tk()
  3. t = text(root) #创建
  4. t.insert(1.0, 0123456789”)#10
  5. t.insert(1,5, inserted”)
  6. t.pack()
  7. root.mainloop()

8.2 窗体布局

8.2.1 pack()方法

  1. lb.pack(expend = yes”, fill = both”)#ListBox大小随窗口的大小变化

8.2.2 grid()方法

  1. mainframe.grid(column=0, row=0, ,sticky =(N,W, E,S))#四周对齐
  2. mainframe.columnconfigure(0,weight=1)
  3. mainframe.rowconfigure(0, weight=1)
  4. uname_entry.grid(column=2, cloumnspan =2, row=1, sticky=(W,E))#W,E表示左右对齐
  5. …….
  6. for child in mainframe.winfo_children():
  7. child.grid_configure(padx=5,pady=5)#设置间距为5

8.2.3 place()方法

  1. label1.place(x=50,y=50, anchor = NW) #anchor对齐方式

8.3 Tkinter字体

  1. form Tkinter import *
  2. import tkFont
  3. thFontObject = tkFont.Font(family =”隶书文字”, size =20, weight =thFont.BOLD, slat = tkFont.ITALIC, underline =1, overstrike =1)
  4. Label(root, text = ”, font =thFontObject).grid()

8.4 事件处理

8.4.1 键盘

  1. def press(event):
  2. print(‘按下’+event.char)
  3. …….
  4. t=Text(win)
  5. t.bind(“<KeyPress>”, press)
  6. t.pack()
  7. win.mainloop()

8.4.2 鼠标

事件名。n=1左键,2中键,3右键
主要事件:ButtonPress\ButtonReleas\Motion\Enter\Leave\MouseWheel

8.4.3 窗体事件

  1. def FocusIn(event):
  2. print(‘hello’)
  3. def FocusOut(event):
  4. print(‘Bye’)
  5. ……
  6. t= Text(win)
  7. t.bind(“<FocusIn>”, FocusIn)
  8. t.bind(“<FocusOut>”, FocusOut)
  9. t.pack() 

第9章 多任务编程

9.1 多进程编程

多任务编程通常指用户可以在同一时间内运行多个应用程序,也指一个应用程序内可以在同一时间内运行多个任务。多任务编程是影响应用程序性能的重要因素。

9.1.1 什么是进程

进程是正在运行的程序的实例。每个进程至少包含一个线程,它从主程序开始执行,直到退出程序,主线程结束,该进程也被从内存中卸载。主线程在运行过程中还可以创建新的线程,实现多线程的功能。
组成:

9.1.2 进程的状态

在操作系统内核中,进程可以被标记成“被创建”(created)、“就绪”(ready)、“运行”(running)、“阻塞”(blocked)、“挂起”(suspend)和“终止”(terminated)等状态。各种状态的切换过程如下:
当其被从存储介质中加载到内存中,进程的状态为“被创建”。
被创建后,进程调度器会自动将进程的状态设置为“就绪”。此时,进程等待调度器做上下文切换。处理器空闲时,器将进程加载到处理器中,然后进程的状态变成“运行”,处理器开始执行该进程的指令。
如果进程需要等待某个资源(比如用户输入、打开文件、执行打印操作等),它将会被标记为“阻塞”状态。当进程获得了等待的资源后,它的状态又会变回“就绪”。
当内存中的所有进程都处于“阻塞”状态时,Windows会将其中一个进程设置为“挂起”状态,并将其在内存中的数据保存到磁盘中。这样可以释放内存空间给其他进程。Windows也会把导致系统不稳定的进程挂起。
一旦进程执行完成或者被操作系统终止,它就会被从内存中移除或者被设置为“被终止”状态。

9.2 进程编程

9.2.1 创建进程

1.subprocess.call()函数

  1. trtcode = subprocess.call(可执行程序) #trtcode返回可执行程序的退出信息。

2.subprocess.Popen()函数

  1. 进程对象 = subprocess.Popen(args, bufsize=0, executable=None, stdin=None, stdout=None, stderr=None, preexec_fn=None, close_fds=False, shell=False, cwd=None, env=None, universal_newlines=False, startupinfo=None, creationflags=0)
  2. '''args:可以是字符串或者序列类型(例如列表和元组),用于指定进程的可执行文件及其参数。
  3. bufsize:指定缓冲区的大小。
  4. executable:用于指定可执行程序。一般通过args参数来设置所要运行的程序。如果将参数shell设为 True,则executable用于指定程序使用的shell。在windows平台下,默认的shell由COMSPEC环境变量来指定,即命令窗口。
  5. stdin:指定程序的标准输入,默认是键盘。
  6. stdout:指定程序的标准输出,默认是屏幕。
  7. stderr:指定程序的标准错误输出,默认是屏幕。
  8. preexec_fn:只在Unix平台下有效,用于指定一个可执行对象,它将在子进程运行之前被调用。
  9. close_fds:在windows平台下,如果close_fds被设置为True,则新创建的子进程将不会继承父进程的输入、输出和错误管道。
  10. shell:如果shell被设为true,程序将通过shell来执行。
  11. cwd:指定进程的当前目录。
  12. env:指定进程的环境变量。
  13. universal_newlines:指定是否使用统一的文本换行符。在不同操作系统下,文本的换行符是不一样的。例如,在windows下用'/r/n '表示换行,而Linux下用' /n '。如果将此参数设置为True,Python统一把这些换行符当作' /n '来处理。
  14. startupinfo和creationflags:只在windows下用效,它们将被传递给底层的CreateProcess()函数,用于设置进程的一些属性,例如主窗口的外观和进程的优先级等。
  15. '''

3.CreateProcess函数

  1. CreateProcess(appName, commandLine , processAttributes ,threadAttributes , bInheritHandles ,dwCreationFlags , newEnvironment , currentDirectory , startupinfo)
  2. '''
  3. appName,要执行的应用程序名,可以包括结对路径和文件名,通常可以为NULL。
  4. commandLine,要执行的命令行。
  5. processAttributes,新进程的安全属性,如果为None,则为默认的安全属性。
  6. ThreadAttributes,线程安全属性,如果为None,则为默认的安全属性。
  7. bInheritHandles,继承属性,如果为None,则为默认的继承属性。
  8. dwCreationFlags,指定附加的、用来控制优先类和进程创建的标志。其取值见表9-1。这些属性值都在win32process模块中定义,例如,使用win32process.CREATE_NO_WINDOW可以指定新建进程是一个没有窗口的控制台应用程序。
  9. newEnvironment,指向新进程的环境块。如果为NULL,则使用调用CreateProcess()函数的进程的环境。
  10. currentDirectory,进程的当前目录。
  11. '''

dwCreationFlags参数的取值

取 值 说 明
CREATE_BREAKAWAY_FROM_JOB 如果进程与一个作业相关联,则其子进程与该作业无关
CREATE_DEFAULT_ERROR_MODE 新进程不继承调用CreateProcess()函数的进程的错误模式,而是使用缺省的错误模式
CREATE_FORCE_DOS 以MS-DOS模式运行应用程序
CREATE_NEW_CONSOLE 新进程打开一个新的控制台窗口,而不是使用调用进程的控制台窗口
CREATE_NEW_PROCESS_GROUP 新进程是一个新进程组的根进程。新进程组中包含新建进程的所有后代进程
CREATE_NO_WINDOW 新建进程是一个没有窗口的控制台应用程序,因此,它的控制台句柄没有被设置
CREATE_SEPARATE_WOW_VDM 只用于16位Windows应用程序。如果设置,则新进程在一个私有虚拟DOS机(VDM,Virtual DOS Machine)中运行
CREATE_SHARED_WOW_VDM 只用于16位Windows应用程序。如果设置,则新进程在一个共享虚拟DOS机中运行
CREATE_SUSPENDED 创建一个处于挂起状态的进程
CREATE_UNICODE_ENVIRONMENT 如果设置了此选项,则参数newEnvironment使用Unicode字符串
DEBUG_PROCESS 启动并调试新进程及所有其创建的子进程
DEBUG_ONLY_THIS_PROCESS
DETACHED_PROCESS 对于控制台程序,新进程不继承父控制台
ABOVE_NORMAL_PRIORITY_CLASS 指定新建进程的优先级比NORMAL_PRIORITY_CLASS高,但是比HIGH_PRIORITY_CLASS低
BELOW_NORMAL_PRIORITY_CLASS 指定新建进程的优先级比IDLE_PRIORITY_CLASS高,但是比NORMAL_PRIORITY_CLASS低
HIGH_PRIORITY_CLASS 指定新建高优先级的进程
IDLE_PRIORITY_CLASS 指定只有系统空闲时才运行新建级的进程
NORMAL_PRIORITY_CLASS 创建一个普通进程
REALTIME_PRIORITY_CLASS 指定新建最高优先级的进程

9.2.2 枚举系统进程

1.CreateToolhelp32Snapshot()函数
调用Windows API CreateToolhelp32Snapshot()可以获取当前系统运行进程的快照(snapshot),也就是运行进程的列表,其中包含进程标示符及其对应的可执行文件等信息,函数原型如下:

  1. HANDLE WINAPI CreateToolhelp32Snapshot(
  2. DWORD dwFlags, //指定快照中包含的对象
  3. DWORD th32ProcessID // 指定获取进程快照的PID。如果为0,则获取当前系统进程列表
  4. );

如果函数执行成功,则返回进程快照的句柄;否则返回INVALID_HANDLE_VALUE
参数dwFlags的取值

取 值 说 明
TH32CS_SNAPALL(15,0x0000000F) 相当于指定了TH32CS_SNAPHEAPLIST, TH32CS_SNAPMODULE, TH32CS_SNAPPROCESS, 和 TH32CS_SNAPTHREAD
TH32CS_SNAPHEAPLIST(1,0x00000001) 快照中包含指定进程的堆列表
TH32CS_SNAPMODULE(8,0x00000008) 快照中包含指定进程的模块列表
TH32CS_SNAPPROCESS(2,0x00000002) 快照中包含进程列表
TH32CS_SNAPTHREAD(4,0x00000004) 快照中包含线程列表

2.Process32First()函数
调用Process32First()函数可以从进程快照中获取第1个进程的信息,函数原型如下:

  1. BOOL WINAPI Process32First(
  2. HANDLE hSnapshot, // 之前调用CreateToolhelp32Snapshot()函数得到的进程快照句柄
  3. LPPROCESSENTRY32 lppe // 包含进程信息的结构体
  4. );

如果函数执行成功,则返回TRUE;否则返回FALSE。
结构体LPPROCESSENTRY32定义如下:

  1. typedef struct tagPROCESSENTRY32{
  2. DWORD dwSize; // 结构体的长度,单位是字节
  3. DWORD cntUsage; // 引用进程的数量,必须为1
  4. DWORD th32ProcessID; // 进程标示符(PID
  5. DWORD th32DefaultHeapID; // 进程的缺省堆标识符
  6. DWORD th32ModuleID; // 进程的模块标识符
  7. DWORD cntThreads; // 进程中运行的线程数量
  8. DWORD th32ParentProcessID; // 创建进程的父进程的标识符
  9. LONG pcPriClassBase; // 进程创建的线程的优先级
  10. DWORD dwFlags; // 未使用
  11. TCHAR szExeFile[MAX_PATH]; // 进程对应的可执行文件名
  12. DWORD th32MemoryBase; // 可执行文件的加载地址
  13. DWORD th32AccessKey; // 位数组,每一位指定进程对地址的查看权限
  14. } PROCESSENTRY32;

结构体tagPROCESSENTRY32定义如下:

  1. class tagPROCESSENTRY32(Structure):
  2. _fields_ = [('dwSize', DWORD),
  3. ('cntUsage', DWORD),
  4. ('th32ProcessID', DWORD),
  5. ('th32DefaultHeapID', POINTER(ULONG)),
  6. ('th32ModuleID', DWORD),
  7. ('cntThreads', DWORD),
  8. ('th32ParentProcessID', DWORD),
  9. ('pcPriClassBase', LONG),
  10. ('dwFlags', DWORD),
  11. ('szExeFile', c_char * 260)]

3.Process32Next()函数
调用Process32Next()函数可以从进程快照中获取下一个进程的信息,函数原型如下:

  1. BOOL WINAPI Process32Next(
  2. HANDLE hSnapshot, // 之前调用createtoolhelp32napshot()函数得到的进程快照句柄
  3. LPPROCESSENTRY32 lppe // 包含进程信息的结构体
  4. );

如果函数执行成功,则返回TRUE;否则返回FALSE。
例子:

  1. from ctypes.wintypes import *
  2. from ctypes import *
  3. kernel32 = windll.kernel32
  4. # 定义进程信息结构体
  5. class tagPROCESSENTRY32(Structure):
  6. _fields_ = [('dwSize', DWORD),
  7. ('cntUsage', DWORD),
  8. ('th32ProcessID', DWORD),
  9. ('th32DefaultHeapID', POINTER(ULONG)),
  10. ('th32ModuleID', DWORD),
  11. ('cntThreads', DWORD),
  12. ('th32ParentProcessID', DWORD),
  13. ('pcPriClassBase', LONG),
  14. ('dwFlags', DWORD),
  15. ('szExeFile', c_char * 260)]
  16. # 获取当前系统运行进程的快照
  17. hSnapshot = kernel32.CreateToolhelp32Snapshot(15, 0)
  18. fProcessEntry32 = tagPROCESSENTRY32()
  19. # 初始化进程信息结构体的大小
  20. fProcessEntry32.dwSize = sizeof(fProcessEntry32)
  21. # 获取第一个进程信息
  22. listloop = kernel32.Process32First(hSnapshot, byref(fProcessEntry32))
  23. while listloop: # 如果获取进程信息成功,则继续
  24. processName = (fProcessEntry32.szExeFile)
  25. processID = fProcessEntry32.th32ProcessID
  26. print("%d:%s" %(processID,processName))
  27. # 获取下一个进程信息
  28. listloop = kernel32.Process32Next(hSnapshot, byref(fProcessEntry32))

4.CreateProcess函数

  1. CreateProcess(appName, commandLine , processAttributes ,
  2. threadAttributes , bInheritHandles ,
  3. dwCreationFlags , newEnvironment , currentDirectory , startupinfo)

参数说明

dwCreationFlags参数的取值

取 值 说 明
CREATE_BREAKAWAY_FROM_JOB 如果进程与一个作业相关联,则其子进程与该作业无关
CREATE_DEFAULT_ERROR_MODE 新进程不继承调用CreateProcess()函数的进程的错误模式,而是使用缺省的错误模式
CREATE_FORCE_DOS、 以MS-DOS模式运行应用程序
CREATE_NEW_CONSOLE 新进程打开一个新的控制台窗口,而不是使用调用进程的控制台窗口
CREATE_NEW_PROCESS_GROUP 新进程是一个新进程组的根进程。新进程组中包含新建进程的所有后代进程
CREATE_NO_WINDOW 新建进程是一个没有窗口的控制台应用程序,因此,它的控制台句柄没有被设置
CREATE_SEPARATE_WOW_VDM 只用于16位Windows应用程序。如果设置,则新进程在一个私有虚拟DOS机(VDM,Virtual DOS Machine)中运行
CREATE_SHARED_WOW_VDM 只用于16位Windows应用程序。如果设置,则新进程在一个共享虚拟DOS机中运行
CREATE_SUSPENDED 创建一个处于挂起状态的进程
CREATE_UNICODE_ENVIRONMENT 如果设置了此选项,则参数newEnvironment使用Unicode字符串
DEBUG_PROCESS 启动并调试新进程及所有其创建的子进程
DEBUG_ONLY_THIS_PROCESS 启动并调试新进程。可以调用WaitForDebugEvent()函数接收调试事件
DETACHED_PROCESS、 对于控制台程序,新进程不继承父控制台
ABOVE_NORMAL_PRIORITY_CLASS 指定新建进程的优先级比NORMAL_PRIORITY_CLASS高,但是比HIGH_PRIORITY_CLASS低
BELOW_NORMAL_PRIORITY_CLASS 指定新建进程的优先级比IDLE_PRIORITY_CLASS高,但是比NORMAL_PRIORITY_CLASS低
HIGH_PRIORITY_CLASS 指定新建高优先级的进程
IDLE_PRIORITY_CLASS 指定只有系统空闲时才运行新建级的进程
NORMAL_PRIORITY_CLASS 创建一个普通进程
REALTIME_PRIORITY_CLASS 指定新建最高优先级的进程

9.2.3 终止进程

TASKKILL命令的语法

  1. TASKKILL [/S system [/U username [/P [password]]]]
  2. { [/FI filter] [/PID processid | /IM imagename] } [/T] [/F]

参数说明

  1. import os
  2. os.system('taskkill /F /IM notepad.exe')

9.2.4 进程池

multiprocessing包是Python中的多进程管理包。使用它可以创建和管理进程池。

  1. from multiprocessing import Pool
  2. 创建一个进程池
  3. 进程池对象 = Pool(processes=n)
  4. n表示进程池中可以包含的最大进程数。
  1. apply_async()函数
    apply_async()函数用于在一个进程池的工作进程中异步地执行函数,并返回结果。函数原型如下:
    multiprocessing.Pool.apply_async(func[, args[, kwargs[, callback]]])
    参数说明如下:

    • func,异步地执行的函数名。
    • args和kwargs,func()函数的参数。
    • callback,可调用对象,接受输入参数。当func的结果变为可用时, 将立即传递给callback。
      假定apply_async()函数的返回结果是result,则可以通过调用result.successful()函数获取整个调用执行的状态。如果执行成功,则返回True;如果还有工作进程没执行完,则会抛出AssertionError异常。
  2. 关闭进程池
    使用进程池完成后,需要关闭进程池。可以使用close()函数或terminate()函数关闭,close()和terminate()的区别在于close()函数会等待池中的工作进程执行结束再关闭进程池,而terminate()函数则是直接关闭。

  3. join()函数
    调用join()函数可以等待进程池中的工作进程执行完毕,以防止主进程在工作进程结束前结束。但join()函数必须在关闭进程池之后使用。

  1. from multiprocessing import Pool
  2. from time import sleep
  3. import subprocess
  4. def f(x):
  5. retcode = subprocess.call("notepad.exe")
  6. sleep(1)
  7. def main():
  8. pool = Pool(processes=3) # 最多工作进程数为 3
  9. for i in range(1,10):
  10. result = pool.apply_async(f, (i,))
  11. pool.close()
  12. pool.join()
  13. if result.successful():
  14. print('successful')
  15. if __name__ == "__main__":
  16. main();
  17. #如果只运行当前模块则运行main函数,否则不运行。

9.3 多线程编程

9.3.1 线程的概念

线程是操作系统可以调度的最小执行单位,通常是将程序拆分成2个或多个并发运行的任务。一个线程就是一段顺序程序。但是线程不能独立运行,只能在程序中运行。
不同的操作系统实现进程和线程的方法也不同,但大多数是在进程中包含线程,Windows就是这样。一个进程中可以存在多个线程,线程可以共享进程的资源(比如内存)。而不同的进程之间则是不能共享资源的。
线程的状态

9.3.2 threading模块

可以引用threading模块来管理线程

  1. 创建和运行线程
    线程对象 = threading.Thread(target=线程函数,args=(参数列表), name=线程名, group=线程组)
    创建线程后,通常需要调用线程对象的setDaemon()方法将线程设置为守护线程。主线程执行完后, 如果还有其他非守护线程,则主线程不会退出,会被无限挂起。
    线程对象.setDaemon(是否设置为守护线程)
    setDaemon()函数必须在运行线程之前被调用。调用线程对象的start()方法可以运行线程。
  1. import threading
  2. def f(i):
  3. print(" I am from a thread, num = %d \n" %(i))
  4. def main():
  5. for i in range(1,10):
  6. t = threading.Thread(target=f,args=(i,))
  7. t.setDaemon(True)
  8. t.start();
  9. if __name__ == "__main__":
  10. main();

虽然线程的启动和创建是有顺序的,但是线程是并发运行的。
2. 阻塞进程
调用线程对象的join()方法可以阻塞进程直到线程执行完毕。函数如下:join(timeout=None)
参数timeout指定超时时间(单位为秒),超过指定时间join就不在阻塞进程了。

  1. import threading
  2. def f(i):
  3. print(" I am from a thread, num = %d \n" %(i))
  4. def main():
  5. for i in range(1,10):
  6. t = threading.Thread(target=f,args=(i,))
  7. t.setDaemon(True)
  8. t.start();
  9. t.join();
  10. if __name__ == "__main__":
  11. main();

可以看到进程在所有线程结束之后才退出。
3. 指令锁
当多个线程同时访问同一资源(比如全局变量),则可能会出现访问冲突。可以使用锁来限制线程同时访问同一资源。

  1. import threading
  2. import time
  3. lock = threading.Lock() # 创建一个指令锁
  4. num =0;
  5. def f():
  6. global num
  7. if lock.acquire():
  8. print('%s 获得指令锁.' %(threading.currentThread().getName()))
  9. b = num
  10. time.sleep(0.0001)
  11. num=b+1
  12. lock.release()# 释放指令锁
  13. print('%s 释放指令锁.' %(threading.currentThread().getName()))
  14. def main():
  15. for i in range(1,20):
  16. t = threading.Thread(target=f)
  17. t.setDaemon(True)
  18. t.start();
  19. t.join()
  20. print(num)
  21. if __name__ == "__main__":
  22. main();
  1. 可重入锁
    使用指令锁可以避免多个线程同时访问全局变量。但是如果一个线程里面有递归函数,则它可能会多次请求访问全局变量,此时,即使线程已经获得指令锁,在它再次申请指令锁时也会被阻塞。
    此时可以使用可重入锁(RLock)。每个可重入锁都关联一个请求计数器和一个占有它的线程,当请求计数器为0时,这个锁可以被一个线程请求得到并把锁的请求计数加1。如果同一个线程再次请求这个锁时,请求计数器就会增加,当该线程释放RLock时,其计数器减1,当计数器为0时,锁被释放。
    可以使用threading.RLock()方法创建一个个可重入锁,例如:
  1. lock = threading.RLock()

使用acquire()方法可以申请可重入锁,使用release()方法可以释放可重入锁。具体用法与指令锁相似。

  1. import threading
  2. import time
  3. lock = threading.RLock() # 创建一个可重入锁锁
  4. num =0;
  5. def f():
  6. global num
  7. # 第一次请求锁定
  8. if lock.acquire():
  9. print('%s 获得可重入锁.\n' %(threading.currentThread().getName()))
  10. time.sleep(0.0001)
  11. # 第2次请求锁定
  12. if lock.acquire():
  13. print('%s 获得可重入锁.\n' %(threading.currentThread().getName()))
  14. time.sleep(0.0001)
  15. lock.release()# 释放指令锁
  16. print('%s 释放指令锁.\n' %(threading.currentThread().getName()))
  17. time.sleep(0.0001)
  18. print('%s 释放指令锁.\n' %(threading.currentThread().getName()))
  19. lock.release()# 释放指令锁
  20. def main():
  21. for i in range(1,20):
  22. t = threading.Thread(target=f)
  23. t.setDaemon(True)
  24. t.start();
  25. t.join()
  26. print(num)
  27. if __name__ == "__main__":
  28. main();
  1. 信号量
    信号量可以用来保证两个或多个关键代码不被并发使用。通过使用信号量设置“访客上限”
    创建信号量对象的方法如下:
    信号量对象 = threading.Semaphore(计数器初值)
    例如,使用下面的语句可以创建一个计数器初值为2的信号量对象s。
  1. s = threading.Semaphore(2)
  1. import threading
  2. import time
  3. s = threading. Semaphore(2) # 创建一个计数器初值为2的信号量对象s
  4. num =0;
  5. def f():
  6. global num
  7. # 第一次请求锁定
  8. if s.acquire():
  9. print('%s 获得信号量.\n' %(threading.currentThread().getName()))
  10. time.sleep(0.0001)
  11. print('%s 释放信号量.\n' %(threading.currentThread().getName()))
  12. s.release()# 释放指令锁
  13. def main():
  14. for i in range(1,20):
  15. t = threading.Thread(target=f)
  16. t.setDaemon(True)
  17. t.start();
  18. t.join()
  19. if __name__ == "__main__":
  20. main();

6.事件
事件是线程通信的一种机制,一个线程通知事件,其他线程等待事件。事件对象内置一个标记(初始值为False),在线程中根据事件对象的标记决定继续运行或阻塞。事件对象中与内置标记有关的方法如下。

函数 说明
set() 将内置标记设置为True
clear() 将内置标记设置为False
wait() 阻塞线程至事件对象的内置标记被设置为True
  1. import threading
  2. import time
  3. e = threading.Event() # 创建一个事件对象s
  4. def f1():
  5. print('%s start.\n' %(threading.currentThread().getName()))
  6. time.sleep(5)
  7. print('触发事件.\n')
  8. e.set()
  9. def f2():
  10. e.wait();
  11. print('%s start.\n' %(threading.currentThread().getName()))
  12. def main():
  13. t1 = threading.Thread(target=f1)
  14. t1.setDaemon(True)
  15. t1.start();
  16. t2 = threading.Thread(target=f2)
  17. t2.setDaemon(True)
  18. t2.start();
  19. if __name__ == "__main__":
  20. main();

线程1运行5秒后触发事件e,随后线程2继续运行。
7.定时器
定时器(Timer)是Thread的派生类,用于在指定时间后调用一个函数

  1. timer = threading.Timer(指定时间t, 函数f)
  2. timer.start()

执行timer.start()后,程序会在指定时间t后启动线程执行函数f。

  1. import threading
  2. import time
  3. def func():
  4. print(time.ctime())
  5. print(time.ctime())
  6. timer = threading.Timer(1, func)
  7. timer.start() 

第10章 网络编程

10.1 网络通信模型和TCP/IP协议簇

10.1.1 OSI参考模型

OSI参考模型的通信过程

PDU在OSI参考模型中的特定名称

OSI参考模型中的层次 PDU的特定名称
传输层 数据段(Segment)
网络层 数据包(Packet)
数据链路层 数据帧(Frame)
物理层 比特(Bit)

10.1.2 TCP/IP

互联网协议族是一种计算机网络模型已经运行在互联网和类似网络上的通信协议的结合,它一般被称为TCP/IP。IP负责把数据分割成IP包,从一台计算机通过网络发送到另一台计算机。TCP建立在IP之上,负责两台计算机之间建立可靠连接,保证数据包顺利发送和接收。TCP通过握手建立连接之后,对每个IP包进行编号发送,如果IP包发生丢掉情况,就自动重发,保证数据的可靠安全性。

图片

  1. 网络接口层(网络接入层)
    在TCP/IP参考模型中,网络接口层位于最低层。它负责通过网络发送和接收IP数据包。与OSI模型的物理层和数据链路层相对应,负责监视数据在主机和网络之间的交换。
  2. 网络层
    负责相邻计算机之间的通信
    网络层4个核心协议

    • IP是网络层的核心,通过路由选择将下一条IP封装后交给接口层。IP数据报是无连接服务。
    • ICMP是网络层的补充,可以回送报文。用来检测网络是否通畅。
    • ARP(Address Resolution Protocol,地址解析协议):可以通过IP地址得知其物理地址(Mac地址)的协议。在TCP/IP网络环境下,每个主机都分配了一个32位的IP地址,这种互联网地址是在网际范围标识主机的一种逻辑地址。为了让报文在物理网络上传送,必须知道对方目的主机的物理地址。这样就存在把IP地址变换成物理地址的地址转换问题。
    • RARP(Reverse Address Resolution Protocol,逆向地址解析协议):该协议用于完成物理地址向IP地址的转换。
  3. 传输层
    它负责在应用程序之间实现端到端的通信。保证数据包的顺序传送及数据的完整性。传输层中定义了下面两种协议。

    • TCP:是一种可靠的面向连接的协议,它允许将一台主机的字节流无差错地传送到目的主机。TCP协议同时要完成流量控制功能,协调收发双方的发送与接收速度,达到正确传输的目的。
    • UDP:是一种不可靠的无连接协议。与TCP相比,UDP更加简单,数据传输速率也较高。当通信网的可靠性较高时,UDP方式具有更高的优越性。
  4. 应用层
    在TCP/IP参考模型中,应用层位于最高层,其中包括了所有与网络相关的高层协议。常用的应用层协议说明如下。

    • Telnet(Teletype Network,网络终端协议):用于实现网络中的远程登录功能。
    • FTP(File Transfer Protocol,文件传输协议):用于实现网络中的交互式文件传输功能。
    • SMTP(Simple Mail Transfer Protocol,简单邮件传输协议):用于实现网络中的电子邮件传送功能。
    • DNS(Domain Name System,域名系统):用于实现网络设备名称到IP地址的映射。
      SNMP(Simple Network Management Protocol,简单网络管理协议):用于管理与监视网络设备。
    • RIP(Routing Information Protocol,路由信息协议):用于在网络设备之间交换路由信息。
    • NFS(Network File System,网络文件系统):用于网络中不同主机之间的文件共享。
      HTTP(Hyper Text Transfer Protocol,超文本传输协议):这是互联网上应用最为广泛的一种网络协议。所有的WWW文件都必须遵守这个标准。设计HTTP的最初目的是为了提供一种发布和接收HTML页面的方法。

IP地址
IPV4地址是一个32位的2进制数,通常分为4个8位2进制数,通常用点分十进制表示成a.b.c.d。其中123开头的IP地址为本机回送地址,用于测试网络与本地的通信。
端口号
同一台计算机可以运行多个网络程序,每个网络程序有唯一的端口号,端口号的作用就是区分不同的网络应用程序。

10.2 Socket编程

10.2.1 Socket的工作原理和基本概念

基于socket编程需要知道目标计算机的IP地址、端口号以及协议类型。按协议类型的不同分为TCP连接和UDP连接。用于描述IP地址和端口。

10.2.2 基于TCP的Socket编程

1.socket()函数
socket()函数用于创建与指定的服务提供者绑定套接字

  1. socket=socket.socket(familly,type)

参数说明如下:

+ familly,指定协议的地址家族,可为AF_INET或AF_UNIX。AF_INET家族包括Internet地址,AF_UNIX家族用于同一台机器上的进程间通信。
type,指定套接字的类型。
套接字类型的取值
套接字类型 说 明
+ SOCK_STREAM 提供顺序、可靠、双向和面向连接的字节流数据传输机制,使用TCP
+ SOCK_DGRAM 支持无连接的数据报,使用UDP
+ SOCK_RAW 原始套接字,可以用于接收本机网卡上的数据帧或者数据包
2.bind()函数
bind()函数可以将本地地址与一个Socket绑定在一起,函数原型如下:socket.bind( address )
参数address是一个双元素元组,格式是(host,port)。host代表主机,port代表端口号。
3.listen()函数
listen()函数可以将套接字设置为监听接入连接的状态,函数原型如下:listen(backlog);
参数backlog指定等待连接队列的最大长度。
4.accept()函数
在服务器端调用listen()函数监听接入连接后,可以调用accept()函数来等待接受连接请求。accept()的函数原型如下:
connection, address = socket.accept()
调用accept()方法后,socket会进入waiting状态。客户请求连接时,accept()方法会建立连接并返回服务器。accept()方法返回一个含有两个元素的元组(connection,address)。第一个元素connection是新的socket对象,服务器必须通过它与客户通信;第二个元素 address是客户的Internet地址。
5.recv()函数
调用recv()函数可以从已连接的Socket中接收数据。recv()的函数原型如下:
buf = sock.recv(size)
参数sock是接收数据的socket对象,参数size指定接收数据的缓冲区的大小。recv()的函数的返回接收的数据。
6.send()函数
调用send()函数可以在已连接的Socket上发送数据。send()的函数原型如下:
sock.recv(buf)
7.close ()函数
sever.py
参数s表示要关闭的Socket。
if name == 'main':
import socket
#创建socket对象
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

绑定到本地的8001端口

sock.bind(('localhost', 8001))
# 在本地的8001端口上监听,等待连接队列的最大长度为5
sock.listen(5)  
while True:

接受来自客户端的连接

    connection,address = sock.accept()  
    try:  
        connection.settimeout(5)  
        buf = connection.recv(1024).decode('utf-8')  #接收客户端的数据
        if buf == '1':  # 如果接收到'1'
            connection.send(b'welcome to server!')  
        else:  
            connection.send(b'please go out!')  
    except socket.timeout:  
        print('time out')
    connection.close()  

client.py
if name == 'main':
import socket
# 创建socket对象
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

连接到本地的8001端口

sock.connect(('localhost', 8001))  
import time  
time.sleep(2)
# 向服务器发送字符'1'
sock.send(b'1')
#打印从服务器接收的数据
print(sock.recv(1024).decode('utf-8'))
sock.close()  

10.2.3基于UDP的Socket编程
客户端连接:创建socket对象-sendto方法传输数据-传输结束close方法关闭连接
服务器连接:创建socket对象-socket绑定到指定地址-recvform方法传输数据-传输结束close方法关闭连接
sendto()函数
使用sendto()函数可以实现发送数据的功能,函数原型如下;
s.sendto(data,(addr,port))
参数说明如下:
s,指定一个Socket句柄。
data,要传输数据。
addr,接收数据的计算机的IP地址。
port,接收数据的计算机的端口。
import socket

创建UDP SOCKET

s = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
port = 8000 #服务器端口
host = '192.168.0.101'#服务器地址
while True:
msg = input()# 接受用户输入
if not msg:
break
# 发送数据
s.sendto(msg.encode(),(host,port))
s.close()
2.recvfrom()函数
使用recvfrom ()函数可以实现接收数据的功能,函数原型如下;
data,addr = s.recvfrom( bufsize);
参数说明如下:
s,指定一个Socket句柄。
bufsize,接收数据的缓冲区的长度,单位为字节。
data,接收数据的缓冲区。
addr,发送数据的客户端的地址。

import socket
s = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
s.bind(('192.168.0.101',8000))
while True:
data,addr = s.recvfrom(1024)
if not data:
print('client has exited!')
break
print('received:',data,'from',addr)
s.close()
10.3电子邮件编程
10.3.1SMTP编程
SMTP(Simple Mail Transfer Protocol,简单邮件传输协议)是一组用于由源地址到目的地址传送邮件的规则,可以控制信件的中转方式。SMTP属于TCP/IP协议簇,通过SMTP所指定的服务器,就可以把E-mail寄到收信人的服务器上了。
要求提供如下信息:
SMTP服务器,不同的邮件提供商都有自己的SMTP服务器。例如新浪的SMTP服务器为smtp.sina.com。
发件人E-mail账号。
收件人E-mail账号。
发件人用户名(通常与E-mail账号是对应的。例如,如果发件人E-mail账号为myemail@sina.com,则发件人用户名myemail)。
发件人E-mail密码。
import smtplib实现SMTP编程
步骤:
连接到 SMTP服务器
在发送E-mail之前首先需要连接到 SMTP服务器,方法如下:
s = smtplib.SMTP(server)
server是要连接的 SMTP服务器。返回值s是SMTP服务器对象,以后就可以通过s与SMTP服务器交互了。
执行EHLO命令
在发送E-mail时,客户应该以EHLO命令开始SMTP会话。如果命令成功,则服务器返回代码250(通常在200到299之间都是正确的返回值)。
执行EHLO命令的方法如下:
s.ehlo()
s是SMTP服务器对象。ehlo()方法返回一个元组,其内容为SMTP服务器的响应。元组的第1个元素是服务器返回的代码。
import smtplib
s = smtplib.SMTP("smtp.sina.com") #连接到服务器
msg = s.ehlo()
code = msg[0] #返回服务器的特性
print(msg)
print("SMTP的返回代码为 %d" %(code))
判断SMTP服务器是否支持指定属性
SMTP服务器对象.has_extn(属性名)
常用的属性如下:
size,获得服务器允许发送邮件的大小。
starttls,获得服务器是否支持TLS。
auth,获得服务器是否支持认证。
import smtplib
s = smtplib.SMTP("smtp.sina.com") #连接到服务器
print("服务器允许发送邮件的大小: %s" %(s.has_extn('size')))
print("服务器是否支持TLS: %s" %(s.has_extn('starttls')))
print("服务器是否支持认证: %s" %(s.has_extn('auth')))
发送邮件
调用sendmail()方法可以发送邮件,方法如下:
SMTP服务器对象.sendmail(发件人地址, 收件人地址, 邮件内容)
import sys
import smtplib
import socket
from getpass import getpass

参数格式不对

if len(sys.argv) < 4:
print("[*]usage:%s server fromaddr toaddr " % sys.argv[0])
sys.exit(1)

server = sys.argv1 #第1个参数是SMTP服务器
fromaddr = sys.argv[2]#第2个参数是发件人地址
toaddr = sys.argv[3]#第3个参数是收件人地址

#邮件内容
message = """
TO: %s
From: %s
Subject: Test Message from SMTP_mail.py

Hello ,This a simple SMTP_mail example.
""" % (toaddr,fromaddr)

定义auth_login()函数,用于登录邮件服务器,并发送邮件

def auth_login():
"""当发送邮件时,服务器需要验证,则输入用户名密码方可发送邮件"""

print("输入用户名: ")
username = input()
password = getpass("输入密码: ")
try:
    s = smtplib.SMTP(server)     #连接到服务器

    code = s.ehlo()[0]      #返回服务器的特性
    usesesmtp = 1
    if not (200 <= code <=299):         #在200到299之间都是正确的返回值
        usesesntp = 0
        code = s.helo()[0]
        if not (200 <= code <=299):
            raise SMTPHeloError(code,resp)

    try:
        s.login(username,password)  #登录服务器
    except smtplib.SMTPException as e:
        print("认证失败:" , e)
        sys.exit(1)
    s.sendmail(fromaddr,toaddr,message)         #如果支持认证则输入用户名密码进行认证;不支持则使用普通形式进行传输
except(socket.gaierror,socket.error,socket.herror,smtplib.SMTPException) as e:

    print(e)
    sys.exit(1)
else:
    print("***邮件成功发送**")

if name == "main":
auth_login()
10.3.2POP编程
需要提供如下信息:
POP服务器,不同的邮件提供商都有自己的POP服务器。例如新浪的POP服务器为smtp.sina.com。
收件人E-mail账号。
收件人E-mail密码。
from poplib import POP3
连接到 POP3服务器
s = smtplib.POP3(server)
执行USER命令
p. user(username)
p是POP3服务器对象。参数username指定要发送的用户名。
执行PASS命令
SMTP服务器对象.has_extn(属性名)
常用的属性如下:
size,获得服务器允许发送邮件的大小。
starttls,获得服务器是否支持TLS。
auth,获得服务器是否支持认证。

import smtplib
s = smtplib.SMTP("smtp.sina.com") #连接到服务器
print("服务器允许发送邮件的大小: %s" %(s.has_extn('size')))
print("服务器是否支持TLS: %s" %(s.has_extn('starttls')))
print("服务器是否支持认证: %s" %(s.has_extn('auth')))
发送邮件
SMTP服务器对象.sendmail(发件人地址, 收件人地址, 邮件内容)
import sys
import smtplib
import socket
from getpass import getpass

参数格式不对

if len(sys.argv) < 4:
print("[*]usage:%s server fromaddr toaddr " % sys.argv[0])
sys.exit(1)

server = sys.argv1 #第1个参数是SMTP服务器
fromaddr = sys.argv[2]#第2个参数是发件人地址
toaddr = sys.argv[3]#第3个参数是收件人地址

#邮件内容
message = """
TO: %s
From: %s
Subject: Test Message from SMTP_mail.py

Hello ,This a simple SMTP_mail example.
""" % (toaddr,fromaddr)

定义auth_login()函数,用于登录邮件服务器,并发送邮件

def auth_login():
"""当发送邮件时,服务器需要验证,则输入用户名密码方可发送邮件"""

print("输入用户名: ")
username = input()
password = getpass("输入密码: ")
try:
    s = smtplib.SMTP(server)     #连接到服务器

    code = s.ehlo()[0]      #返回服务器的特性
    usesesmtp = 1
    if not (200 <= code <=299):         #在200到299之间都是正确的返回值
        usesesntp = 0
        code = s.helo()[0]
        if not (200 <= code <=299):
            raise SMTPHeloError(code,resp)

    try:
        s.login(username,password)  #登录服务器
    except smtplib.SMTPException as e:
        print("认证失败:" , e)
        sys.exit(1)
    s.sendmail(fromaddr,toaddr,message)         #如果支持认证则输入用户名密码进行认证;不支持则使用普通形式进行传输
except(socket.gaierror,socket.error,socket.herror,smtplib.SMTPException) as e:

    print(e)
    sys.exit(1)
else:
    print("***邮件成功发送**")

if name == "main":
auth_login()
python35 例10-7.py smtp.163.com wyx18862142062@163.com wyx18862142062@163.com

第11章Python数据库编程
11.1数据库技术基础
11.1.1数据库的基本概念
数据库(DataBase,DB),简单地讲就是存放数据的仓库。不过,数据库不是数据的简单堆积,而是以一定的方式保存在计算机存储设备上的相互关联的数据的集合。也就是说,数据库中的数据并不是相互孤立的,数据和数据之间是有关联的。
11.1.2关系数据库
11.2SQLite数据库
11.2.1下载和安装SQLite数据库
http://www.sqlite.org/download.html
11.2.2创建SQLite数据库
可以在运行SQLite数据库的同时通过参数创建SQLite 数据库,具体方法如下:
sqlite3 数据库文件名
qlite3 test.db
SQLite 数据库文件的扩展名为.db。如果指定的数据库文件存在,则打开该数据库;否则创建该数据库。
保存数据库save test.db
11.2.3数据类型
数据类型 说明
NULL 空值
integer 带符号的整型
real 实数
text 字符串文本
blob 二进制对象
smallint 16 位整数
decimal(p,s) 小数。p指数字的位数,s指小数点后有几位数。
float 32位浮点数字
double 64位实数
char(n) 固定长度的字符串,n为字符串的长度,不能超过 254
varchar(n) 不固定长度的字符串,n为字符串的最大长度,不能超过 4000
graphic(n) 和char(n)一样,不过其单位是两个字节double-bytes, n不能超过127。graphic支持两个字节长度的字体,例如汉字
vargraphic(n) 长度不固定且最大长度为 n 的双字节字符串,n不能超过 4000
date 日期,包含年、月、日
time 时间包含小时、分钟、秒
timestamp 时间戳,包含年、月、日、时、分、秒、千分之一秒
datetime 日期和时间
11.2.4创建表
CREATE TABLE 表名
(
列名1 数据类型和长度1 列属性1,
列名2 数据类型和长度2 列属性2,
......
列名n 数据类型和长度n 列属性n
)
CREATE TABLE Employees
(
Emp_id integer,
Emp_name varchar(50) NOT NULL,
Sex char(2) DEFAULT('男'),
Title varchar(50) NOT NULL,
Wage float DEFAULT(0),
IdCard varchar(20) NOT NULL,
Dep_id integer NOT NULL
)
常用的关键字
PRIMARY KEY,定义此列为主键列。定义为主键的列可以唯一标识表中的每一行记录。
AutoIncrement,定义此列为自增列,即由系统自动生成此列的值。
NOT NULL,指定此列不允许为空。NULL表示允许空,但因为它是默认设置,不需要指定。
DEFAULT,指定此列的默认值。例如,指定Sex列的默认值为“男”,可以使用DEFAULT('男')。这样,在向表中插入数据时,如果不指定此列的值,则此列采用默认值
使用下面的语句可以查看当前数据库里:.table
执行下面的语句可以查看表Employees的结构:select * from sqlite_master where type="table" and name="Employees";
11.2.5向表中添加列
使用ALTER TABLE语句向表中添加列的基本语法如下:
ALTER TABLE 表名 ADD COLUMN 列名 数据类型和长度 列属性

ALTER TABLE Employees ADD Tele VARCHAR(50) NULL
ALTER TABLE Employees MODIFY Tele CHAR(50) NULL
执行下面的语句可以查看表Employees的结构。
.schema Employees
11.2.6向表中插入数据
可以使用INSERT语句向表中插入数据。基本使用方法如下:
INSERT INTO 表名 (列名1, 列名2, …, 列名n)
VALUES (值1, 值2, …, 值n);

INSERT INTO Employees (Emp_name, IdCard, Dep_id, Title) VALUES('张三', '1101234567890', 1, '部门经理');
11.2.7修改表中的数据
可以使用UPDATE语句修改表中的数据。UPDATE语句的基本使用方法如下所示:
UPDATE 表名 SET 列名1 = 值1, 列名2 = 值2, …, 列名n = 值n
WHERE 更新条件表达式
11.2.8删除数据
可以使用DELETE语句删除表中的数据,基本使用方法如下所示:
DELETE FROM 表名WHERE 删除条件表达式
当执行DELETE语句时,指定表中所有满足WHERE子句条件的行都将被删除。
DELETE FROM Employees WHERE Emp_name = '李明';
11.2.9查询数据
可以使用SELECT语句查询表中的数据,基本使用方法如下所示:
SELECT * FROM 表名WHERE 删除条件表达式
*表示查询表中所有的字段,当执行SELECT语句时,指定表中所有满足WHERE子句条件的行都将被返回。
SELECT * FROM Employees WHERE Title= '部门经理';
11.2.10在Python中访问SQLite数据库
import sqlite3
1.创建和打开数据库
使用connect()方法可以创建和打开数据库,具体方法如下:
数据库连接对象 = sqlite3.connect(数据库名)
import sqlite3
cx = sqlite3.connect("d:/test.db")
执行SQL语句
使用execute ()方法可以执行SQL语句,具体方法如下:
数据库连接对象.execute(SQL语句)
使用游标查询数据
Python可以使用下面的方法创建一个游标对象:
游标对象 =数据库连接对象.cursor()
可以使用游标对象的execute()方法执行SELECT语句将查询结果保存在游标中,方法如下:
游标对象.execute(SELECT语句)
可以使用游标对象的fetchall()方法获取游标中所有的数据到一个元组中,方法如下:
结果集元组 =游标对象.fetchall()
11.3MySQL数据库
11.3.1安装MySQL数据库
11.3.2MySQL—Front
11.3.3创建数据库
11.3.4删除数据库
11.3.5MySQL数据类型
11.3.6创建表
11.3.7编辑和查看表
11.3.8删除表
11.3.9插入数据
11.3.10修改数据
11.3.11删除数据
11.3.12使用SELECT语句查询数据
11.3.13在Python中访问MySQL数据库

第13章 绘图
11.1turtle绘图
Python2.6之后,内置turtle Graphics。中心点为原点。
属性:color, fillcolor, pensize
行为:
运动命令:forward(len), backword(len), right(degree), left(degree), goto(x, y), speed(v)v是[0, 11]的整数reset()
画笔控制命令:down() , up()
结束绘制命令:s=Screen(), s.extionclick()
from turtle import *
reset()
color("purple")
pensize(3)
for i in range(6):
forward(110)
right(144)
color('red')
up()
goto(50, -120)
down()

finish draw

s = Screen()
s.exitonclick()
11.2canvas绘图
1.引入Tkinter
2.设置画布背景色
3.创建图形
4.消息主循环
import Tkinter

top = Tkinter.Tk()
c = Tkinter.Canvas(top, bg = "blue", height = 500, width = 500)

line = c.create_line(0,0,110, 110, fill = "red")

polygon = c.create_polygon(110, 110, 150, 150, 110, 200, fill = "yellow")

oval = c.create_oval(250, 50, 400, 100, fill = "white")

line = c.create_line(50, 250, 100, 300, fill = "white")
oval = c.create_oval(50, 250, 100, 300, fill = "black")

cord = [250, 250, 350, 350]
arc = c.create_arc(cord, start = 0, extent = 270, fill ="red")

c.pack()
top.mainloop()
参考资料
Python基础教程刘浪
Python程序设计基础周元哲
Python语言程序设计 李娜(基于Python3)

help(‘modules’) 就能列出所有已经安装的模块了

Python2.7不支持中文,包括中文注释。有中文注释不能保存。

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注