Python3 - 復習(update to Day6)

# 第一優(yōu)先級規(guī)則聲明:

# 除了夢境万伤,每一個意識主進程都必須與一個身體參與的機械進程相匹配,否則結束意識主進程呜袁。如學習python同時必須伴有記筆記敌买、敲代碼等機械進程,學習英語必須伴有朗讀阶界、聽說虹钮、查字典、查語法書等機械進程跟隨膘融,拆解問題必須在紙上或iPad上實時記錄意識的每一次嘗試芙粱。

如果身體狀況或是客觀情況不允許有機械進程存在,請轉入其他進程氧映,如注意力恢復(閉目養(yǎng)神春畔、睡覺)或是娛樂進程(健身、看電影等)岛都。

# 此優(yōu)先級將在每一個意識進程前聲明律姨。


Day1:

Why Python 3.5(意義賦予):?

- Life is short and I need python.?

- 以前沒有編程基礎,只有Linux和MySQL的基礎臼疫。

- 每天能抽出時間不多择份。

- 工作的強烈需求。

- Python大量的第三方庫

- 開源社區(qū)的強力支持

- 3.5總比2.7強烫堤,長遠來看

Installation: 略

IDLE: Pycharm

編碼聲明:

#!/usr/bin/env python3

# -*- coding: utf-8 -*-

也可以借助pycharm右下角的編碼來修改荣赶,或是notepad++的encoding-轉為utf-8無BOM格式

I/O:

print()

print在python3.5中正式成為函數(shù),允許用“鸽斟,”分隔多個字符串拔创,也接受數(shù)學計算

input()

接受用戶的輸入,同時也接受()內插入內容湾盗。

如果要規(guī)范輸入的內容伏蚊,可以用這種方法

int(input(...))

代碼風格:

python使用縮進來組織代碼塊,請移動使用4個空格的縮進(pycharm會對不規(guī)范的代碼風格給出波浪下劃紅線的warning)

數(shù)據(jù)類型和變量:

類型在python中極其重要格粪,最常見的報錯就是“你不能對xx類型進行xx操作”躏吊!

整數(shù)integer:正整數(shù),負整數(shù)帐萎,0

浮點數(shù)float:小數(shù)(叫浮點數(shù)是因為用科學計數(shù)法表示比伏,一個浮點數(shù)的小數(shù)點位置可變),存在四舍五入的誤差疆导。

字符串string:單引號或者雙引號括起來的任意文本(里邊有特殊符號請轉義)赁项。需要轉義的入托太多,用r'string' 來帶來一大堆的\。計算string多長悠菜,用len()

布爾值:True/False 1/0舰攒。如果True/False拼錯了或者大小寫出錯,并不會識別為布爾值(在pycharm中識別成為橙色)悔醋∧η裕可加減乘除,可and/or/not芬骄。

空值:None

變量賦值符號是“=”猾愿,等于號是‘==’,所以請正確理解

x = 3

x = x + 3

賦值過程依照語句順序而來账阻。

常量:不能變的變量

Python支持多種數(shù)據(jù)類型蒂秘,可以把任何數(shù)據(jù)都看成一個對象,

- 變量就是在程序中用來指向這些數(shù)據(jù)對象的淘太。

- 對變量賦值就是把數(shù)據(jù)和變量給關聯(lián)起來

字符串和編碼

Python3支持中文

1個中文字符經(jīng)過utf-8編碼后占用3個字節(jié)姻僧,一個英文字符占用1個字節(jié)。

格式化:

格式化的使用頻率非常高琴儿,其應用主要在于占位符的使用

%s 字符串(如果不清楚數(shù)據(jù)類型段化,可以用%s來接受一切)

%d 整數(shù) (整數(shù)接受%002d這種表達,來填充位數(shù))

%f 浮點數(shù)(浮點數(shù)接受%.3f這種表達造成,來截取位數(shù))

%s 字符串

%x 十六進制整數(shù)

%%來表示正常的百分比

條件判斷和循環(huán)

計算機可以自動化,其中最重要的原因就是因為有條件判斷和循環(huán)

條件判斷

(注意冒號P巯)

if <條件判斷1>:

<執(zhí)行1>

elif <條件判斷2>:

<執(zhí)行2>

elif <條件判斷3>:

<執(zhí)行3>

else:

<執(zhí)行4>

if 語句從上往下判斷晒屎,如果某個判斷是True,執(zhí)行完畢就不執(zhí)行了缓升。

循環(huán)

1. 遍歷式循環(huán)(for x in ...)

for i in ... :

.......

2. while循環(huán): 只要條件滿足鼓鲁,就不斷循環(huán)(類似scratch里用if和forever在循環(huán)中結合的用法)

不過代碼會出現(xiàn)死循環(huán)(如果寫的有問題),就像Human Resource Machine里小人不停地搬箱子港谊。這時候可用ctrl+c結束(與linux一致)

List和Tuple:

list: 列表骇吭,python內置。是一種有序的元素集合(或者說容器)歧寺,元素是什么數(shù)據(jù)類型都可以可以隨時添加和刪除其中的元素()燥狰。同樣,可以用len()獲取list中的個數(shù)(string也能進行l(wèi)en()操作斜筐,因為string本質上也是list)

訪問list中的每個元素需要通過索引(索引:從0開始的序列號)龙致,格式為list[1],超出索引報錯IndexError顷链。也可以通過負數(shù)的索引號來倒取元素

支持list.append()目代,追加元素到末尾

支持list.insert(index, 'element'),插入元素到指定位置。

支持空List榛了,且len(List)為0

因為list是可變的在讶,所以才可以list.sort()來排序

Tuple: 不可變的list是tuple, 不能append/insert操作,可以用索引取值霜大,但不能再次賦值了真朗。

tp = ()

tp = (1,) 如果要定義的是tuple, 務必通過括號內逗號來消除歧義。


Dict和Set

dict

其他語言中也稱之為map, 使用key-value存儲僧诚,優(yōu)點是查找速度極快遮婶。

d = {'Michael': 95, 'Bob': 75, 'Tracy': 85}

為什么查找dict特別快,比查找list要開快得多呢? list查詢是遍歷查詢湖笨,從第一個翻到最后一個旗扑,查詢速度直接取決于list大小。dict直接計算出對應的位置慈省,直接取出臀防,非常快边败。根據(jù)什么算出來呢袱衷?就是key-value。

dict有個缺點:占用內存大笑窜。正因為如此致燥,拿空間換時間,占用空間大排截,所以查找速度快嫌蚤。

