斜体
粗体
这是一个参考式链接
这是一个行内式链接
这是一个引用示例(在首行插入>表示引用)
//标记代码区域(或者用~~~或者缩进4个空格或者tab)
void main()
{
cout<<"hello world"<
无序列表
*或+或-都是无序列表
markdowm有序列表在Atom中默认从1开始
名字 | 性别 | 年龄 | 身高 |
---|---|---|---|
小明 | 男 | 18 | 160 |
小王 | 男 | 21 | 161 |
默认方式对齐 | |||
:— | 左对齐 | ||
:—: | 居中对齐 | ||
—: | 右对齐 |
Atom支持qq截屏图片复制粘贴进来
行内式插入图片
参考式插入图片
脚注:添加脚注只需要在想要加脚注的文字后面插上[^脚注标记]。然后你可以在文件任意位置将脚注内容写出来,脚注内容会显示在文件的最后。
[^脚注01]: 这是一个脚注的注释
转义:在以下字符前面插入反斜杠,插入之后,将不再解析这些字符,而是原样输出。
\ 反斜线
` 反引号
* 星号
_ 底线
{} 花括号
[] 方括号
() 括弧
# 井字号
+ 加号
- 减号
. 英文句点
! 惊叹号
name=raw_input("please enter your name")
>>>print "hello"+name
def calc(*numbers):
sum = 0
for n in numbers:
sum = sum + n*n
return sum
def person(,age,**kw):
print 'name:',name,'age:',age,'other','kw'
在Python中定义函数,可以用必选参数、默认参数、可变参数和关键字参数,这4种参数都可以一起使用,或者只用其中某些,
但是请注意,参数定义的顺序必须是:必选参数、默认参数、可变参数和关键字参数.
L=[]
for x in range(1,11):
L.append(x*x)
[x*x for x in range(1,11)]
[x*x for x in range(1,11) if x%2 == 0 ]
[m+n for m in 'ABC'for n in 'XYZ']
>>>L=['Hello','World','IBM','Apple']
>>>[s.lower() for s in L]
['hello','world','ibm','apple']
>>>x = 'abc'
>>>y = 123
>>>isinstance(x,str)
True
>>>isinstance(y,str)
False
def add(x,y,f):
return f(x)+f(y)
>>> def f(x):
... return x * x
...
>>> map(f, [1, 2, 3, 4, 5, 6, 7, 8, 9])
[1, 4, 9, 16, 25, 36, 49, 64, 81]
>>> def add(x, y):
... return x + y
...
>>> reduce(add, [1, 3, 5, 7, 9])
25
利用map/reduce将字符串转换为整形
def str2int(s):
def fn(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]
return reduce(fn, map(char2num, s))
练习1:首字母大写,其他小写
def wgw(x):
return [x[0].upper()+x[1:].lower()]
练习2:编写一个prod()函数,可以接受一个list并利用reduce()求积
def prod(s):
def fn(x,y):
return x*y
return reduce(fn,s)
def sushu(x):
for n in range(2,x-1):
if(x%n == 0):
return x
x=sorted([3,5,9,7,1],reverse=False)
y=sorted([3,5,9,7,1],reverse=True)
print x
print y
def count():
fs = []
for i in range(1, 4):
def f():
return i*i
fs.append(f)
return fs
f1, f2, f3 = count()
返回的函数引用了变量i,但它并非立刻执行。等到3个函数都返回时,它们所引用的变量i已经变成了3,因此最终结果为9。
返回闭包时牢记的一点就是:返回函数不要引用任何循环变量,或者后续会发生变化的变量。
如果一定要引用循环变量怎么办?方法是再创建一个函数,用该函数的参数绑定循环变量当前的值,无论该循环变量后续如何更改,已绑定到函数参数的值不变:
26. 匿名函数:关键字lambda表示匿名函数,冒号前面的x表示函数参数。
匿名函数有个限制,就是只能有一个表达式,不用写return,返回值就是该表达式的结果。
用匿名函数有个好处,因为函数没有名字,不必担心函数名冲突。此外,匿名函数也是一个函数对象,也可以把匿名函数赋值给一个变量,再利用变量来调用该函数
>>> map(lambda x: x * x, [1, 2, 3, 4, 5, 6, 7, 8, 9])
[1, 4, 9, 16, 25, 36, 49, 64, 81]
>>> import functools
>>> int2 = functools.partial(int, base=2)
>>> int2('1000000')
64
>>> int2('1010101')
85
_future_
模块:把下一个新版本的特性导入到当前版本,于是我们就可以在当前版本中测试一些新版本的特性。由于Python是由社区推动的开源并且免费的开发语言,不受商业公司控制,因此,Python的改进往往比较激进,不兼容的情况时有发生。Python为了确保你能顺利过渡到新版本,特别提供了__future__
模块,让你在旧的版本中试验新版本的一些特性。class Student(object):
pass
>>> bart = Student()
>>> bart
<__main__.Student object at 0x10a67a590>
>>> Student
<class '__main__.Student'>
__
开头,就变成了一个私有变量(private),只有内部可以访问,外部不能访问.class Student(object):
def __init__(self, name, score):
self.__name = name
self.__score = score
def print_score(self):
print '%s: %s' % (self.__name, self.__score)
双下划线开头的实例变量是不是一定不能从外部访问呢?其实也不是。不能直接访问__name
是因为Python解释器对外把__name
变量改成了_Student__name
,所以,仍然可以通过_Student__name
来访问__name
变量
33. 继承和多态:当我们定义一个class的时候,可以从某个现有的class继承,新的class称为子类(Subclass),而被继承的class称为基类、父类或超类(Base class、Super class)。继承可以把父类的所有功能都直接拿过来,这样就不必重零做起,子类只需要新增自己特有的方法,也可以把父类不适合的方法覆盖重写;
有了继承,才能有多态。在调用类实例方法的时候,尽量把变量视作父类类型,这样,所有子类类型都可以正常被接收;
旧的方式定义Python类允许不从object类继承,但这种编程方式已经严重不推荐使用。任何时候,如果没有合适的类可以继承,就继承自object类。
34. type():判断对象是什么类型;isinstance(a,int):判断是否是某个类型。
__slots__
:限制class能添加的属性.定义的属性仅对当前类起作用,对继承的子类是不起作用的;除非在子类中也定义slots,这样,子类允许定义的属性就是自身的__slots__
加上父类的__slots__
class Student(object):
@property
def birth(self):
return self._birth
@birth.setter
def birth(self, value):
self._birth = value
@property
def age(self):
return 2014 - self._birth
@property广泛应用在类的定义中,可以让调用者写出简短的代码,同时保证对参数进行必要的检查,这样,程序运行时就减少了出错的可能性。
37. Mixin:目的就是给一个类增加多个功能,这样,在设计类的时候,我们优先考虑通过多重继承来组合多个Mixin的功能,而不是设计多层次的复杂的继承关系.由于Python允许使用多重继承,因此,Mixin就是一种常见的设计。
只允许单一继承的语言(如Java)不能使用Mixin的设计
38. __str__
:返回一个好看的字符串,用户看到的;__repr__
:返回程序开发者看到的字符串
>>> class Student(object):
... def __init__(self, name):
... self.name = name
... def __str__(self):
... return 'Student object (name: %s)' % self.name
...
>>> print Student('Michael')
Student object (name: Michael
class Fib(object):
def __init__(self):
self.a, self.b = 0, 1 # 初始化两个计数器a,b
def __iter__(self):
return self # 实例本身就是迭代对象,故返回自己
def next(self):
self.a, self.b = self.b, self.a + self.b # 计算下一个值
if self.a > 100000: # 退出循环的条件
raise StopIteration();
return self.a # 返回下一个值
>>> for n in Fib():
... print n
...
1
1
2
3
5
...
46368
75025
__getitem__
:实例像list那样按照下标取出元素class Fib(object):
def __getitem__(self, n):
if isinstance(n, int):
a, b = 1, 1
for x in range(n):
a, b = b, a + b
return a
if isinstance(n, slice):
start = n.start
stop = n.stop
a, b = 1, 1
L = []
for x in range(stop):
if x >= start:
L.append(a)
a, b = b, a + b
return L
__getattr__
:可以针对完全动态的情况做调用。在没有找到属性的情况下,才调用__getattr__
,已有的属性,比如name,不会在__getattr__
中查找。此外,注意到任意调用如s.abc都会返回None,这是因为我们定义的__getattr__
默认返回就是None。要让class只响应特定的几个属性,我们就要按照约定,抛出AttributeError的错误.class Student(object):
def __getattr__(self, attr):
if attr=='age':
return lambda: 25
raise AttributeError('\'Student\' object has no attribute \'%s\'' % attr)
__call__
:可以直接对实例进行调用class Student(object):
def __init__(self, name):
self.name = name
def __call__(self):
print('My name is %s.' % self.name)
#metaclass是创建类,所以必须从`type`类型派生:
class ListMetaclass(type):
def __new__(cls, name, bases, attrs):
attrs['add'] = lambda self, value: self.append(value)
return type.__new__(cls, name, bases, attrs)
class MyList(list):
__metaclass__ = ListMetaclass # 指示使用ListMetaclass来定制类
try:
print 'try...'
r = 10 / 0
print 'result:', r
except ZeroDivisionError, e:
print 'except:', e
finally:
print 'finally...'
print 'END'
Python的错误其实也是class,所有的错误类型都继承自BaseException,所以在使用except时需要注意的是,它不但捕获该类型的错误,还把其子类也“一网打尽”
try:
foo()
except StandardError, e:
print 'StandardError'
except ValueError, e:
print 'ValueError'
第二个except永远也捕获不到ValueError,因为ValueError是StandardError的子类,如果有,也被第一个except给捕获了。Python所有的错误都是从BaseException类派生的
45. 调用堆栈:如果错误没有被捕获,它就会一直往上抛,最后被Python解释器捕获,打印一个错误信息,然后程序退出。如果不捕获错误,自然可以让Python解释器来打印出错误堆栈,但程序也被结束了。既然我们能捕获错误,就可以把错误堆栈打印出来,然后分析错误原因,同时,让程序继续执行下去。Python内置的logging模块可以非常容易地记录错误信息:
同样是出错,但程序打印完错误信息后会继续执行,并正常退出
# err.py:
def foo(s):
return 10 / int(s)
def bar(s):
return foo(s) * 2
def main():
bar('0')
main()
在bar()函数中,我们明明已经捕获了错误,但是,打印一个Error!后,又把错误通过raise语句抛出去了,这不有病么?
其实这种错误处理方式不但没病,而且相当常见。捕获错误目的只是记录一下,便于后续追踪。但是,由于当前函数不知道应该怎么处理该错误,所以,最恰当的方式是继续往上抛,让顶层调用者去处理。
raise语句如果不带参数,就会把当前错误原样抛出。此外,在except中raise一个Error,还可以把一种类型的错误转化成另一种类型
46. 调试:1.print打印出来,简单粗暴。2.断言assert,启动Python解释器时可以用-O参数来关闭assert。3.logging,和assert比,logging不会抛出错误,而且可以输出到文件。4.pdb,启动Python的调试器pdb,让程序以单步方式运行,可以随时查看运行状态。
# err.py
def foo(s):
n = int(s)
return 10 / n
def bar(s):
try:
return foo(s) * 2
except StandardError, e:
print 'Error!'
raise
def main():
bar('0')
main()
# err.py
def foo(s):
n = int(s)
assert n != 0, 'n is zero!'
return 10 / n
def main():
foo('0')
# err.py
import logging
s = '0'
n = int(s)
logging.info('n = %d' % n)
print 10 / n
>>> f = open('/Users/michael/test.txt', 'r')
with open('/path/to/file', 'r') as f:
print f.read()
for line in f.readlines():
print(line.strip()) # 把末尾的'\n'删掉
import codecs
with codecs.open('/Users/michael/gbk.txt', 'r', 'gbk') as f:
f.read() # u'\u6d4b\u8bd5'
with open('/Users/michael/test.txt', 'w') as f:
f.write('Hello, world!')
# 查看当前目录的绝对路径:
>>> os.path.abspath('.')
'/Users/michael'
# 在某个目录下创建一个新目录,
# 首先把新目录的完整路径表示出来:
>>> os.path.join('/Users/michael', 'testdir')
'/Users/michael/testdir'
# 然后创建一个目录:
>>> os.mkdir('/Users/michael/testdir')
# 删掉一个目录:
>>> os.rmdir('/Users/michael/testdir')
try:
import cPickle as pickle
except ImportError:
import Pickle
d = dict(name = 'Bob',age = 20,score = 88)
g=pickle.dumps(d)
f = open('dump.txt','wb')
pickle.dump(d,f)
f.close()
print g
f = open('dump.txt','rb')
n = pickle.load(f)
f.close()
print n
输出结果
json:要在不同的编程语言之间传递对象,就必须把对象序列化为标准格式,比如XML,但更好的方法是序列化为JSON,因为JSON表示出来就是一个字符串,可以被所有语言读取,也可以方便地存储到磁盘或者通过网络传输。JSON不仅是标准格式,并且比XML更快,而且可以直接在Web页面中读取,非常方便。
>>> import json
>>> d = dict(name='Bob', age=20, score=88)
>>> json.dumps(d)
'{"age": 20, "score": 88, "name": "Bob"}'
Python语言特定的序列化模块是pickle,但如果要把序列化搞得更通用、更符合Web标准,就可以使用json模块。
json模块的dumps()和loads()函数是定义得非常好的接口的典范。当我们使用时,只需要传入一个必须的参数。但是,当默认的序列化或反序列机制不满足我们的要求时,我们又可以传入更多的参数来定制序列化或反序列化的规则,既做到了接口简单易用,又做到了充分的扩展性和灵活性。
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()
print 'All subprocesses done.'
进程间的通信是通过queue和Pipes实现的
from multiprocessing import Process, Queue
import os, time, random
#写数据进程执行的代码:
def write(q):
for value in ['A', 'B', 'C']:
print 'Put %s to queue...' % value
q.put(value)
time.sleep(random.random())
#读数据进程执行的代码:
def read(q):
while True:
value = q.get(True)
print 'Get %s from queue.' % value
if __name__=='__main__':
#父进程创建Queue,并传给各个子进程:
q = Queue()
pw = Process(target=write, args=(q,))
pr = Process(target=read, args=(q,))
#启动子进程pw,写入:
pw.start()
#启动子进程pr,读取:
pr.start()
#等待pw结束:
pw.join()
#pr进程里是死循环,无法等待其结束,只能强行终止:
pr.terminate()
import threading
#创建全局ThreadLocal对象:
local_school = threading.local()
def process_student():
print 'Hello, %s (in %s)' % (local_school.student, threading.current_thread().name)
def process_thread(name):
# 绑定ThreadLocal的student:
local_school.student = name
process_student()
t1 = threading.Thread(target= process_thread, args=('Alice',), name='Thread-A')
t2 = threading.Thread(target= process_thread, args=('Bob',), name='Thread-B')
t1.start()
t2.start()
t1.join()
t2.join()
在Thread和Process中,应当优选Process,因为Process更稳定,而且,Process可以分布到多台机器上,而Thread最多只能分布到同一台机器的多个CPU上。
>>>import re
#编译:
>>>re_telephone = re.compile(r'^(\d{3})-(\d{3,8})$')
#使用:
>>>re_telephone.match('010-12345').groups()
('010', '12345')
>>>re_telephone.match('010-8086').groups()
('010', '8086')
在python使用正则表达式时,re模块内部会1.编译正则表达式,如果正则表达式的字符串本身不合法,会报错;2.用编译后的正则表达式去匹配字符串。如果一个正则表达式要重复使用几千次,出于效率的考虑,我们可以预编译该正则表达式,接下来重复使用时就不需要编译这个步骤了,直接匹配。
练习题:写一个验证Email地址的正则表达式
#-*- coding: utf-8 -*-
import re
regex = r'^(<\w[\s\w]+>\s)?(\w+[\w+.]*@\w+.(org|com)$)'
#题目一:正则匹配
m = re.compile(regex)
#纯Email地址
if m.match('[email protected]'):
print('match [email protected]')
if m.match('[email protected]'):
print('match [email protected]')
#带名字的Email地址
if m.match(' [email protected]' ):
print('match [email protected]' )
#题目二:提取带名字的Email地址
m_email = m.match(' [email protected]' ).group(2)
print(m_email)
>>> from collections import namedtuple
>>> Point = namedtuple('Point', ['x', 'y'])
>>> p = Point(1, 2)
>>> p.xfrom coll
1
>>> p.y
2
>>> from collections import deque
>>> q = deque(['a', 'b', 'c'])
>>> q.append('x')
>>> q.appendleft('y')
>>> q
deque(['y', 'a', 'b', 'c', 'x'])
>>> from collections import defaultdict
>>> dd = defaultdict(lambda: 'N/A')
>>> dd['key1'] = 'abc'
>>> dd['key1'] # key1存在
'abc'
>>> dd['key2'] # key2不存在,返回默认值
'N/A'
>>> from collections import OrderedDict
>>> d = dict([('a', 1), ('b', 2), ('c', 3)])
>>> d # dict的Key是无序的
{'a': 1, 'c': 3, 'b': 2}
>>> od = OrderedDict([('a', 1), ('b', 2), ('c', 3)])
>>> od # OrderedDict的Key是有序的
OrderedDict([('a', 1), ('b', 2), ('c', 3)])
要内容和顺序完全相同才会视为相等;注意顺序以添加顺序为准,和修改的顺序无关。
1. 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})
>>> import base64
>>> base64.b64encode('binary\x00string')
'YmluYXJ5AHN0cmluZw=='
>>> base64.b64decode('YmluYXJ5AHN0cmluZw==')
'binary\x00string'
>>> import struct
>>> struct.pack('>I', 10240099)
'\x00\x9c@c'
import hashlib
md5 = hashlib.md5()
md5.update('how to use md5 in python hashlib?')
print md5.hexdigest()
>>> import itertools
>>> cs = itertools.cycle('ABC') # 注意字符串也是序列的一种
>>> for c in cs:
... print c
...
'A'
'B'
'C'
'A'
'B'
'C'
...
repeat()负责把一个元素无限重复下去,不过如果提供第二个参数就可以限定重复次数
>>> ns = itertools.repeat('A', 10)
>>> for n in ns:
... print n
...
打印10次'A'
takewhile()函数根据条件判断来截取出一个有限的序列
>>> natuals = itertools.count(1)
>>> ns = itertools.takewhile(lambda x: x <= 10, natuals)
>>> for n in ns:
... print n
...
打印出1到10
chain()可以把一组迭代对象串联起来,形成一个更大的迭代器
for c in itertools.chain('ABC', 'XYZ'):
print c
# 迭代效果:'A' 'B' 'C' 'X' 'Y' 'Z'
groupby()把迭代器中相邻的重复元素挑出来放在一起
>>> for key, group in itertools.groupby('AAABBBCCAAA'):
... print key, list(group) # 为什么这里要用list()函数呢?
...
A ['A', 'A', 'A']
B ['B', 'B', 'B']
C ['C', 'C']
A ['A', 'A', 'A']
imap()和map()的区别在于,imap()可以作用于无穷序列,并且,如果两个序列的长度不一致,以短的那个为准。
>>> for x in itertools.imap(lambda x, y: x * y, [10, 20, 30], itertools.count(1)):
... print x
...
10
40
90
imap()返回一个迭代对象,而map()返回list。当你调用map()时,已经计算完毕
>>> r = map(lambda x: x*x, [1, 2, 3])
>>> r # r已经计算出来了
[1, 4, 9]
itertools模块提供的全部是处理迭代功能的函数,它们的返回值不是list,而是迭代对象,只有用for循环迭代的时候才真正计算
1. XML:操作XML有两种方法:DOM和SAX。DOM会把整个XML读入内存,解析为树,因此占用内存大,解析慢,优点是可以任意遍历树的节点。SAX是流模式,边读边解析,占用内存小,解析快,缺点是我们需要自己处理事件。
正常情况下,优先考虑SAX,因为DOM实在太占内存。
#hello.py
def application(environ, start_response):
start_response('200 OK', [('Content-Type', 'text/html')])
return 'Hello, %s!
' % (environ['PATH_INFO'][1:] or 'web')
#server.py
#从wsgiref模块导入:
from wsgiref.simple_server import make_server
#导入我们自己编写的application函数:
from hello import application
#创建一个服务器,IP地址为空,端口是8000,处理函数是application:
httpd = make_server('', 8000, application)
print "Serving HTTP on port 8000..."
#开始监听HTTP请求:
httpd.serve_forever()
from flask import Flask
from flask import request
app = Flask(__name__)
@app.route('/', methods=['GET', 'POST'])
def home():
return 'Home
'
@app.route('/signin', methods=['GET'])
def signin_form():
return ''''''
@app.route('/signin', methods=['POST'])
def signin():
# 需要从request对象读取表单内容:
if request.form['username']=='admin' and request.form['password']=='password':
return 'Hello, admin!
'
return 'Bad username or password.
'
if __name__ == '__main__':
app.run()
from flask import Flask, request, render_template
app = Flask(__name__)
@app.route('/', methods=['GET', 'POST'])
def home():
return render_template('home.html')
@app.route('/signin', methods=['GET'])
def signin_form():
return render_template('form.html')
@app.route('/signin', methods=['POST'])
def signin():
username = request.form['username']
password = request.form['password']
if username=='admin' and password=='password':
return render_template('signin-ok.html', username=username)
return render_template('form.html', message='Bad username or password', username=username)
if __name__ == '__main__':
app.run()
得将运行的xxx.py文件放到路径C:\Users\Administrator\myvir\Scripts中,在cmd中输入指令python xxx.py启动,然后在浏览器中输入地址http://localhost:5000/才可以访问。
from gevent import monkey; monkey.patch_socket()
import gevent
def f(n):
for i in range(n):
print gevent.getcurrent(), i
g1 = gevent.spawn(f, 5)
g2 = gevent.spawn(f, 5)
g3 = gevent.spawn(f, 5)
g1.join()
g2.join()
g3.join()
主要参考学习:
廖雪峰的官方网站:
https://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000