本文是本人学完 Python 后的一遍回顾, 加深理解顺便留作手册以备查阅
学习 Python 的这几天来, 觉得 Python 还是比较简单, 容易上手的, 就基本语法而言, 但是有些高级特性掌握起来还是有些难度, 需要时间去消化 Python 给我最大的印象就是语法简洁, 就像写伪代码一样, 很多其他语言要用很多行才能实现的操作 Python 可能几行就搞定了, 这让人摆脱了繁杂的语法而专注于问题本身, 这也正是我为什么不太喜欢 Java 的原因之一, 虽然它很强大
一 Python 简介
Python 是一种用来编写应用程序的高级程序设计语言, TIOBE 程序语言排行榜 2016 年 4 月的排名如下:
Python 实现强势逆袭, 而且我相信, 随着时间的推移, 国内 Python 语言未来前景也是一片向好
Python 的特点是优雅简单, 易学易用(虽然我感觉还是有一些概念不容易理解),Python 的哲学是尽量用最少的, 最简单易懂的代码实现需要的功能 Python 适宜于开发网络应用, 脚本写作, 日常简单小工具等等 Python 的缺点是效率较低, 但是在大量的场合效率却不是那么重要或者说 Python 不是其性能瓶颈, 所以不要太在意其次是 2.x-3.x 的过渡使得许多 3.x 还缺少很多 2.x 下的模块, 不过也在完善中其次就是源代码无法加密, 发布 Python 程序其实就是发布源代码
二基础语法要点
1. 如果一个字符串中有许多需要转义的字符, 而又不想写那么多, 那么可以用 r'...' 表示 '...'内的内容不转义
2.Python 可用'''...'''来表示多行内容, 如:
- >>> print('''line1
- line2
- line3''')
- line1
- line2
- line3
3.Python 的逻辑运算 and, or, not 分别对应 C 语言中的 &&, ||, !.
4.Python 的整数与浮点数大小都没有范围
5.Python 中除法有两种: / 除出来必是浮点数, // 除出来是整数, 即地板除
6.Python 中一切皆引用每个对象都有一个引用计数器 (内部跟踪变量) 进行跟踪, 引用计数值表示该对象有多少个引用, 当初次产生赋给变量时, 引用计数为 1, 其后没进行下列行为中的任意一种都会增加引用计数:
赋值: a = b
用作函数参数传递: func(a)
成为容器对象的一个元素: lis = [1,2,a]
以下任意一种行为都会减少引用计数:
del 销毁: del a
变量另赋给其他对象: a = False
对象从容器中删除: lis.remove(a)
身在的容器被销毁: del lis
7. 深拷贝与浅拷贝的概念与对比, 有点复杂, 看这篇文章
8.list,tuple 和 dict,set
list: 为列表, 是一个有序集合, 类似于数组但又比数组功能强大, 可以随时 append,pop 元素, 下标从 0 开始, 且下标为加 n 模 n 制, 即 lis[-1] = lis[len-1], 下标范围[-len,len-1].
tuple: 为元组, 类似于 list, 但 list 为可变类型, 而 tuple 不可变, 即没有 append,pop 等函数一个建议是为了安全起见, 能用 tuple 代替 list 尽量用 tuple 如果 tuple 只有一个元素, 要写成如 (1,) 以避免歧义
dict: 字典类型, 存放 key-value 键值对, 可以根据 key 迅速地找出 value, 当然, key 必须是不可变类型, 如下是错误的:
- >>> dic = {[1,2]:'value'}
- Traceback (most recent call last):
- File "<pyshell#10>", line 1, in <module>
- dic = {[1,2]:'value'}
- TypeError: unhashable type: 'list'
list 与 dict 的优劣对比:
dict:
1. 插入, 查找速度快, 跟 key 的数目无关
2. 需占用大量内存, 内存浪费严重
list:
1. 插入, 查找速度慢, O(n)的复杂度, 随元素个数增加而增加
2. 占用内存小
dict 内部存放的顺序和 key 放入的顺序是没有关系的
set:set 与 dict 类似, 相当于只有 key 没有 value 的 dict, 每个 key 不同, set 间有 &, | 等操作对应集合的交, 并操作
三函数
1. 函数是对象, 函数名即是指向对应函数对象的引用, 所以可以将函数名赋给一个变量, 相当于给函数起一个别名
- >>> mmm = max
- >>> mmm(1,2,3)
- 3
2.Python 函数可以返回多个值, 之所以打引号, 是因为实际上返回的多个值拼成了一个元组, 返回这个元组
3. 定义默认参数需要牢记: 默认参数必须指向不变对象否则第一次调用和第二次调用结果会不一样, 因为可变的默认参数调用后改变了
4. 可变参数: 传入的参数个数是可变的, 可以是 0 个或多个可变参数会将你传入的参数自动组装为一个 tuple 在你传入的 list 或 tuple 名字前加一个 * 即说明传入的是可变参数习惯写法为 args
5. 关键字参数: 传入 0 个或多个含参数名的参数, 这些参数被自动组装成一个 dict 习惯写法 **kw, 如 **a 表示把 a 中所有的键值对以关键字参数的形式传入 kw, 获得一个 dict, 这个 dict 是 a 的一份拷贝, 对 kw 改动不会传递到 a
6. 命名关键字在函数定义中跟在一个分割符后, 如
- def func(a,b,*,c,d):
- pass
c,d 为命名关键字参数, 可以限制调用者可以传入的参数名, 同时可以提供默认值
7. 参数定义顺序: 必选参数, 默认参数, 可变参数 / 命名关键字参数, 关键字参数
8. 切片操作格式为 lis[首下标: 尾下标: 间隔], 如果都不填, 即 lis[::]则代表整个容器 lis
9. 用圆括号 () 括起来一个列表生成式创建一个生成器 generator,generator 保存生成算法, 我们可以用 next(g)取得生成器 g 的下一个返回值生成器的好处就是我们不需要提前生成所有列表元素, 而是需要时再生成, 这在某些情况下可以节省许多内存算法也可以不是列表生成式而是自定义函数, 只需在函数定义中包含 yield 关键字
10.map()和 reduce(): 二者都是高阶函数 map()接收两个参数, 一个是函数, 一个是 Iterable 序列, map 将传入的函数依次作用在序列每一个元素上, 并把结果作为新的 Iterator 返回 reduce()类似累积计算版的 map(), 把一个函数作用在一个序列上, 每次接收两个参数, 将结果继续与序列的下一个元素做累积计算
利用 map 和 reduce 编写一个 str2float 函数, 如把字符串'123.456'转换成浮点数 123.456:
- from functools import reduce
- def str2float(s):
- def f1(x,y):
- return x*10 + y
- def char2num(s):
- return {'0': 0, '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9}[s]
- def f2(x,y):
- return x*0.1 + y
- a,b = s.split('.')
- print('a=',a)
- print('b=',b)
- return reduce(f1, map(char2num,a)) + 0.1*reduce(f2, map(char2num,b[::-1]))
- print('str2float(\'123.456\') =', str2float('123.456'))
11.fliter()函数过滤序列, 类似于 map()作用于每一元素, 根据返回值是 True 或者 False 决定舍弃还是保留该元素函数返回一个 Iterator
12.sorted()函数可实现排序, 类似于 C++ 库中的 sort()函数, 但是比其更加简洁, 语法为
sorted(lis,key=func,reverse=T/F)
key 函数可实现自定义的排序规则, reverse 表示升序还是降序
13. 一个函数可以返回一个函数, 但是返回时该函数并未执行, 所以返回函数中不要引用任何可能发生变化的变量, 否则会出现逻辑错误
14. 装饰器(decorator): 当需要增强函数的功能却不希望修改函数本身, 那么可以采用装饰器这种运行时动态增加功能的方式, 增加的功能卸载装饰器函数中如在执行前后打印'begin call'和'end call', 可以这样做:
- import functools
- def log(func):
- @functools.wraps(func) #为了校正函数签名, 最好写上
- def wrapper(*args,**kw):
- print('begin call')
- f = func(*args,**kw)
- print('end call')
- return f
- return wrapper
- @log
- def hah():
- print('hahahaha')
- hah()
- ---
- begin call
- hahahaha
- end call
15. 偏函数: functools.partial(), 作用是将一个函数的某些参数固定住, 作为新函数的参数, 即固定住该参数, 返回一个新函数, 使调用更简单
四面向对象编程
1.Python 实例变量可以自由地绑定任何属性
2. 为了不让内部属性不被外部访问, 在属性的名称前加上两个下划线__, 这样就变成了一个私有变量(private), 注意, 不能直接访问不代表一定不能访问, 事实上, 加双下划线后 Python 就会将其改名为_class 名__name, 所以还是可以这样来访问这个私有变量
3. 对于静态语言, 如果要求传入一个 class 类型的对象, 那么传入的对象必须是 class 类型或者其子类, 否则将无法调用 class 中的方法, 而 Python 这样的动态语言有鸭子类型一说, 即不一定要传入 class 类型或其子类, 而只要保证传入的对象中有要使用的方法即可
4. 如果想要限制实例可以绑定的属性, 那么在定义 class 时定义一个__slots__变量即可, 例如:
- class Student(object):
- __slots__ = ('name','age')
注意,__slots__限制的属性对当前类实例起完全限制作用, 且与子类共同定义其__slots__, 也就是说子类可以定义自己的__slots__, 子类实例允许定义的属性就是自身的__slots__加上父类的__slots__, 即并集
5.@ property 装饰器可以使一个 getter 方法变成属性, 如果方法名为 me, 那么 @me.setter 装饰器则可使一个 setter 方法变成属性这样可以使代码更简短, 同时可对参数进行必要的检查
6. 通过多重继承, 可使子类拥有多个父类的所有功能
7. 在类中__call__方法可使实例对象像函数那样直接调用, 作用即是该方法定义的过程
8.ORM(Object Relational Mapping 对象关系映射), 就是把关系数据库的一行映射为一个对象, 也就是一个类对应一个表 ORM 的实现需要通过 metaclass 元类修改类的定义元类可以改变类创建时的行为
五调试
1.Python 调试方法:
直接打印
断言
pdb
IDE
六 IO 编程
1. 序列化: 把变量从内存中变成可存储或传输的过程称之为序列化 Python 用 pickle 模块实现序列化序列化之后, 就可以把序列化后的内容存储到磁盘上或者通过网络进行传输 pickle.dumps()将对象序列化成一个 bytes, 而 pickle.loads()可以根据 bytes 反序列化出对象
2.pickle 虽好, 但是它专为 Python 而生, 所以要在不同语言间传递对象, 最好还是 xml 或者 json, 而 json 表示格式是一个字符串, 更易读取, 且比 xml 快, 所以更加适宜于对象序列化 Python 内置了 json 模块, 相应方法仍然是 dumps()和 loads()
3. 但是在默认情况下, 有些对象是无法序列化的, 所以我们有时还需要定制转换方法, 告诉 json 该如何将某类对象转换成可序列为 json 格式的 {} 对象如下即是一个转换方法:
- def mantodict(std):
- return {
- 'name': std.name,
- 'age': std.age,
- 'id': std.id
- }
七进程与线程
1.Python 用 mutiprocessing 模块来实现多进程
2. 如果要大量创建子进程, 可以使用进程池, 示例如下:
- from multiprocessing import Pool
- ....
- p = Pool(4)
- for i in range(5):
- p.apply_async(long_time_task, args=(i,))
- print('Waiting for all subprocesses done...')
- p.close()
- p.join()
- print('All subprocesses done.')
要使用进程池需新建 Pool 对象, 对 Pool 对象调用 join()使等待池中所有子进程运行完毕, 调用 join()方法之前必须调用 close(), 且此后无法再新加子进程
3. 使用 subprocess 模块可以方便的启动并管理一个子进程, 控制其输入输出
4. 进程间通信使用 Queue,Pipes 实现
5.threading 模块管理线程 threading.lock()创建线程锁, 防止同时访问互斥资源造成的错误, 示例如下:
- lock = threading.Lock()
- ...
- lock.acquire()
- ...
- change(mutex)
- ...
- lock.release()
6.ThreadLocal 可以解决参数在一个线程中各个函数之间互相传递的问题
7.managers 模块实现分布式进程
八正则表达式与常用内建模块
1.re 模块进行正则表达式编译和匹配, 如果该表达式需要匹配很多次, 那么最好进行编译从而大大节省时间
正则表达式匹配邮箱例子:
- import re
- hah = re.compile('[0-9a-zA-Z]+[\.[0-9a-zA-Z]+]*\@[0-9a-zA-Z]+\.[a-z]{2,3}')
- print(hah.match('someone@gmail.com').group())
- print(hah.match('bill.gates@microsoft.com').group())
- i = 1
- while i < 10:
- r = input('请输入邮箱:')
- print(hah.match(r).group())
- i = i+1
2.datetime 模块进行日期和时间的处理, 每一个时间对应一个 timestamp, 我们把 1970 年 1 月 1 日 00:00:00 UTC+00:00 时区的时刻称为 epoch time, 记为 0(1970 年以前的时间 timestamp 为负数), 当前时间就是相对于 epoch time 的秒数, 称为 timestamp 字符串和 datetime 也可以相互转换, 采用 strptime()方法, 字符串转换为 datetime 时需要设定一个识别格式, 其中
%Y-%m-%d %H:%M:%S
分别表示年 - 月 - 日 时 - 分 - 秒
从 datetime 得出月份, 星期等字符串用 strftime()方法, 其中:
%a, %b %d %H:%M
分别表示星期, 月份 日期 时: 分
示例:
- from datetime import datetime
- r = '2015-11-23 12:01'
- dt = datetime.strptime(r, '%Y-%m-%d %H:%M')
- print(dt)
- week = dt.strftime('%a %b %d, %H:%M')
- print(week)
- 2015-11-23 12:01:00
- Mon Nov 23, 12:01
3.collections 是 Python 内建的一个集合模块, 提供了许多有用的集合类
4.Base64 是一种任意二进制到文本字符串的编码方法, 常用于在 URLCookie 网页中传输少量二进制数据
5.struct 模块用来解决 bytes 和其他二进制数据类型的转换
6.Python 的 hashlib 提供了常见的哈希算法, 如 MD5,SHA1 等等 hashlib 实现简单登录:
- import hashlib
- db = {
- 'michael': 'e10adc3949ba59abbe56e057f20f883e',
- 'bob': '878ef96e86145580c38c87f0410ad153',
- 'alice': '99b1c2188db85afee403b1536010c2c9'
- }
- def get_md5(ostr):
- md5 = hashlib.md5()
- md5.update(ostr.encode())
- return md5.hexdigest()
- def login(user, password):
- r = get_md5(password)
- for name in db:
- if db[name] == r:
- return True
- return False
- print(login('bob','abc999'))
- True
7.Python 的内建模块 itertools 提供了非常有用的用于操作迭代对象的函数
8.urllib 提供了一系列用于操作 URL 的功能如 GET,POST
9.PIL(Python Imaging Library Python 图像库)是一个强大的图像处理标准库, 功能强大却又简单易用现在的名字叫做 Pillow 可以如下安装 Pillow:
pip3 install pillow
从下面生成数字验证码的程序可以窥其一斑:
- from PIL import Image, ImageDraw, ImageFont, ImageFilter
- import random
- # 随机字母:
- def rndChar():
- return chr(random.randint(48, 57))
- # 随机颜色 1:
- def rndColor():
- return (random.randint(64, 255), random.randint(64, 255), random.randint(64, 255))
- # 随机颜色 2:
- def rndColor2():
- return (random.randint(32, 127), random.randint(32, 127), random.randint(32, 127))
- # 240 x 60:
- width = 60 * 4
- height = 60
- image = Image.new('RGB', (width, height), (255, 255, 255))
- # 创建 Font 对象:
- font = ImageFont.truetype('ariblk.ttf', 40)
- # 创建 Draw 对象:
- draw = ImageDraw.Draw(image)
- # 填充每个像素:
- for x in range(width):
- for y in range(height):
- draw.point((x, y), fill=rndColor())
- # 输出文字:
- for t in range(4):
- draw.text((60 * t + 10, 10), rndChar(), font=font, fill=rndColor2())
- # 模糊:
- image = image.filter(ImageFilter.BLUR)
- image.save('code.jpg', 'jpeg')
效果:
九网络编程和电子邮件
1. 网络编程主要是 TCP 和 UDP 的编程, 示例见 Python 网络编程利用 Python 进行 TCPUDP 套接字编程
2.SMTP 是发送邮件的协议, Python 内置对 SMTP 的支持, 可以发送纯文本邮件 html 邮件以及带附件的邮件 Python 对 SMTP 支持有 smtplib 和 email 两个模块, email 负责构造邮件, smtplib 负责发送邮件 Python 内置一个 poplib 模块, 实现了 POP3 协议, 可以直接用来收邮件由于现在绝大多数大型邮件服务商都采取了反垃圾邮件措施, 所以这部分的简单实验并没有成功, 还需进一步研究, 等遇到具体情况再说
3.Python 内嵌了 sqlite 数据库, 还可以自行安装连接 mysql,MySQL 是当前最流行的开源数据库, 在行业内有着广泛的应用
十 web 开发和异步 IO
1.WSGI(Web Server Gateway Interface) 服务器网关接口
2.Python web 开发框架:
Flask: 流行的 Web 框架
Django: 全能型 Web 框架 中文文档
web.py: 一个小巧的 Web 框架
Bottle: 和 Flask 类似的 Web 框架
Tornado:Facebook 的开源异步 Web 框架 文档
3. 协程
十一参考读物
1. 廖雪峰 Python 教程
十二更多资料
1.Django 入门教程
2. 编程小白学 Python
3.Python 源码剖析
4.Python 标准库 Python 字典式书籍, 大部头
(完) 2016.2.4 初稿 5.2 修改
来源: http://www.jqhtml.com/11975.html