既然是通過Key來查找,那么key一定要是不可變對象断傲。通過key來計算位置的算法脱吱,就叫做hash算法。

要保證hash正確性认罩,那么key就不可變(如字符串和整數(shù))箱蝠。但是list這種就是可變的,就不能作為Key垦垂。這時候報錯就是Typeerror: unhasable type

d['barry'] = 90 這個過程跟給變量賦值沒什么區(qū)別宦搬,相當于給key這個變量賦值。

調用不存在key的乔外,會返回keyerror床三。

怎么判斷Key在不在dict里呢?

1. 可以通過key in dict來判斷杨幼,會返回布爾值撇簿。

2. 也可以d.get['barry']聂渊。如果key不存在,可以返回None, 或者自己制定的value

d.get['key', value]

要刪除一個Key四瘫,就d.pop('key').

既然是一個字典dict汉嗽,那么哪一對key-value在前面是無所謂的。也就是說找蜜,無所謂key-value的順序饼暑,什么時候放入的不重要。

set

set和dict唯一的區(qū)別就是洗做,只存儲Key弓叛,不存儲value。因為dict內部key就不能重復诚纸,所以set里邊的元素也不能重復(即使重復撰筷,也會自動會被過濾)。一樣畦徘,單純的key集合也無所謂先后順序毕籽。

這樣,才形成了set數(shù)學意義上的無序+無重復元素的集合井辆。

s = set(list)

list = [1, 2, 3]

可以通過add(key)來添加元素(key)到set當中关筒,重復添加倒是可以,不過還是會被過濾掉杯缺。

可以通過remove(key)來刪除元素蒸播。

可以s1 & s2 取交集,s1 | s2取并集夺谁。(跟linux非常相似)

可變和不可變

不可變對象(如string)調用對象自身的任意方法廉赔,也不會改變對象自身的內容。相反這些方法會創(chuàng)建新的對象然后返回匾鸥,這樣就保證了不可變對象的不便。

函數(shù)

函數(shù)是啥碉纳?函數(shù)本質上就是把一些現(xiàn)成的功能寫成一個封裝的包(跟第三方庫非常像)勿负,調用即可。也就是說劳曹,函數(shù)可以自己寫奴愉,也可以用寫好的現(xiàn)成的。比如不用每次都寫平方或者指數(shù)不需要每次都寫x * x...這種底層寫法铁孵。很多函數(shù)內置锭硼,很多函數(shù)在可調用庫。(import大法好M扇啊)

抽象

抽象是啥檀头?每次都還原成最底層代碼煩不煩轰异?那你需要抽象!

抽象可以使我們每次都調用一些聚合過的概念暑始,如求和西格瑪符號搭独。

有好多內置函數(shù)(build-in functions)筷屡,可以直接調用鸡捐。(至少讀一遍,知道都有啥闹司。Python真的是能夠做到嗤朴,你能想到的函數(shù)配椭,99%都有之前人寫過,stack overflow/github/python各種庫雹姊,多讀讀)

Built-in functions:

數(shù)學運算類:

abs(x) 取x的絕對值

divmod(a, b) 返回(商股缸,余數(shù))

float(x) 取浮點數(shù) ;bool() 取布爾值容为; str()轉換成字符乓序; int() 轉換成正整數(shù)

int(x, base=n) 取整數(shù),base是可選的坎背,表示進制) 也可以long(x, base=n) 轉Long

pow(x, y, z) x的y次方(如果z存在替劈,那么再對結果取模)

range([start], stop[, step]) 產(chǎn)生一個序列,規(guī)定結束得滤,可以規(guī)定開始和步長陨献。

