classA: deffoo(self): print("in A::foo") classB(A): pass b = B() b.foo()
多态
1 2 3 4 5 6 7 8 9 10 11 12 13
classA: deffoo(self): print("in A::foo") classB(A): deffoo(self): print("in B::foo") classC: deffoo(self): print("not subclass of A/B") b = B() b.foo() isinstance(b, B) isinstance(b, A)
λ 表达式
• 注意 :Python的lambda表达 式 不 能 换 行
1 2 3 4
inc = lambda x: x + 1 add = lambda x, y: x + y inc(5) add(10, 20)
列表推导
1 2 3 4 5
[i*2for i inrange(10)] [i*2for i inrange(10) if i % 2 == 0] colours = ["red", "green", "yellow", "blue"] things = ["house", "car", "tree"] combined = [(x,y) for x in colours for y in things]
>>> x, y, z = t >>> x, y = y, x >>> x = (1, 2, 3, [4, 5]) >>> x[3] += [6] --------------------------------------------------------------------------- TypeError Traceback (most recent call last) <ipython-input-34-1b7fadc4e686> in <module>() ----> 1 x[3] += [6] TypeError: ’tuple’ object does not support item assignment >>> x (1, 2, 3, [4, 5, 6])
>>> basket = {’apple’, ’orange’, ’apple’, ’pear’, ’orange’, ’banana’} >>> print(basket) # show that duplicates have been removed {’orange’, ’banana’, ’pear’, ’apple’} >>> ’orange’ in basket # fast membership testing True >>> ’crabgrass’ in basket False >>> # Demonstrate set operations on unique letters from two words ... >>> a = set(’abracadabra’) >>> b = set(’alacazam’) >>> a # unique letters in a {’a’, ’r’, ’b’, ’c’, ’d’} >>> a - b # letters in a but not in b {’r’, ’d’, ’b’} >>> a | b # letters in a or b or both {’a’, ’c’, ’r’, ’d’, ’b’, ’m’, ’z’, ’l’} >>> a & b # letters in both a and b {’a’, ’c’} >>> a ^ b # letters in a or b but not both {’r’, ’d’, ’b’, ’m’, ’z’, ’l’} >>> a = {x for x in ’abracadabra’ if x notin ’abc’} >>> a {’r’, ’d’}
HTTP 基础知识
• GET 向指定的资源发出“显示”请求。使用 GET 方法应该只用在读取数据,而不应当被用于产生“副作用”的操作中,例如在 WebApplication 中。其中一个原因是 GET 可能会被网络蜘蛛等随意访问。 • HEAD 与 GET 方法一样,都是向服务器发出指定资源的请求。只不过服务器将不传回资源的本文部分。它的好处在于,使用这个方法可以在不必传输全部内容的情况下,就可以获取其中“关于该资源的信息”(元信息或称元数据)
r = requests.post(’http://httpbin.org/post’, data = {’key’:’value’})
正规式
1 2 3 4 5 6 7 8
>>> import re >>> re.findall(r’\bf[a-z] * ’, ’which foot or hand fell fastest’) [’foot’, ’fell’, ’fastest’] >>> re.sub(r’(\b[a-z]+) \1’, r’\1’, ’cat in the the hat’) ’cat in the hat’ //查找所有HTML链接 >>> re.findall("href=’(. * ?)’", html) [’a.html’, ’b.html’]
从文档中找到所有 <a> 标签的链接: for link in soup.find_all(’a’): print(link.get(’href’)) # http://example.com/elsie # http://example.com/lacie # http://example.com/tillie
Beautiful Soup对象
Beautiful Soup 将复杂 HTML 文档转换成一个复杂的树形结构, 每个节点都是 Python 对象, 所有对象可以归纳为 4 种: Tag , NavigableString ,BeautifulSoup , Comment .
Tag 有很多方法和属性, 在遍历文档树和搜索文档树中有详细解释. 现在介绍一下 tag 中最重要的属性: name 和 attributes
每个 tag 都有自己的名字, 通过.name 来获取:
一个 tag 可能有很多个属性. tag 有一个“class”的属性, 值为“boldest”. tag 的属性的操作方法与字典相同:
也可以直接”点”取属性, 比如: .attrs :
字符串常被包含在 tag 内.Beautiful Soup 用 NavigableString 类来包装tag 中的字符串:
通过 tag的.children 生成器, 可以对 tag的子节点进行循环: for child in title_tag.children: print(child) # The Dormouse’s story 继续分析文档树, 每个 tag或字符串都有父节点: 被包含在某个 tag 中通过.parent 属性来获取某个元素的父节点. 在例子“爱丽丝”的文档中,<head> 标签是 <title> 标签的父节点: title_tag = soup.title title_tag # <title>The Dormouse’s story</title> title_tag.parent # <head><title>The Dormouse’s story</title></head> 文档 title 的字符串也有父节点:<title> 标签 title_tag.string.parent # <title>The Dormouse’s story</title> 文档的顶层节点比如 <html> 的父节点是 BeautifulSoup 对象: html_tag = soup.html type(html_tag.parent) # <class ’bs4.BeautifulSoup’> BeautifulSoup 对象的.parent 是 None: print(soup.parent) # None 通过元素的.parents 属性可以递归得到元素的所有父辈节点, 下面的例子使用了.parents 方法遍历了 <a> 标签到根节点的所有节点. link = soup.a link # <a class="sister" href="http://example.com/elsie" id="link1">Elsie</a> for parent in link.parents: if parent is None: print(parent) else: print(parent.name) # p # body # html # [document] # None
last_a_tag = soup.find("a", id="link3") last_a_tag # <a class="sister" href="http://example.com/tillie" id="link3">Tillie</a> last_a_tag.next_sibling # ’; and they lived at the bottom of a well.’
import re 下面例子中找出所有以 b 开头的标签 for tagin soup.find_all(re.compile("^b")): print(tag.name) # body # b 下面代码找出所有名字中包含”t”的标签: for tagin soup.find_all(re.compile("t")): print(tag.name) # html # title
tag 的 class 属性是多值属性. 按照 CSS 类名搜索 tag 时, 可以分别搜索tag 中的每个 CSS 类名: css_soup = BeautifulSoup(’<p class="body strikeout"></p>’) css_soup.find_all("p", class_="strikeout") # [<p class="body strikeout"></p>] css_soup.find_all("p", class_="body") # [<p class="body strikeout"></p>]
通过 text 参数可以搜搜文档中的字符串内容. 与 name 参数的可选值一样, text 参数接受字符串, 正则表达式, 列表, True . 看例子: soup.find_all(text="Elsie") # [u’Elsie’] soup.find_all(text=["Tillie", "Elsie", "Lacie"]) # [u’Elsie’, u’Lacie’, u’Tillie’] soup.find_all(text=re.compile("Dormouse")) [u"The Dormouse’s story", u"The Dormouse’s story"]
虽然 text 参数用于搜索字符串, 还可以与其它参数混合使用来过滤tag.Beautiful Soup 会找到.string 方法与 text 参数值相符的 tag. 下面代码用来搜索内容里面包含“Elsie”的 <a> 标签: soup.find_all("a", text="Elsie") #[<a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>]
find_all() 和 find() 只搜索当前节点的所有子节点, 孙子节点等.find_parents() 和 find_parent() 用来搜索当前节点的父辈节点, 搜索方法与普通 tag 的搜索方法相同, 搜索文档搜索文档包含的内容. 我们从一个文档中的一个叶子节点开始: a_string = soup.find(text="Lacie") a_string # u’Lacie’ a_string.find_parents("a") # [<a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>] a_string.find_parent("p") # <p class="story">Once upon a time there were three little sisters; and their names were # <a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>, # <a class="sister" href="http://example.com/lacie" id="link2">Lacie</a> and # <a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>; # and they lived at the bottom of a well.</p>
for html in glob.glob("*.html"): handle = open(html) soup = bs4.BeautifulSoup(handle.read()) for script in soup.find_all("script"): script.decompose() handle.close() handle = open(html, "w") handle.write(soup.prettify()) handle.close()
import sqlite3 conn = sqlite3.connect(’example.db’) # or use :memory: conn_memory = sqlite3.connect(’:memory:’)
c = conn.cursor() # Create table c.execute(’’’CREATETABLE stocks (datetext, trans text, symbol text, qty real, price real)’’’) # Insert a row of data c.execute("INSERT INTO stocks VALUES (’2006-01-05’,’BUY’,’RHAT’,100,35.14)") # Save (commit) the changes conn.commit() # We can also close the connection if we are done with it. # Just be sure any changes have been committed or they will be lost. conn.close()
防止sql注入
1 2 3 4 5 6 7 8 9 10 11 12 13
# Never do this -- insecure! symbol = ’RHAT’ c.execute("SELECT * FROM stocks WHERE symbol = ’%s’" % symbol)
# Do this instead t = (’RHAT’,) c.execute(’SELECT * FROM stocks WHERE symbol=?’, t) print(c.fetchone()) # Larger example that inserts many records at a time purchases = [(’2006-03-28’, ’BUY’, ’IBM’, 1000, 45.00), (’2006-04-05’, ’BUY’, ’MSFT’, 1000, 72.00), (’2006-04-06’, ’SELL’, ’IBM’, 500, 53.00),] c.executemany(’INSERT INTO stocks VALUES (?,?,?,?,?)’, purchases)
移动 • gg:gotofirstline • G: gotolastline • 0: gotofirst column • ˆ: gotofirst non-blank column • $: gotolast column • w:next word • W: next Word • e: end of word • E: end of Word • fa:finda in current line • Fa:finda in current line backward • ta:find till before a • Ta:find till before a backward 单独使用命令 • i: insert • I: insert at front • a:append • A: append after end • o: appendnewline • O: insertnewline 命令 • c: Change • d: Delete • y: Yank • gU: Upper case • gu: Lower case ... 文本对象 • aw:a word • iw: inner word • ab:a bracket • ib: inner bracket • at:atag 命令 +移动/文本对象 • dj: delete current and the next lines • y0: copyto the line head • ciw:change inner word • dab:deletea bracket • gUit:change inner tagto lower case 相对高阶功能 • :%s/re.pattern/replace/g 全局替换 • :g/re.pattern/d 删除匹配行 • :h! E478 Don’t panic • :h 42
#initialization $ git init #configuration $ git config --global user.name "Your Name" $ git config --global user.email "[email protected]" # First commit $ git add example.py # adds file to the staging area $ git commit -m "First commit" # Second commit $ git add another.py # adds file to the staging area $ git commit -m "Second commit"
• By default you are on the "master" branch • To create a new branch and switch to it: $ git branch branchName $ git checkout branchName • Merge changes back to master branch $ git checkout master $ git merge branchName • To delete branch $ git branch -d branchName
怎么使用分支
• Master branch is always clean and working • When I want to try a new idea, create a branch • Work and commit to that branch until code is clean and working • Switch back to master and merge branch into master • Delete branch
• Any branch can be merged to any other branch(Careful, this might get confusing) • Must commit before switching branches • Unless you add it, a file will not be tracked. • If you want to ignore a file, add it to the .git/info/exclude file. • To revert a file back to it’s state at the last commit: git checkout fileName • To revert the entire repo to it’s state at the last commit: git reset –hard HEAD • CAREFULL! You’ll loose all your changes since your last commit!
单元测试
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
import unittest classTestStringMethods(unittest.TestCase): deftest_upper(self): self.assertEqual(’foo’.upper(), ’FOO’) deftest_isupper(self): self.assertTrue(’FOO’.isupper()) self.assertFalse(’Foo’.isupper()) deftest_split(self): s = ’hello world’ self.assertEqual(s.split(), [’hello’, ’world’]) # check that s.split fails when the separator is not a string with self.assertRaises(TypeError): s.split(2) if __name__ == ’__main__’: unittest.main()
test_isupper (__main__.TestStringMethods) ... ok test_split (__main__.TestStringMethods) ... ok test_upper (__main__.TestStringMethods) ... ok
方法——检测条件 assertAlmostEqual(a, b) ——round(a-b, 7) == 0 assertNotAlmostEqual(a, b)——round(a-b, 7) != 0 assertGreater(a, b)—— a > b assertGreaterEqual(a, b)—— a >= b assertLess(a, b)—— a < b assertLessEqual(a, b) ——a <= b assertRegex(s, r)—— r.search(s) assertNotRegex(s, r)—— not r.search(s)
@app.route(’/’) def index(): return ’Index Page’ @app.route(’/hello’) def hello(): return ’Hello, World’ @app.route(’/user/<username>’) def show_user_profile(username): # show the user profile for that user return ’User %s’ % username @app.route(’/post/<int:post_id>’) def show_post(post_id): # show the post with the given id, the id is an integer return ’Post %d’ % post_id from flask import request @app.route(’/login’, methods=[’GET’, ’POST’]) def login(): if request.method == ’POST’: do_the_login() else: show_the_login_form()
from flask import Flask, session, redirect, url_for, escape, request app = Flask(__name__) @app.route(’/’) def index(): if ’username’ insession: return ’Logged in as %s’ % escape(session[’username’]) return ’You are not logged in’ @app.route(’/login’, methods=[’GET’, ’POST’]) def login(): if request.method == ’POST’: session[’username’] = request.form[’username’] >>> importos >>> os.urandom(24) ’\xfd{H\xe5<\x95\xf9\xe3\x96.5\xd1\x01O<!\xd5\xa2\xa0\x9fR"\xa1\xa8’ Just take that thing and copy/paste it into your code
@app.route("/") defroot(): return redirect("index") @app.route("/index") defindex(): return"""\ <html> <body> <p> This is the index page</p> </body> </html>"""
import matplotlib.pyplot as plt import numpy as np # Data for plotting t = np.arange(0.0, 2.0, 0.01) s = 1 + np.sin(2 * np.pi * t) # Note that using plt.subplots below is equivalent to using # fig = plt.figure and then ax = fig.add_subplot(111) fig, ax = plt.subplots() ax.plot(t, s) ax.set(xlabel=’time (s)’, ylabel=’voltage (mV)’, title=’About as simple as it gets, folks’) ax.grid() fig.savefig("test.png") plt.show()
histogram (hist) function直方图
1 2 3 4 5 6 7 8 9 10 11 12 13
import numpy as np import matplotlib.pyplot as plt np.random.seed(19680801) mu, sigma = 100, 15 x = mu + sigma * np.random.randn(10000) # the histogram of the data n, bins, patches = plt.hist(x, 50, normed=1, facecolor=’g’, alpha=0.75) plt.xlabel(’Smarts’) plt.ylabel(’Probability’) plt.title(’Histogram of IQ’) plt.axis([40, 160, 0, 0.03]) plt.grid(True) plt.show()
Basic pie chart
1 2 3 4 5 6 7 8 9 10
import matplotlib.pyplot as plt # Pie chart, where the slices will be ordered and plotted counter-clockwise: labels = ’Frogs’, ’Hogs’, ’Dogs’, ’Logs’ sizes = [15, 30, 45, 10] explode = (0, 0.1, 0, 0) # only "explode" the 2nd slice (i.e. ’Hogs’) fig1, ax1 = plt.subplots() ax1.pie(sizes, explode=explode,labels=labels,autopct=’%1.1f%%’, shadow=True,startangle=90) ax1.axis(’equal’) # Equal aspect ratio ensures that pie is drawn as a circle. plt.show()
Fill plot demo
1 2 3 4 5 6 7 8 9 10
import numpy as np import matplotlib.pyplot as plt x = np.linspace(0, 1, 500) y = np.sin(4 * np.pi * x) * np.exp(-5 * x) fig, ax = plt.subplots() ax.fill(x, y, zorder=10) ax.grid(True, zorder=5) x = np.linspace(0, 2 * np.pi, 500) y1 = np.sin(x) y2 = np.sin(3 * x)
Log Demo
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
import numpy as np import matplotlib.pyplot as plt # Data for plotting t = np.arange(0.01, 20.0, 0.01) # Create figure fig, ((ax1, ax2), (ax3, ax4)) = plt.subplots(2, 2) # log y axis ax1.semilogy(t, np.exp(-t / 5.0)) ax1.set(title=’semilogy’) ax1.grid() # log x axis ax2.semilogx(t, np.sin(2 * np.pi * t)) ax2.set(title=’semilogx’) ax2.grid() # log x and y axis ax3.loglog(t, 20 * np.exp(-t / 10.0), basex=2)
Legend using pre-defined labels
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
import numpy as np import matplotlib.pyplot as plt # Make some fake data. a = b = np.arange(0, 3, .02) c = np.exp(a) d = c[::-1] # Create plots with pre-defined labels. fig, ax = plt.subplots() ax.plot(a, c, ’k--’, label=’Model length’) ax.plot(a, d, ’k:’, label=’Data length’) ax.plot(a, c + d, ’k’, label=’Total message length’) legend = ax.legend(loc=’upper center’, shadow=True, fontsize=’x-large’) # Put a nicer backgroundcolor on the legend. legend.get_frame().set_facecolor(’#00FFCC’) plt.show()
XKCD-style sketch plots
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
import matplotlib.pyplot as plt import numpy as np with plt.xkcd(): # Based on "Stove Ownership" from XKCD by RandallMonroe # http://xkcd.com/418/ fig = plt.figure() ax = fig.add_axes((0.1, 0.2, 0.8, 0.7)) ax.spines[’right’].set_color(’none’) ax.spines[’top’].set_color(’none’) plt.xticks([]) plt.yticks([]) ax.set_ylim([-30, 10]) data = np.ones(100) data[70:] -= np.arange(30) plt.annotate( ’THEDAYIREALIZED\nI COULDCOOKBACON\nWHENEVER IWANTED’, xy=(70, 1), arrowprops=dict(arrowstyle=’->’), xytext=(15, -10))
--dbpath arg directory for datafiles - defaults to /data/db --port arg specify port number - 27017 by default --replSet arg arg is <setname> --configsvr declare this is a config db of a cluster; default port 27019; default dir /data/configdb --journal enable journaling --nojournal disable journaling (journaling is on by default for 64 bit) --logpath arg log file to send write to instead of stdout - has to be a file, not directory
import pymongo from pymongo import MongoClient client = MongoClient() # Get the sampleDB database db = client.sampleDB # equivalently, use db = client[’sampleDB’] coll = db.sampleCollection # equivalently, use coll = db[’sampleCollection’]