python笔记
1、迭代
for value in a.itervalues(): for k, v in a.iteritems():
#a可以是dict, 字符串,list,生成器
判断是否可迭代
from collections import Iterable
isinstance(type, Iterable)
下标迭代
for i, v in enumerate(['a', 'b', 'c']):
print i, v
生成器
a = [i for i in range(10)] -> list
a = (i for i in range(10)) -> 生成器
#生成器有a.next()方法,也可以用for
#通过函数得到生成器:yield
斐波那契
def fib(max):
n, a, b = 0, 0, 1
while n < max:
yield b
a, b = b, a + b
n = n + 1
2、map/reduce
- map(f, data),接受一个函数,一个数据
map(str, [1, 2, 3, 4, 5, 6, 7, 8, 9]) - reduce(f, data),接受一个函数,一个数据
reduce(f, [x1, x2, x3, x4]) = f(f(f(x1, x2), x3), x4)递归的执行函数f
#string转int
def str2int(s):
def fn(x, y):
return 10 * x + y
def char2int(x):
return {'0': 0, '1':1, '2':2, ..., '9':9} [x] #通过key“x”取出对应的数
return reduce(fn, map(char2int, s))
3、filter
filter(f, data),接受一个函数,一个数据,根据返回值true/false决定保留还是丢掉
4、sorted
sorted(data[, fn]),接受一个数据,(可选)一个函数,这个函数只需定义二维关系
5、返回函数
在函数内返回值也为函数:
def f(*args):
def fn():
return fn
只有在调用时才执行计算:fn()
6、闭包
返回闭包时牢记的一点就是:返回函数不要引用任何循环变量,或者后续会发生变化的变量。
7、匿名函数lambda
关键字lambda表示匿名函数,冒号前表示参数,之后表示表达式,不需要return,只能有一个表达式
8、装饰器
装饰器返回的是一个函数
- name:一种属性。
函数对象可以被赋值给变量,通过__name__可以拿到函数名 - 功能:不修改函数的前提下,增强函数的功能
- @:函数的装饰符,出现在函数定义的上一行,它将被修饰的函数作为输入参数,并返回修饰后的函数.
def log(func):
def wrapper(*args, **kw):
print 'call %s():' % func.__name__
return func(*args, **kw)
return wrapper
@log
def now():
print '2013-12-25'
结果:
>>> now()
call now():
2013-12-25
9、*args **kw
- *args:非关键字参数,元组
- **kw:关键字参数,字典
10、偏函数
functools.partial的作用就是,把一个函数的某些参数给固定住(也就是设置默认值),返回一个新的函数,调用这个新函数会更简单
11、模块
- init.py
标志一个模块包,可以为空,也是模块,名称为包名 - if name==‘main’
当我们在命令行运行hello模块文件时,Python解释器把一个特殊变量__name__置为__main__,而如果在其他地方导入该hello模块时,if判断将失败,因此,这种if测试可以让一个模块通过命令行运行时执行一些额外的代码,最常见的就是运行测试。 - 作用域
xxx: 特殊变量,可以被引用
_xx/__xx:私有
future
12、面向对象编程OOP
面向对象的设计思想是抽象出Class,根据Class(类)创建Instance(实例)。class既包含数据又包含方法。
__init__方法
第一个参数永远是self,表示创建的实例本身,因此,在__init__方法内部,就可以把各种属性绑定到self,因为self就指向创建的实例本身。有了__init__方法,在创建实例的时候,就不能传入空的参数了,必须传入与__init__方法匹配的参数,但self不需要传,Python解释器自己会把实例变量传进去。和普通的函数相比,在类中定义的函数只有一点不同,就是第一个参数永远是实例变量self,并且,调用时,不用传递该参数。除此之外,类的方法和普通函数没有什么区别,仍然可以用默认参数、可变参数和关键字参数。
数据封装
使用类的方法,“包裹”(封装)数据,使数据不外现。
通过Class.name 为类Class增加属性name
访问限制
- 内部属性不允许外部访问: __xxx;
- 需要外部能访问不能修改
定义方法get_xxx(self):return self.__xxx;
需要外部能修改:定义方法set_xxx(self,xxx): self.__xxx = xxx
虽然可以访问但是视为私有:_xxx - 继承
子类获得了父类的全部功能;
子类方法覆盖父类方法(多态) - 多态:可以方便的以父类为参数定义函数,实现多个子类
- “开闭”原则:
对扩展开放:允许新增Animal子类;对修改封闭:不需要修改依赖Animal类型的run_twice()等函数。 - 获取对象信息
type(xxx)
isinstance(a, sometype) - dir():如果要获得一个对象的所有属性和方法,可以使用dir()函数,它返回一个包含字符串的list
- slots = (xxx, yyy):定义允许被外部“赋值”(绑定)的属性,子类不继承父类的slots,除非显示定义
- @property:装饰器,将方法变成属性调用,同时保留方法的灵活性
class Student(object):
@property
def score(self):
return self._score
@score.setter
def score(self, value):
if not isinstance(value, int):
raise ValueError('score must be an integer!')
if value < 0 or value > 100:
raise ValueError('score must between 0 ~ 100!')
self._score = value
- 多重继承Mixin:通过多重继承,一个子类就可以同时获得多个父类的所有功能。class Bat(Mammal, Flyable):pass。java不行。
- 其他内置方法以自定义定制类:
- str(self): 用于返回print Class的结果
- repr():用于返回 Class 回车的结果,可以设置为与__str__()相同
- iter():用于定义可迭代对象,需要跟next方法一起定义
- getitem():用于返回按下标访问的对象
- getattr(self,attr):用于调用没有定义的属性attr时的返回值
- call():用于定义调用实例
13、调试
- assert:断言,替代print。
assert 判断条件, 否则语句。可以通过 python -o关闭所有断言,此时相当于pass - logging:需要import logging,设置logging.basicConfig(level=logging.INFO),用logging.info("")替代print。通过level设置debug,info,warning,error
- pdb:单步调试。
python -m pdb python.py 输入1显示代码,输入n执行下一步,输入p 变量名 输出变量,输入q推出
pdb.set_trace():设置断点。需要import pdb, 到断点自动暂停,p查看变量,c继续 - 单元测试:(。。。)
- 文档测试:(。。。)
14、IO编程
- f = open(’/Users/michael/test.txt’, ‘r’):文件打开,若不存在报错
- f.read():方法可以一次读取文件的全部内容到内存str
f.read(size):仅读取size字节
readline()可以每次读取一行内容,readlines()一次读取所有内容并按行返回list - 字符解码:要读取非ASCII编码的文本文件,就必须以二进制模式打开,再解码
>>> f = open('/Users/michael/gbk.txt', 'rb')
>>> u = f.read().decode('gbk')
>>> u
u'\u6d4b\u8bd5'
>>> print u
测试
- codecs模块帮我们在读文件时自动转换编码,直接读出unicode
import codecs
with codecs.open('/Users/michael/gbk.txt', 'r', 'gbk') as f:
f.read() # u'\u6d4b\u8bd5'
- os模块:操作文件系统。
os.environ: 获取环境变量
os.getenv(xxx):获取某个环境变量
os.uname():获取系统详细信息
os.path:操作文件或目录。shutil,补充模块
os.path.abspath(’.’):获取当前绝对路径;
os.path.join(‘xxx’, ‘xxx’):将路径和文件名组合成新路径,可以避免不同操作系统下分隔符问题
os.path.split(‘xxx/xxx.txt’): 分割路径和文件名
ps.path.splitext(‘xxx’):得到“文件名”和扩展名
os.mkdir(‘xxx’):新建
os.rmdir(‘xxx’):删除
os.rename(‘xxx’):重命名文件
os.remove(‘xxx’):删除文件
os.listdir;os.path.isdir;os.path.isfile - 序列化:把变量从内存中变成可存储或传输的过程称之为序列化,在Python中叫pickling,在其他语言中也被称之为serialization,marshalling,flattening等等,都是一个意思。序列化之后,就可以把序列化后的内容写入磁盘,或者通过网络传输到别的机器上。反过来,把变量内容从序列化的对象重新读到内存里称之为反序列化,即unpickling。
- 模块pickle/cPickle
pickle.dumps(variable)-pickle.loads(str): pickle.dump(variable, file)-pickle.load(file) - 模块json:json.dumps-json.loads
15、进程和线程
- 进程(Process):一个任务
- 线程(Thread) :进程内的“子任务”
- multiprocessing模块
提供了一个Process类来代表一个进程对象
from multiprocessing import Process
import os
#子进程要执行的代码
def run_proc(name):
print 'Run child process %s (%s)...' % (name, os.getpid())
if __name__=='__main__':
print 'Parent process %s.' % os.getpid()
p = Process(target=run_proc, args=('test',)) #创建进程池
print 'Process will start.'
p.start() #开始
p.join() #等待结束
print 'Process end.'
from multiprocessing import Pool
import os, time, random
def long_time_task(name):
print 'Run task %s (%s)...' % (name, os.getpid())
start = time.time()
time.sleep(random.random() * 3)
end = time.time()
print 'Task %s runs %0.2f seconds.' % (name, (end - start))
if __name__=='__main__':
print 'Parent process %s.' % os.getpid()
p = Pool() #创建,可以设置可以并行的进程数量
for i in range(5):
p.apply_async(long_time_task, args=(i,)) #开始
print 'Waiting for all subprocesses done...'
p.close() #结束
p.join() #等待结束,对pool对象,之前必须调用close,强制结束perminate
print 'All subprocesses done.'
- 通信:进程间通信是通过Queue、Pipes等实现的。
- thread和threading
thread是低级模块,threading是高级模块,对thread进行了封装。绝大多数情况下,我们只需要使用threading这个高级模块。
import time, threading
#新线程执行的代码:
def loop():
print 'thread %s is running...' % threading.current_thread().name
n = 0
while n < 5:
n = n + 1
print 'thread %s >>> %s' % (threading.current_thread().name, n)
time.sleep(1)
print 'thread %s ended.' % threading.current_thread().name
print 'thread %s is running...' % threading.current_thread().name
t = threading.Thread(target=loop, name='LoopThread') #创建线程锁:保证同一时间只有一个线程在运行。创建一个锁就是通过threading.Lock()来实现:
t.start() #开始
t.join() #等待结束
print 'thread %s ended.' % threading.current_thread().name
balance = 0
lock = threading.Lock()
def run_thread(n):
for i in range(100000):
# 先要获取锁:
lock.acquire()
try:
# 放心地改吧:
change_it(n)
finally:
# 改完了一定要释放锁:
lock.release()
当多个线程同时执行lock.acquire()时,只有一个线程能成功地获取锁,然后继续执行代码,其他线程就继续等待直到获得锁为止。全局变量必须加锁
- GIL锁:Global Interpreter Lock,任何Python线程执行前,必须先获得GIL锁,然后,每执行100条字节码,解释器就自动释放GIL锁,让别的线程有机会执行。这个GIL全局锁实际上把所有线程的执行代码都给上了锁,所以,多线程在Python中只能交替执行,即使100个线程跑在100核CPU上,也只能用到1个核。
- threading.local():以threading.current_thread()为key将每个线程的全局变量保存独立保存
- 所有线程共享进程的内存。线程不如进程稳定。
- 计算密集型:要最高效地利用CPU,计算密集型任务同时进行的数量应当等于CPU的核心数。代码运行效率至关重要。Python这样的脚本语言运行效率很低,完全不适合计算密集型任务。对于计算密集型任务,最好用C语言编写。
- IO密集型:对于IO密集型任务,任务越多,CPU效率越高,但也有一个限度。对于IO密集型任务,最合适的语言就是开发效率最高(代码量最少)的语言,脚本语言是首选,C语言最差。
16、正则表达式
*贪婪匹配,?非贪婪匹配
预编译:re.compile(r’^(\d{3})-(\d{3,8})$’)
17、常用模块
datetime
datetime.now();
dt.timestamp();
datetime.fromtimestamp(t);
datetime.utcfromtimestamp(t);
datetime.strptime(‘2015-6-1 18:19:59’, ‘%Y-%m-%d %H:%M:%S’);
now.strftime(’%a, %b %d %H:%M’);
timedelta(hours=10)
collections
namedtuple(‘name’, [‘n1’, ‘n2’,…])命名tuple,并能根据属性引用
deque: deque除了实现list的append()和pop()外,还支持appendleft()和popleft(),这样就可以非常高效地往头部添加或删除元素。
defaultdict: dd = defaultdict(lambda: ‘N/A’),key不存在时,返回一个默认值
OrderedDict:OrderedDict的Key会按照插入的顺序排列,不是Key本身排序
Counter
计数器,是dict的子类
from collections import Counter
c = Counter()
for ch in 'programming':
c[ch] = c[ch] + 1
>>> c
Counter({'g': 2, 'm': 2, 'r': 2, 'a': 1, 'i': 1, 'o': 1, 'n': 1, 'p': 1})
base64
是一种用64个字符来表示任意二进制数据的方法,常用于在URL、Cookie、网页中传输少量二进制数据。
hashlib
提供了常见的摘要算法,如MD5,SHA1等等。
import hashlib
md5 = hashlib.md5()
md5.update('how to use md5 in python hashlib?')#太长可以多次调用update
print md5.hexdigest()#结果
itertools
itertools.count(1) #产生自然数列
itertools.cycle(xxx)#无限重复xxx
itertools.repeat(‘A’, 10) #重复10次
itertools.takewhile(lambda x: x <= 10, xxx) #将无限序列xxx截取
itertools.chain(‘ABC’, ‘XYZ’)#将一组迭代对象串联起来,形成一个更大的迭代器
itertools.groupby #把迭代器中相邻的重复元素挑出来放在一起
itertools.imap #可以作用于无限序列,返回迭代对象;map作用于有限,返回计算结果
itertools.ifilter #filter的惰性实现
第三方模块
- https://pypi.org
- pillow----PIL:Python Imaging Library,已经是Python平台事实上的图像处理标准
- chardet:检测编码
- psutil:获取系统信息
18、网络编程
网络通信
两台计算机上的两个进程之间的通信
- 互联网的协议简称TCP/IP协议:
IP协议负责把数据从一台计算机通过网络发送到另一台计算机。一个IP包除了包含要传输的数据外,还包含源IP地址和目标IP地址,源端口和目标端口。TCP协议则是建立在IP协议之上的。
TCP协议负责在两台计算机之间建立可靠连接,保证数据包按顺序到达。TCP协议会通过握手建立连接,然后,对每个IP包编号,确保对方按顺序收到,如果包丢掉了,就自动重发。 - Socket:网络编程的一个抽象概念。通常我们用一个Socket表示“打开了一个网络链接”,而打开一个Socket需要知道目标计算机的IP地址和端口号,再指定协议类型即可。
- TCP编程:创建TCP连接时,主动发起连接的叫客户端,被动响应连接的叫服务器
- UDP编程:不需要建立连接,只需要知道对方的IP地址和端口号,就可以直接发数据包。但是,能不能到达就不知道了。虽然用UDP传输数据不可靠,但它的优点是和TCP比,速度快,对于不要求可靠到达的数据,就可以使用UDP协议。
电子邮件:
MUA:Mail User Agent——邮件用户代理。即电子邮件软件
MTA:Mail Transfer Agent——邮件传输代理,就是那些Email服务提供商,比如网易、新浪等等
MDA:Mail Delivery Agent——邮件投递代理
发件人 -> MUA -> MTA -> MTA -> 若干个MTA -> MDA <- MUA <- 收件人
发邮件时,MUA和MTA使用的协议就是SMTP:Simple Mail Transfer Protocol,后面的MTA到另一个MTA也是用SMTP协议。
收邮件时,MUA和MDA使用的协议有两种:POP:Post Office Protocol,目前版本是3,俗称POP3;IMAP:Internet Message Access Protocol,目前版本是4,优点是不但能取邮件,还可以直接操作MDA上存储的邮件,比如从收件箱移到垃圾箱,等等。
19、数据库
要操作关系数据库,首先需要连接到数据库,一个数据库连接称为Connection;
连接到数据库后,需要打开游标,称之为Cursor,通过Cursor执行SQL语句,然后,获得执行结果。
20、协程
yield
(。。。)
异步IO(。。。)