round(x[,n) 四舍五入,可以規(guī)定n位數(shù)

sum(iterable[, start]) 對可迭代對象求和

集合操作符

iter(o[, sentinel) 生成一個對象的迭代器懂更,第二個參數(shù)表示分隔符(眨业?)

max() min() 最大最小值

dict() set() list() str() tupe()創(chuàng)建

sorted(iterable, key=None, reverse=True/False) 排序

all(iterable) 集合中的所有 元素都為真時候為真,空串返回為真沮协。

any(iterable) 任一為真就為真

IO操作

input() 獲取用戶輸入

open(file_name, mode) mode可以是'r', 'w', 'a'

print() 打印函數(shù)

神器

help()

函數(shù)

自己動手寫函數(shù)

def my_abs(x):

if x > = 0:

return x

else:

return -x

邏輯是: 執(zhí)行到return就結束了龄捡。沒有return,函數(shù)執(zhí)行完畢慷暂,返回None

如果某一個步驟沒想好聘殖,還可以直接pass(放過),占著位置

一個函數(shù)的功能完善行瑞,包括三方面的完善: stdin, stdout, stderror奸腺。所以如果我們要自己定義一個完善的函數(shù),必須包括這三個方面血久。要不然調用函數(shù)錯誤突照,都不知道為什么錯誤。

def my_abs(x):

if not isinstace(x, (int, float)):

raise TypeError(‘bad operand')

if x>= 0:

return x

if x < 0:

return -x

(isinstance(x, type)是判斷x是否為type的函數(shù))

很多函數(shù)都return一個值氧吐,那么可以return多個值么讹蘑?可以末盔,但是返回的本質上是個tuple

比如剛剛學到的科學計算函數(shù)divmod(x, y), 返回的就是兩個值(商,余數(shù))衔肢,但是如果你去嘗試type()庄岖,就會看到這是一個tuple

type(divmod(5, 2)

Out: tuple

函數(shù)的參數(shù)

對于日常使用來說,因為python大量的build-in functions和變態(tài)的import功能角骤,我們非常少去自己寫一個函數(shù)隅忿。更多的是理解自己調用的函數(shù)該如何使用——核心就在于,函數(shù)的參數(shù)的了解和使用邦尊。日常使用的大量報錯都是因為:對于某個函數(shù)是否能夠接受某種方式傳入的某個參數(shù)的不確定背桐,導致大量debug時間(隨機嘗試不是個長期解決方案,雖然能夠不斷地返回error信息以供調試)

1. 位置參數(shù)

簡單理解蝉揍,位置固定的參數(shù)链峭,如pow(x, y)計算x的y次方。直接寫pow(3, 2)不再需要規(guī)定哪個是x, 哪個是y

2. 默認參數(shù): 大大減輕了函數(shù)調用的難度

比如range(5)又沾,實際上start位置的參數(shù)就被忽略了弊仪,只傳入了stop。但是仍然能運行杖刷,因為range()內部規(guī)定了start默認為0励饵。

也可以不接受默認設定,自己規(guī)定:range(2, 5)

但是在自己定義函數(shù)的時候滑燃,必選參數(shù)在前役听,默認參數(shù)在后。且默認參數(shù)指向不可變對象(不能指向個變量什么的!)

3. 可變參數(shù)

并不規(guī)定要傳入幾個參數(shù)表窘,多少個都行典予。define的時候加個星號即可

def calc(*numbers):

sum = 0

for n in numbers:

sum = sum + n * n

return sum

這樣numbers里邊有多少個都沒問題。

如果已經(jīng)有個numbers集合(list或者tuple)咋辦乐严?

num = [1, 2, 3]

calc(*num)

這種寫法瘤袖,就是把num這個list中所有元素都傳入calc()進行計算。如果不加*會咋樣昂验?

TypeError: can't multiply sequence by non-int of type 'list'

原理上孽椰,可變參數(shù)允許你傳入 0 個或任意個參數(shù),這些可變參數(shù)在函數(shù)調用時自動組裝為一個 tuple凛篙。

4. 關鍵字參數(shù)

def person(name, age, **kw):

print('name:', name, 'age:', age, 'other:', kw)

除了規(guī)定的name和age, 還接受擴展性的其他參數(shù)。這就被稱為關鍵字參數(shù)

比如用戶除了必填項之外栏渺,還愿意提供其他參數(shù)呛梆,那么就可以通過關鍵字參數(shù)來擴展。

5. 命名關鍵字參數(shù)(限制了可擴展的關鍵字)

def person(nama, age, *, city, job)

這里的星號后邊的city和job就是命名關鍵字參數(shù)磕诊,也就是限定了的關鍵字參數(shù)填物。(不加星號纹腌,就變成了位置參數(shù))

語法風格

**args: 可變參數(shù),接受的是一個tuple

**kw: 關鍵字參數(shù)滞磺,kw接收的是一個dict

可變參數(shù)既可以直接傳入func(1, 2, 3), 又可以先組裝list或tuple升薯,再通過**args傳入func(*(1, 2, 3))

關鍵字參數(shù)既可以直接傳入 func(a=1, b=2), 又可以先組裝dict, 再通過**kw傳入 func(**{'a': 1, 'b': 2})

切片

list切片 L[1:3]這種方式,包前不包后击困。也可以L[:3]或者L[2:]涎劈。L[:]就是區(qū)這個List本身

實際上,切片的規(guī)則是list[start:stop:step]

list的切片結果是List阅茶,tuple的切片結果是tuple蛛枚。

string也是一種List

迭代:

通過for循環(huán)來遍歷list或是tuple或是其他可迭代對象,這邊遍歷我們稱為迭代iteration脸哀。

python中蹦浦,迭代是通過for...in完成的。

像dict這種類型撞蜂,默認迭代的是key盲镶。想迭代value, 可以for value in d.values()。同時要迭代key和value, 可以for k, v in d.items()

只要是可迭代對象蝌诡,就可迭代溉贿。判斷是否是可迭代對象,方法是

from collections import Iterable

isinstance('abc', Iterable) 前面我們學過了isinstance函數(shù)

列表生成式List comprehesions

顧名思義送漠,就是為了生成List的(list幾乎是應用最為廣泛的類型) [x * x for x in range(1, 11)]

要生成的元素放在前面顽照,后邊跟for循環(huán)(其實就是for循環(huán)的一種簡寫)

還可以加上if(但是不接受else)

x * x for x in range(1, 11) if x % 2 ==0

m + n for m in 'ABC' for n in 'XYZ'

利用這個列表生成式,可以生成非常簡介的代碼闽寡,比如生成當前目錄下所有的文件名稱

import os

[d for d in os.list('.')]

生成器generator

列表生成式雖然生成方便(一個規(guī)則+for循環(huán)[+if語句])代兵,但是問題也很明顯。

你生成辣么大的列表爷狈,占著內存植影,留著過年么?又不見得全都用得上涎永!

這時候你就需要個generator, 也就是 邊生成思币,邊循環(huán),邊計算羡微。

符號上跟列表生成式的區(qū)別只有一個

List = [x * x for x in range(10)]

Generator = (x * x for x in range(10))

對谷饿,沒看錯,就是把中括號變成了小括號妈倔,就從list變成了generator博投。(如果你去type()他們,會看到區(qū)別)盯蝴。

調用列表當然很簡單毅哗,怎么調用generator呢听怕。怎么個生成法呢?

用next(generator)來調用虑绵,調用一次生成一次尿瞭。也就是每次next(generator)結果都不一樣,next()到最后一步翅睛,拋出Stopiteration錯誤声搁。不過你也看出來了,也不能每次都next()宏所,啥時候是個頭八盅蕖?(實際上幾乎用不上next())

所幸爬骤,一個generator仍然能被for循環(huán)調用充石。

for n in generator:
? ? print(n)

那么問題來了:挖掘機技術哪家強?如果列表生成式這種簡單的結構霞玄,描述不了一個generator的算法怎么辦骤铃?(當然能看出來,列表生成式雖然入手容易坷剧,不過干不了太復雜的事情——你看它那個傻樣連else都不接受

好消息惰爬!好消息!用定義函數(shù)的方法就可以創(chuàng)建generator啦惫企!不過要把return改成yield撕瞧。(等用到再來填坑)

迭代器Iterator

前面說到,可直接作用于for循環(huán)的數(shù)據(jù)類型有

1. 集合數(shù)據(jù)類型:list, tuple, dict, set, str等

2. generator狞尔,包括生成器和帶yield的generator function

這些可以直接作用于for循環(huán)的對象丛版,叫Iterable可迭代對象。判斷類型有兩個方法:type()和isinstance(obj, type)

切記:判斷Iterable之前偏序,請先from collections import Iterable

可以用next()調用并不斷返回下一個值的對象成為迭代器Iterator页畦。想把Iterable對象編程iterator,可以使用Iter()函數(shù)研儒。

for循環(huán)本質上就是不斷調用next()實現(xiàn)的豫缨。以下兩個是等價的:

for x in [1, 2, 3, 4, 5]:

? ? pass

it = iter([1, 2, 3, 4, 5])

while True:

? ? try:

? ? ? ? x = next(it)

? ? except StopIteration

? ? ? ? break


高階函數(shù)

1. 變量可以指向函數(shù),函數(shù)的參數(shù)能接受變量端朵。

2. 所以好芭,一個函數(shù)局可以接收另一個函數(shù)作為參數(shù)。這種函數(shù)就稱為高階函數(shù)冲呢。

def add(x, y, f):

? ?return f(x) + f(y)

就是傳入兩個值栓撞,絕對值后再相加。

map/reduce

map(function, iterable)得到一個Iterator。map就是把一個函數(shù)瓤湘,作用于一個iteratable。

(想要讀取結果恩尾,可以list(iterator))

list(map(str, [1, 2, 3])) # 把列表里的123全部字符串化弛说。

reduce把一個函數(shù)作用在一個序列上,這個函數(shù)必須接受兩個參數(shù)翰意,reduce把結果繼續(xù)和序列的下一個元素做累積計算木人,其效果就是

from functools import reduce

reduce(f, [x1, x2, x3, x4]) = f(f(f(x1, x2), x3), x4)

filter函數(shù)用于過濾序列,和map一樣冀偶,filter也接受一個函數(shù)和序列醒第,然后根據(jù)函數(shù)返回值是T/F來決定保留還是丟棄該元素。返回的也是惰性序列进鸠,需要list()稠曼。一樣,filter也是惰性計算客年,不調用不篩選霞幅。

sorted既是可以對list進行排序的函數(shù),也是個高階函數(shù)量瓜。

sorted([36, 5, -12, 9, -21], key=abs)

sorted(['bob', 'about', 'Zoo'], key=str.lower, reverse=True)

高階函數(shù)抽象能力強司恳,代碼簡潔

注意,這些高階函數(shù)因為是把一個函數(shù)分配到iterable里邊的每一個元素里邊了绍傲,所以不用再去考慮怎么樣調用每一個元素了。比如

L= [('Bob',75),('Adam',92),('Bart',66),('Lisa',88)]

def by_name(t):

return t[0].lower()

L2 = sorted(L, key=by_name)

print(L2)

不用再想怎么去調用每一個元素了猎塞,比如L[0][1]這種枫弟。。骇塘。

返回函數(shù)(坑款违,小特性群凶,待填充)

匿名函數(shù)

很多時候我們不需要顯式定義函數(shù),直接做一個匿名函數(shù)更方便,而且函數(shù)名還不會重復赠尾。

list(map(lambda x: x * x, [1, 2, 3, 4])

要比這么寫方便很多

def f(x):

? ? return x * x

關鍵字lambda表示匿名函數(shù)力穗,冒號前面x表示函數(shù)參數(shù)。但是只能有一個表達式气嫁,不用寫return当窗,返回值就是該表達式的結果。

也可以把匿名函數(shù)作為返回值返回

def build(x, y):

? ? return lambda: x * x + y * y

python的一些單條表達式適合用lambda函數(shù)寸宵,都是一些比較簡單的狀況崖面。

裝飾器Decorator(沒搞懂)

函數(shù)支持通過function_name.__name__來調用函數(shù)名稱(后面會詳細解析)

裝飾器就是在函數(shù)動態(tài)運行期間,給函數(shù)增加了的功能(其實就是返回函數(shù))梯影。

@log # 把log函數(shù)通過@方法巫员,放到now()前面,作為裝飾器出現(xiàn)甲棍。

def now():

? ? print('2016-10-01')

在面向對象的設計模式中简识,decorator被成為裝飾模式。OOP的裝飾模式需要通過繼承和組合來實現(xiàn)救军,而Python除了能支持OOP的decorator外财异,直接從語法層次支持decorator。Python的decorator可以用函數(shù)實現(xiàn)唱遭,也可以用類實現(xiàn)戳寸。(啥意思?)

偏函數(shù)

借助functools.partial(需要先import functools)拷泽,可以創(chuàng)建一個部分參數(shù)被固定的常用函數(shù)。這就稱為偏函數(shù)拆吆。

比如int(obj, base=n)。如果進制參數(shù)base的n常用(比如轉換成為16進制)捞奕,那么可以規(guī)定

int(obj, base=16)作為偏函數(shù)。使用方法如下

import functools

int2 = functools.partial(int, base=8)

但是院促,調用的時候如果主動改變規(guī)定好的默認參數(shù)渐溶,比如int2(int, base=16)掌猛,16進制轉換仍然有效废膘。

當函數(shù)的參數(shù)個數(shù)太多需要簡化的時候斋配,固定住某一些參數(shù),從而方便調用甩卓。

模塊

把函數(shù)分組逾柿,放到不同的.py文件里,每一個.py文件就叫做模塊弱匪。

調用模塊的最大好處在于,不需要重復制作輪子财搁,只要調用就好。

模塊會組成package(包)提茁,所以我們會說“調用第三方包/庫铃岔,說的就是這個意思。

包目錄下纺且,必須有__init__.py文件,否則python就不識別這個包目錄嫁艇,而是當成普通目錄。

切記:不能與系統(tǒng)自帶模塊重名歧斟,比如sys静袖。

使用模塊要先import sys队橙。

模塊的編寫(略)

安裝模塊

安裝第三方模塊,是通過pip工具

$ pip install pandas

調用的時候解总, 只import就只會在1. 當前目錄 2. 所有已經(jīng)安裝的內置模塊 3.第三方模塊 進行搜索刻盐,實際上遍歷了sys.path變量下的文件內容

import sys

sys.path

如果要暫時添加敦锌,用append()

sys.path.append('the directory you want to add')?

第二種方法設置環(huán)境變量PYTHONPATH乙墙,該環(huán)境變量的內容會被自動添加到模塊搜索路徑

(待填坑)

面向對象編程Object Orient Programming(OOP)

OOP把對象作為程序設計的基本單元,一個對象包含了數(shù)據(jù)和(操作數(shù)據(jù)的)函數(shù)哗魂。把計算機程序程序視為一組對象的集合朽色,而每個對象都可以接收其他對象發(fā)過來的消息抱冷,并處理這些消息旺遮。執(zhí)行程序就是在對象之間傳遞信息。

面向過程的程序設計把計算機程序視為一系列的命令集合,就是一組函數(shù)的順序執(zhí)行丈积。具體铛纬,就是把函數(shù)切分成為子函數(shù)棺弊。

python中所有數(shù)據(jù)類型都可以視為對象,當然也可以自定義對象缝驳。自定義的對象數(shù)據(jù)類型就是面向對象中的類(class)的概念用狱。

比如class是student, 是泛指學生這個概念,instance則是一個個具體的student, 張三李四溺忧。

所以,面向對象的設計思想是抽象出class歌溉,根據(jù)class創(chuàng)建instance痛垛。

面向對象的抽象成都又比函數(shù)要高,因為一個class既包含數(shù)據(jù)乾胶,又包含操作數(shù)據(jù)的方法。

面向對象三大特點:數(shù)據(jù)封裝喻频、繼承和多態(tài)

是時候祭出這張圖了锻煌!當當當當!

類和實例

類是抽象的模板,比如student類倦沧。實例是根據(jù)類創(chuàng)建出來的一個個具體的對象,每個對象只是數(shù)據(jù)不一樣而已告希,方法是相同的。

定義一個class

class Student(object):

? ? pass

注意:類名通常是首字母大寫的單詞,接下來是(object),表示該類是從哪個類繼承下來的檬贰。如果沒有,就繼承自object類萌踱,這是所有類最終都會繼承的類鸳粉。

定義好了Student類,就可以根據(jù)Student類創(chuàng)建出Student的實例艰山,創(chuàng)建實例是

barry = Student()

barry

<__main__.Student at 0x103d40d68>

后邊的0x103d40d6是內存地址,每個object地址都不一樣舔腾。

每個實例都可以自由綁定屬性,比如

barry.name = 'barry li'

這種方法對于實例雖然自由搂擦,但是沒有讓class起到模板的作用稳诚。我們要把class更加規(guī)范化,從而讓instance更加規(guī)范化瀑踢,這個方法就是定義__init__

class Student(object):

? ? def __init__(self, name, score):

? ? ? ? self.name = name

? ? ? ? self.score = score

__init__方法的第一個參數(shù)永遠是self扳还,表示創(chuàng)建的實例本身。因此橱夭,在__init__方法內部茬暇,就可以把各種屬性(name, score這種)綁定到self,因為self就指向創(chuàng)建的實例本身沧奴。

這樣定義完畢了肆资,就不能再barry = Studeng()了女器,比如傳入

barry = Student('barry li', '100') 來定義

barry.name輸出barry li

barry.score輸出100

def __init__的過程抗愁,跟普通函數(shù)的定義只有一點不同癞季,就是第一個參數(shù)永遠是實例變量self,并且在調用時不用傳遞該參數(shù)购披。所以蝙云,默認參數(shù)抡医、可變參數(shù)、關鍵字參數(shù)和命名關鍵字參數(shù)仍然是存在的。

數(shù)據(jù)封裝

可以直接在class的內部定義訪問數(shù)據(jù)的函數(shù),而不必在外部定義铁追,這樣就把數(shù)據(jù)進行了封裝屿岂。封裝數(shù)據(jù)的函數(shù)和class本身是關聯(lián)起來的空骚,我們稱之為類的方法(所以會經(jīng)常看到“這個類沒有這個方法”)

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))

想要調用

barry.print_score() 得到barry li: 100

(注意, 這個時候print_score(barry)) 就不好用,想想為什么)

這樣诽嘉,封裝的巨大意義就出現(xiàn)了:創(chuàng)建實例只需要給出score, name這些,而打印只需要調用print_score黍少,這些都是在Student類內部定義的,這些數(shù)據(jù)和邏輯封裝起來了,調用很容易,但卻不用知道內部實現(xiàn)的細節(jié)。

(注意print_score仍然是函數(shù)汉操,只不過是class內部的函數(shù)其弊,稱為Method(?), 所以return)

封裝的另一個巨大好處是膀斋,可以給一個定義好的class增加新的方法,比如get_grade

總結下痹雅,類是創(chuàng)建實例的模板仰担,實例是一個個具體的對象,比如你要批量創(chuàng)造鍵盤绩社,那么要先規(guī)定好摔蓝,鍵盤(作為class)的特征是什么,(要傳入的參數(shù)是什么,比如尺寸愉耙,顏色贮尉,軸體,品牌等)朴沿,然后創(chuàng)造出來的具體的鍵盤比如filco圣手二代(實例)猜谚。但其實跟創(chuàng)建的第二個鍵盤Cherry MX2.0沒啥關系,但是他們都是鍵盤呀(攤手)赌渣。

class Keyboard(object):

? ? def __init__(self, size, color, switch, barry)

? ? ? ? self.switch = switch

...

? ? def print_switch(self):

? ? ? ? ?print('%s' % self.switch)

如果我們要知道魏铅,某個鍵盤是什么軸體的,那么可以直接在class內部定義好坚芜,怎樣從外部獲壤婪肌:直接定義訪問軸體get_switch訪問switch這個參數(shù)的內容就好。

通過實例調用方法鸿竖,我們就直接操作了對象內部的數(shù)據(jù)沧竟,但無需知道方法內部的實現(xiàn)細節(jié)。

同樣的缚忧,對一個實例的操作悟泵,并不影響其他實例。比如指著A說“你除了一個鼻子搔谴,兩個眼睛魁袜,是‘人’這個類之外,你還有有個特性:A.feature = '傻逼') 定義了A的feature是個傻逼敦第,但是你如果嘗試調用B.feature峰弹,就會報錯:B連feature這個屬性都沒有,更別提B是不是傻逼了。

訪問限制

外部代碼還是可以自由修改一個實例的name, score屬性芜果。如果要讓內部屬性不被外部訪問鞠呈,可以把屬性的名稱前加上兩個下劃線__,在python中右钾,實例的變量如果以__開頭蚁吝,就變成了一個私有變量(private)旱爆,外部不能訪問,只能通過內部定義的方法來訪問窘茁,這樣就保證了代碼的robust怀伦。

class定義好了規(guī)則,只能通過指定規(guī)則來訪問指定數(shù)據(jù)山林,這種直接從底層拿的方法就被ban掉了房待。

一樣,修改也是可以開放的, 可以在內部定義set_score這種驼抹。換句話說桑孩,修改這個權限也是在內部通過方法實現(xiàn)的。


繼承和多態(tài)

在OOP中框冀,當我們定義一個class的時候流椒,可以從某個現(xiàn)有的class繼承,新的class稱為subclass明也。而被繼承的class被稱為基類宣虾、父類和超類(base class, super class)。

還說機械鍵盤的例子温数,Cherry這個subclass只pass了下峭状,就獲得了來自base class Keyboard的clean_keyboard方法瓦胎。


當然,subclass也不是什么都要跟著base class走。完全可以定義自己的方法辫狼。當然狐粱,如果subclass創(chuàng)建了跟base class同名的方法拗胜,以subclass為主導(這和父母和孩子的關系很像:孩子的后天行為會覆蓋掉先天影響歧匈,但是孩子來源于父母)

這時候得到的輸出結果一定是your cherry is being cleaned

比如這個clean_keyboard方法,父類子類都有王带,以子類為主淑蔚。代碼運行,總是調用子類的愕撰。

這時候刹衫,就是繼承的另一個好處:多態(tài)。啥是多態(tài)搞挣?

我們定義了一個class带迟,我們就定義了一個數(shù)據(jù)類型,跟內置的tuple/list/dict/set/string/int沒啥兩樣囱桨。如果我們用常規(guī)測類型的方法isinstance(obj, type)來測仓犬,就會發(fā)現(xiàn)cherry(作為實例,不是class) 確實是屬于Cherry類型舍肠,同時也是Keyboard類型搀继,當然更是object類型(這是根父類)窘面。

所以這三個結果都是True

print(isinstance(cherry,Cherry))

print(isinstance(cherry,Keyboard))

print(isinstance(cherry,object))

理解多態(tài)的好處:

實際上,任何依賴Animal作為參數(shù)的函數(shù)或者方法不加修改地正常運行叽躯。

新增一個Animal的子類财边,不必對run_twice進行修改。也就是說不管傳入的是貓是狗点骑,我們只需要接收Animal類型就好制圈。因為貓狗都是Animal類型,然后按照Animal類型進行操作即可畔况。由于Animal類型有run()方法,因此傳入的任意數(shù)據(jù)類型慧库,只要是Animal的類或子類,就會自動調用實際類型的run()方法齐板,這就是多態(tài)的意思:

對于一個變量吵瞻,我們只需要知道它是Animal類型,無需確切知道它的子類型橡羞,就可以放心地調用run()方法,而具體調用的run()方法是作用在Animal济舆、Dog還是cat對象上卿泽,由運行時該對象的確切類型決定,這就是多態(tài)真正的威力:調用只管調用滋觉,不管細節(jié)签夭。當我們新增一種Animal子類的時候,只要確保子類的run()編寫正確(前提是run()還是要寫到子類里邊的)椎侠,不用管原來的代碼是如何調用的第租。這就是著名的”開閉“原則:

對擴展開放:允許新增Animal子類;

對修改封閉:不需要修改依賴Animal類型的run_twice()等函數(shù)我纪。

繼承還還可以一級一級地繼承狹隘慎宾,就好比從爺爺?shù)桨职帧⒃俚絻鹤舆@樣的關系浅悉。而任何類趟据,最終都可以追溯到根類object,這些繼承關系看上去就像一顆倒著的樹术健。

從這個意義上講之宿,在任何一個更根的類里定義的方法,都可以被這個分支上的所有子類繼承苛坚。

看到這里比被,一定有人像我一樣暈了

dog.run()

run_twice(Dog())

為什么一個dog在前面

一個Dog()在里面色难?

經(jīng)過測試,這兩個寫法居然不是通用的等缀,那是怎么回事枷莉?

dog.run() 是方法的使用范例

run_twice(Dog()) 是函數(shù)的使用范例

方法和函數(shù)的關系是,

函數(shù)(function)就相當于一個數(shù)學公式尺迂,它理論上不與其它東西關系笤妙,它只需要相關的參數(shù)就可以

方法(method)是與某個對象相互關聯(lián)的,也就是說它的實現(xiàn)與某個對象有關聯(lián)關系.也就是說噪裕,在Class定義的函數(shù)就是方法.

簡而言之蹲盘,方法和對象相關,函數(shù)和對象無關膳音。

靜態(tài)語言 vs 動態(tài)語言

對于靜態(tài)語言(如Java)召衔,如果需要傳入Animal類型,則傳入的對象必須是Animal類型或者它的子類祭陷,否則將無法調用run()方法苍凛。

對于Python這樣的動態(tài)語言來說,不一定需要傳入Animal類型兵志。我們保證傳入的對象有一個run()方法就可以了醇蝴。鴨子類型和多態(tài)詳解

http://blog.csdn.net/shangzhihaohao/article/details/7065675

以前寫過一篇文章講了一下python中的多態(tài),最后得出結論python不支持多態(tài)想罕,隨著對python理解得加深悠栓,對python中得多態(tài)又有了一些看法。

首先Python不支持多態(tài)按价,也不用支持多態(tài)闸迷,python是一種多態(tài)語言,崇尚鴨子類型俘枫。以下是維基百科中對鴨子類型得論述:

在程序設計中腥沽,鴨子類型(英語:duck typing)是動態(tài)類型的一種風格。在這種風格中鸠蚪,一個對象有效的語義今阳,不是由繼承自特定的類或實現(xiàn)特定的接口,而是由當前方法和屬性的集合決定茅信。這個概念的名字來源于由James Whitcomb Riley提出的鴨子測試盾舌,“鴨子測試”可以這樣表述:

“當看到一只鳥走起來像鴨子、游泳起來像鴨子蘸鲸、叫起來也像鴨子妖谴,那么這只鳥就可以被稱為鴨子。”

在鴨子類型中膝舅,關注的不是對象的類型本身嗡载,而是它是如何使用的。例如仍稀,在不使用鴨子類型的語言中洼滚,我們可以編寫一個函數(shù),它接受一個類型為鴨的對象技潘,并調用它的走和叫方法遥巴。在使用鴨子類型的語言中,這樣的一個函數(shù)可以接受一個任意類型的對象享幽,并調用它的走和叫方法铲掐。如果這些需要被調用的方法不存在,那么將引發(fā)一個運行時錯誤值桩。任何擁有這樣的正確的走和叫方法的對象都可被函數(shù)接受的這種行為引出了以上表述摆霉,這種決定類型的方式因此得名。

鴨子類型通常得益于不測試方法和函數(shù)中參數(shù)的類型颠毙,而是依賴文檔、清晰的代碼和測試來確保正確使用砂碉。從靜態(tài)類型語言轉向動態(tài)類型語言的用戶通常試圖添加一些靜態(tài)的(在運行之前的)類型檢查蛀蜜,從而影響了鴨子類型的益處和可伸縮性,并約束了語言的動態(tài)特性增蹭。

毫無疑問在python中對象也是一塊內存滴某,內存中除了包含屬性、方法之外滋迈,還包含了對象得類型霎奢,我們通過引用來訪問對象,比如a=A()饼灿,首先python創(chuàng)建一個對象A幕侠,然后聲明一個變量a,再將變量a與對象A聯(lián)系起來碍彭。變量a是沒有類型得晤硕,它的類型取決于其關聯(lián)的對象。a=A()時庇忌,a是一個A類型的引用舞箍,我們可以說a是A類型的,如果再將a賦值3皆疹,a=3疏橄,此時a就是一個整型的引用,但python并不是弱類型語言略就,在python中'2'+3會報錯捎迫,而在PHP中'2'+3會得到5晃酒。可以這么理解立砸,在python中變量類似與c中的指針掖疮,和c不同的是python中的變量可以指向任何類型,雖然這么說不太準確颗祝,但是理解起來容易點浊闪。

因此,在python運行過程中螺戳,參數(shù)被傳遞過來之前并不知道參數(shù)的類型搁宾,雖然python中的方法也是后期綁定,但是和Java中多態(tài)的后期綁定卻是不同的倔幼,java中的后期綁定至少知道對象的類型盖腿,而python中就不知道參數(shù)的類型。

還引用上次的例子:

[python]view plaincopy

classA:

defprt(self):

print"A"

classB(A):

defprt(self):

print"B"

classC(A):

defprt(self):

print"C"

classD(A):

pass

classE:

defprt(self):

print"E"

classF:

pass

deftest(arg):

arg.prt()

a?=?A()

b?=?B()

c?=?C()

d?=?D()

e?=?E()

f?=?F()

test(a)

test(b)

test(c)

test(d)

test(e)

test(f)

輸出結果:

[python]view plaincopy

A

B

C

A

E

Traceback?(most?recent?call?last):

File"/Users/shikefu678/Documents/Aptana?Studio?3?Workspace/demo/demo.py",?line33,in

test(a),test(b),test(c),test(d),test(e),test(f)

File"/Users/shikefu678/Documents/Aptana?Studio?3?Workspace/demo/demo.py",?line24,intest

arg.prt()

AttributeError:?F?instance?has?no?attribute'prt'

a损同,b翩腐,c,d都是A類型的變量膏燃,所以可以得到預期的效果(從java角度的預期)茂卦,e并不是A類型的變量但是根據(jù)鴨子類型,走起來像鴨子组哩、游泳起來像鴨子等龙、叫起來也像鴨子,那么這只鳥就可以被稱為鴨子伶贰,e有prt方法蛛砰,所以在test方法中e就是一個A類型的變量,f沒有prt方法黍衙,所以f不是A類型的變量泥畅。

以上是從java的角度分析的,其實上邊都是一派胡言琅翻,只是為了說明python中的運行方法涯捻。沒有誰規(guī)定test方法是接收的參數(shù)是什么類型的。test方法只規(guī)定望迎,接收一個參數(shù)障癌,調用這個參數(shù)的prt方法。在運行的時候如果這個參數(shù)有prt方法辩尊,python就執(zhí)行涛浙,如果沒有,python就報錯,因為abcde都有prt方法轿亮,而f沒有疮薇,所以得到了上邊得結果,這就是python的運行方式我注。

獲取對象信息

當我們拿到一個對象的引用時按咒,如何知道這個對象是什么類型,有哪些方法可以調用但骨?

type()

判斷對象類型励七,基本類型肯定都可以判斷,變量或者類也能判斷奔缠。

In[7]: type(Cat())

Out[7]: __main__.Cat

In[5]: type(abs)

Out[5]: builtin_function_or_method

可見掠抬,type()返回的是對應的class類型。也可以通過if語句來生成布爾值

type('abc') == str

type('abc') == type(123)

也可以判斷一個對象是否為函數(shù)校哎,但是需要調用types(別忘了s傲讲ā!C贫摺)

import types

def fn():

? ?pass

type(fn) == types.FunctionType

type(abs) == types.BuiltinFunctionType

type((x for x in range(10)) == types.GeneratorType

isinstance()

type()直接判斷沒問題腰奋,判斷繼承就很麻煩——我們想知道的是Dog是否屬于Animal,type()只能告訴我Dog()(實例)屬于Dog

一句話:isinstance可以幫你判斷一個對象是否是該類型本身抱怔,或是位于該類型的父繼承鏈上劣坊。

也可以判斷多個,關系是any(或)

isinstance([1, 2, 3], (list, tupe))
>>>True

使用dir() (重頭戲來了)

如果要獲得一個對象的所有屬性和方法野蝇,可以使用dir()函數(shù)讼稚,它返回一個包含字符串的list括儒。(這也是針對”某對象沒有這個方法“報錯的最有效方法——而不是盲目嘗試或是貿然百度绕沈,需要學會調試錯誤)

比如dir('ABC') # 查看一個string所有的屬性和方法,以“__"開頭的暫且不提

'capitalize','casefold','center','count','encode','endswith','index','isdecimal','isdigit','isidentifier','islower',isnumeric','isprintable','isspace','lower','lstrip',maketrans','partition','replace','rindex','just','rpartition','rsplit','rstrip','splitlines', ?(復制的不全)

要清楚一件事情帮寻,len('ABC') 也是通過'ABC'.__len__()實現(xiàn)的

(想想為啥一個寫'ABC'.len()不行乍狐。因為一個字符串并沒有內部的方法叫l(wèi)en(),不信可以自己去看固逗。只有內部確有這個方法可以用object.method()

剩下的都是普通屬性方法浅蚪,比如lower()返回小寫的字符串:'ABC'.lower()

?進階:

可以使用hasattr(object, name) 判斷object是否有這個屬性

可以用setattr(object, name, value) 給object加上name這個屬性,value是xxx

也可以用getattr(object, name)來獲取name的value 等價于obj.name

報錯提醒:如果試圖獲取不存在的屬性烫罩,會拋出AttributeError(最常見的錯誤之一)

可以通過限制getattr(obj, name, 404) 這種方法來限定錯誤返回——即不返回AttriuteError惜傲,而返回指定的value, 比如404

所以,通過內置的type(), isintance(),dir()贝攒,我們可以對任意一個python對象進行解析盗誊,拿到其內部的數(shù)據(jù)。只有不知道不確定對象內部信息的時候,我們才會嘗試去獲取對象信息哈踱。如果你知道可以

sum = obj.x + obj.y沒問題荒适,就不要sum = getattr(obj, 'x') + getattr(obj, 'y')

但是話說回來,根據(jù)鴨子類型原理开镣,只要有x方法刀诬,就可以用調用。有x方法的不一定是同一類對象——但是鴨子根本不在乎邪财。

實例屬性和類屬性

就一點:在寫程序的時候陕壹,千萬不要把實例屬性和類屬性使用相同的名字,因為相同名稱的實例屬性將屏蔽掉類屬性卧蜓。(如果刪除類型屬性帐要,但是當你刪除實例屬性后,再使用相同的名稱弥奸,訪問到的將是類屬性)


我覺得好像從現(xiàn)在開始榨惠,知識的抽象程度就直接升了一個檔次。每一塊花的時間都要比前面的幾塊加起來還要多——但這也正是意義所在盛霎,簡單的東西稍微下功夫就學得會赠橙,但終究價值不大。

面向對象高級編程

數(shù)據(jù)封裝愤炸、繼承和多態(tài)只是面向對象程序設計中的基礎三概念期揪。高級功能還有很多。

使用__slots__

先說一個小技巧规个,可以直接給一個實例綁定一個方法凤薛,通過

from types import MethodType

instance.function = MethodType(function, instance)

但是一般我們不給instance綁定方法,我們都直接給class綁诞仓。有兩個方法缤苫,要么直接在class內綁定,要么通過instance.function = MethodType(function, instance)來綁定方法

內部綁定的方法是常規(guī)方法墅拭,基本上所有語言都能實現(xiàn)活玲;

外部綁定因為是后綁定上去的,或者說隨時想綁就綁的谍婉,稱之為動態(tài)綁定舒憾,只有動態(tài)語言才能實現(xiàn)。

靜態(tài)綁定:內部綁定
動態(tài)綁定:MethodType綁定

針對instance和class, 如果用這種方法來綁定屬性的話穗熬,基本上想綁啥就綁啥镀迂。其實是很多時候需要限制的,這時候就需要在class內部定義的__slots__唤蔗。

class Student(object):

? ? __slot__ = ('name', 'age') # 用tuple定義允許綁定的屬性名稱

這時候嘗試去綁定其他屬性就會返回錯誤

但是探遵!這僅僅限于這個class, 繼承class的其他subclass并不受__slot__限制唧瘾,除非subclass自己也定義上__slot__。

使用@property(和裝飾器相連别凤,實在是沒看懂)

多重繼承

只有通過多重繼承饰序,一個子類就可以同時獲得多個父類的所有功能。

這樣规哪,就避免了繼承的過分的復雜性求豫。

在設計class的繼承關系時,通常都是“一脈相承”诉稍。如果需要額外混入其他功能蝠嘉,通過多重繼承就可以實現(xiàn)。就如同Dog繼承Mammal杯巨,同時也繼承Runnable蚤告。這種設計通常稱之為MixIn。MixIn的目的就是給一個類增加多個功能服爷。這樣我們會優(yōu)先考慮通過多重繼承來組合多個MixIn功能杜恰,而不是設計多層次的復雜的繼承關系。(JAVA這種只允許單一繼承的語言不能使用MixIn的設計)

定制類仍源、枚舉類心褐、元類(略,等待填坑)

6天時間復習到這笼踩。元動力消耗完畢逗爹,任務掛起,切換至pandas嚎于。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末掘而,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子于购,更是在濱河造成了極大的恐慌袍睡,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,490評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件价涝,死亡現(xiàn)場離奇詭異女蜈,居然都是意外死亡持舆,警方通過查閱死者的電腦和手機色瘩,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,581評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來逸寓,“玉大人居兆,你說我怎么就攤上這事≈裆欤” “怎么了泥栖?”我有些...
    開封第一講書人閱讀 165,830評論 0 356
  • 文/不壞的土叔 我叫張陵簇宽,是天一觀的道長。 經(jīng)常有香客問我吧享,道長魏割,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,957評論 1 295
  • 正文 為了忘掉前任钢颂,我火速辦了婚禮钞它,結果婚禮上,老公的妹妹穿的比我還像新娘殊鞭。我一直安慰自己遭垛,他們只是感情好,可當我...
    茶點故事閱讀 67,974評論 6 393
  • 文/花漫 我一把揭開白布操灿。 她就那樣靜靜地躺著锯仪,像睡著了一般。 火紅的嫁衣襯著肌膚如雪趾盐。 梳的紋絲不亂的頭發(fā)上庶喜,一...
    開封第一講書人閱讀 51,754評論 1 307
  • 那天,我揣著相機與錄音救鲤,去河邊找鬼溃卡。 笑死,一個胖子當著我的面吹牛蜒简,可吹牛的內容都是我干的瘸羡。 我是一名探鬼主播,決...
    沈念sama閱讀 40,464評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼搓茬,長吁一口氣:“原來是場噩夢啊……” “哼犹赖!你這毒婦竟也來了?” 一聲冷哼從身側響起卷仑,我...
    開封第一講書人閱讀 39,357評論 0 276
  • 序言:老撾萬榮一對情侶失蹤峻村,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后锡凝,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體粘昨,經(jīng)...
    沈念sama閱讀 45,847評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,995評論 3 338
  • 正文 我和宋清朗相戀三年窜锯,在試婚紗的時候發(fā)現(xiàn)自己被綠了张肾。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,137評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡锚扎,死狀恐怖吞瞪,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情驾孔,我是刑警寧澤芍秆,帶...
    沈念sama閱讀 35,819評論 5 346
  • 正文 年R本政府宣布惯疙,位于F島的核電站,受9級特大地震影響妖啥,放射性物質發(fā)生泄漏霉颠。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,482評論 3 331
  • 文/蒙蒙 一荆虱、第九天 我趴在偏房一處隱蔽的房頂上張望掉分。 院中可真熱鬧,春花似錦克伊、人聲如沸酥郭。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,023評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽不从。三九已至,卻和暖如春犁跪,著一層夾襖步出監(jiān)牢的瞬間椿息,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,149評論 1 272
  • 我被黑心中介騙來泰國打工坷衍, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留寝优,地道東北人。 一個月前我還...
    沈念sama閱讀 48,409評論 3 373
  • 正文 我出身青樓枫耳,卻偏偏與公主長得像乏矾,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子迁杨,可洞房花燭夜當晚...
    茶點故事閱讀 45,086評論 2 355

推薦閱讀更多精彩內容

  • http://python.jobbole.com/85231/ 關于專業(yè)技能寫完項目接著寫寫一名3年工作經(jīng)驗的J...
    燕京博士閱讀 7,579評論 1 118
  • //Clojure入門教程: Clojure – Functional Programming for the J...
    葡萄喃喃囈語閱讀 3,674評論 0 7
  • 前言 人生苦多钻心,快來 Kotlin ,快速學習Kotlin铅协! 什么是Kotlin捷沸? Kotlin 是種靜態(tài)類型編程...
    任半生囂狂閱讀 26,215評論 9 118
  • Spring Cloud為開發(fā)人員提供了快速構建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務發(fā)現(xiàn)狐史,斷路器痒给,智...
    卡卡羅2017閱讀 134,672評論 18 139
  • 有一天大啊躍問佛:“佛啊佛,世人皆跪你骏全、拜你苍柏、有求于你,你累嗎吟温?”佛說:“我本西山之竹序仙,東山之泥突颊。被人們挖了伐了塑...
    大啊躍閱讀 123評論 0 0