Python源碼漫游指南

發(fā)現(xiàn)這一篇對 Python 源碼樹更詳細(xì)的分析文章,特復(fù)制轉(zhuǎn)載到此垫释,感謝原文作者分享

作者:秘塔科技算法研究員?Qian Wan

前幾天IEEE Spectrum發(fā)布了第五屆頂級語言交互排行榜丝格,Python語言繼續(xù)穩(wěn)坐第一把交椅,并且相比去年的排行情況棵譬,拉開了與第二名的距離(去年第二名的排名得分為99.7)显蝌。從下圖能看出Python的優(yōu)勢還是很明顯的,而且在Web订咸、企業(yè)級和嵌入式這三種應(yīng)用類別的流行度都很高曼尊。

IEEE Spectrum發(fā)布了第五屆頂級語言交互排行榜

冰凍三尺非一日之寒。Python語言自1990年由Guido van Rossum第一次發(fā)布至今已經(jīng)快三十年的歷史脏嚷,它支持多種操作系統(tǒng)骆撇,以CPython為參考實(shí)現(xiàn)。

Python語言在很多領(lǐng)域都有殺手級的應(yīng)用框架父叙,如深度學(xué)習(xí)方面有PyTorch和Tensorflow恋腕,自然語言處理有NLTK莺掠,Web框架有Django、Flask宇植,科學(xué)計(jì)算有Numpy布疼、Scipy城豁,計(jì)算機(jī)視覺有OpenCV逗抑,科學(xué)繪圖有Matplotlib镊绪,爬蟲有Scrapy,凡此種種带欢,不一而足。面對這么多不同種類的Python應(yīng)用框架烤惊,下面一些問題是值得我們思考的:

1.?怎樣使用Python語言能將程序的性能發(fā)揮到極致乔煞?

2.?什么類型的單一語言框架不適合用Python來實(shí)現(xiàn)?

3.?多語言框架中與Python語言的交互如何做到高效柒室?

4.?從架構(gòu)的角度看渡贾,Python內(nèi)部的架構(gòu)設(shè)計(jì)如何?

5.?從使用Python語言的角度雄右,它適合于什么樣的軟件架構(gòu)設(shè)計(jì)空骚?

6.?在多語言(Python與CUDA)纺讲、異構(gòu)節(jié)點(diǎn)(CPU與GPU)、多業(yè)務(wù)類型(IO密集型與CPU密集型)以及跨區(qū)域(跨國多機(jī)房)的復(fù)雜系統(tǒng)中囤屹,Python語言的定位又如何熬甚?其他語言呢?

三言兩語可能很難比較全面的回答上面一些問題肋坚,而且只研究Python語言得到的答案也可能會有失偏頗乡括。但是Python語言的源代碼能夠?yàn)榛卮疬@些問題提供一些線索,而且通過閱讀源碼能讓我們在使用Python語言時看到一些以前我們看不到的細(xì)節(jié)智厌,就如同《黑客帝國》電影里的Neo一樣能看到母體世界的源代碼诲泌,也能像Neo那樣在機(jī)器的世界里飛天遁地。

Python環(huán)境的部署

我們使用pyenv花幾分鐘時間來構(gòu)建Python運(yùn)行環(huán)境铣鹏,它不僅可以與操作系統(tǒng)原生的Python環(huán)境隔離敷扫,還能支持多種版本的Python環(huán)境,另外也支持在同一Python版本下的多個虛擬環(huán)境诚卸,可以用來隔離不同應(yīng)用的Python依賴包葵第。部署代碼如下

$ git?clone?https://github.com/pyenv/pyenv.git?~/.pyenv

$ echo?'export PYENV_ROOT="$HOME/.pyenv"'?>> ~/.bashrc

$ echo?'export PATH="$PYENV_ROOT/bin:$PATH"'?>> ~/.bashrc

$ git clone?https://github.com/pyenv/pyenv-virtualenv.git?${HOME}/.pyenv/plugins/pyenv-virtualenv

$ echo?'eval "$(pyenv init -)"'?>> ~/.bashrc

$ echo?'eval "$(pyenv virtualenv-init -)"'?>> ~/.bashrc

$ CONFIGURE_OPTS=--enable-shared?

$HOME/.pyenv/bin/pyenv install 3.6.6 -k -v

$ $HOME/.pyenv/bin/pyenv virtualenv 3.6.6 py3.6

部署好了之后每次運(yùn)行下面命令就能替換掉系統(tǒng)原生的Python環(huán)境

$ pyenv activate py3.6

安裝后的目錄結(jié)構(gòu)如下

·?Python源碼:~/.pyenv/sources/3.6.6/Python-3.6.6

·?頭文件:~/.pyenv/versions/3.6.6/include/python3.6m/

·?動態(tài)鏈接庫:~/.pyenv/versions/3.6.6/lib/libpython3.6m.dylib

目錄結(jié)構(gòu)

要深入剖析Python的源代碼,就要對源碼中幾個大的模塊的作用有一個初步的認(rèn)識惨险。我們進(jìn)入到源碼目錄~/.pyenv/sources/3.6.6/Python-3.6.6羹幸,其中幾個跟Python語言直接相關(guān)的目錄及其功能如下

·?Include:C頭文件,與部署好的頭文件目錄~/.pyenv/versions/3.6.6/include/python3.6m/中的文件一致(嚴(yán)格來說辫愉,部署好的頭文件目錄中會多一個自動生成的pyconfig.h文件)栅受,這些頭文件定義了Python語言的底層抽象結(jié)構(gòu)。

·?Lib:Python語言庫恭朗,這部分不參與Python的編譯屏镊,而是用Python語言寫好的模塊庫。

·?Modules:用C語言實(shí)現(xiàn)的Python內(nèi)置庫痰腮。

·?Objects:Python內(nèi)置對象的C語言實(shí)現(xiàn)以及抽象接口的實(shí)現(xiàn)而芥。

·?Parser:Python編譯器的前端,詞法分析器語法分析器膀值。后者就是基于龍書的LL(1)實(shí)現(xiàn)的棍丐。

·?Programs:可執(zhí)行文件~/.pyenv/versions/3.6.6/bin/python的源碼所在的目錄。

·?Python:Python虛擬機(jī)所在的目錄沧踏,也是整個Python語言較為核心的部分歌逢。

使用下面的圖示能更好的展示這些目錄之前的相互關(guān)系,虛線箭頭表示提供接口定義翘狱,實(shí)線箭頭表示提供服務(wù)秘案,自頂向下的結(jié)構(gòu)也體現(xiàn)了語言設(shè)計(jì)在架構(gòu)上的層次關(guān)系。


Include目錄

從上面這些模塊的大致功能上分析,我們可以判斷出Include阱高、Objects和Python中的代碼比較重要赚导。我們先看一下這三個目錄包含的代碼量

$ cat Include/* Objects/* Python/* | wc -l

cat: Objects/clinic: Is a directory

cat: Objects/stringlib: Is a directory

cat: Python/clinic: Is a directory

?215478

21萬行代碼的閱讀量有點(diǎn)略大,我們還是先挨個看看這些目錄中文件的命名赤惊、大小以及一些注釋吼旧,看能不能得到一些線索。

$ wc -l Include/*.h | sort -k1

?...

?324 pystate.h

?370 objimpl.h

?499 dynamic_annotations.h

?503 pyerrors.h

?637 Python-ast.h

?767 pyport.h

?1077 object.h

?1377 abstract.h

?2342 unicodeobject.h

?15980 total

從文件名和文件大小可以初步判斷object.h和abstract.h是兩個比較重要的頭文件荐捻,實(shí)際上它們定義了Python底層的抽象對象以及統(tǒng)一的抽象接口黍少。

unicodeobject.h雖然體積大,但是有很多跟它類似的頭文件处面,如boolobject.h厂置、longobject.h、floatobject.h等等魂角,這些頭文件應(yīng)該是內(nèi)置類型的頭文件昵济,我們可以暫時不去理會這些文件,對語言的總體理解不會造成困難野揪。

為了不漏掉一些重要的頭文件访忿,我們快速閱讀一下其他頭文件中可能包含的一些引導(dǎo)性的注釋,發(fā)現(xiàn)這些頭文件也比較重要:

·?Python.h:元頭文件斯稳,通常在寫Python的C擴(kuò)展時會包含它海铆。

·?ceval.h:作為Python/ceval.c的頭文件,而Python/ceval.c負(fù)責(zé)運(yùn)行編譯后的代碼挣惰。

·?code.h:包含字節(jié)碼相關(guān)的底層抽象卧斟。

·?compile.h:抽象語法樹的編譯接口。

·?objimpl.h:跟內(nèi)存相關(guān)的抽象對象高層接口憎茂,如內(nèi)存分配珍语,初始化,垃圾回收等等竖幔。

·?pystate.h:線程狀態(tài)解釋器狀態(tài)以及它們的接口板乙。

·?pythonrun.h:Python代碼的語法分析與執(zhí)行接口。

通過以上篩選拳氢,我們看看還剩下多少代碼:

$ cat object.h abstract.h objimpl.h Python.h ceval.h code.h compile.h pystate.h pythonrun.h | wc -l

?3950

核心頭文件壓縮到不到4千行募逞。

Objects目錄

用類似的思路,我們能從Objects目錄中篩選出一些比較重要的文件

·?abstract.c:抽象對象的接口實(shí)現(xiàn)馋评。

·?codeobject.c:字節(jié)碼對象的實(shí)現(xiàn)凡辱。

·?object.c:通用對象操作的實(shí)現(xiàn)。

·?obmalloc.c:內(nèi)存分配相關(guān)實(shí)現(xiàn)栗恩。

·?typeobject.c:Type對象實(shí)現(xiàn)。

統(tǒng)計(jì)一下代碼量

$ wc -l abstract.c codeobject.c object.c obmalloc.c typeobject.c

?3246 abstract.c

?921 codeobject.c

?2048 object.c

?2376 obmalloc.c

?7612 typeobject.c

?16203 total

一下子新增了1.6萬行,畢竟是實(shí)打?qū)嵉腃語言實(shí)現(xiàn)磕秤。

另外還有一些具象化的對象實(shí)現(xiàn)文件乳乌,雖然它們跟longobject.c和dictobject.c之類的對象實(shí)現(xiàn)類似,都是具體的對象市咆,但是它們跟Python語言特性比較相關(guān)汉操,在這里也把它們列出來,做為備份蒙兰。

·?classobject.c:類對象實(shí)現(xiàn)磷瘤。

·?codeobject.c:代碼對象實(shí)現(xiàn)。

·?frameobject.c:Frame對象實(shí)現(xiàn)搜变。

·?funcobject.c:函數(shù)對象實(shí)現(xiàn)采缚。

·?methodobject.c:方法對象實(shí)現(xiàn)。

·?moduleobject.c:模塊對象實(shí)現(xiàn)挠他。

順便統(tǒng)計(jì)下行數(shù)

$ wc -l classobject.c codeobject.c frameobject.c funcobject.c methodobject.c moduleobject.c

?648 classobject.c

?921 codeobject.c

?1038 frameobject.c

?1031 funcobject.c

?553 methodobject.c

?802 moduleobject.c

?4993 total

Objects目錄中合計(jì)約2.1萬行扳抽。通過探索這些源代碼,我們看出Python的一個設(shè)計(jì)原則就是:一切皆對象殖侵。

嚴(yán)格來說贸呢,只有Python語言暴露給外部使用的部分才抽象成了對象,而一些僅在內(nèi)部使用的數(shù)據(jù)結(jié)構(gòu)則沒有對象封裝拢军,如后面會提到的解釋器狀態(tài)線程狀態(tài)等楞陷。

Python目錄

依然經(jīng)過一輪篩選,能得到下面這些比較重要的文件

·?ast.c:將具體語法樹轉(zhuǎn)換成抽象語法樹茉唉,主要函數(shù)是PyAST_FromNode()

·?ceval.c:執(zhí)行編譯后的字節(jié)碼固蛾。

·?ceval_gil.h:全局解釋器鎖(Global Interpreter Lock,GIL)的接口赌渣。

·?compile.c:將抽象語法樹編譯成Python字節(jié)碼魏铅。

·?pylifecycle.c:Python解釋器的頂層代碼,包括解釋器的初始化以及退出坚芜。

·?pystate.c:線程狀態(tài)解釋器狀態(tài)览芳,以及它們的接口實(shí)現(xiàn)。

·?pythonrun.c:Python解釋器的頂層代碼鸿竖,包括解釋器的初始化以及退出沧竟。

能夠注意到,pylifecycle.c和pythonrun.c的功能是類似的缚忧,實(shí)際上查閱Python開發(fā)歷史記錄能發(fā)現(xiàn)前者是因?yàn)殚_發(fā)需要從后者分離出來的悟泵。統(tǒng)計(jì)一下代碼的數(shù)量:

$ wc -l ast.c ceval.c ceval_gil.h compile.c pystate.c pythonrun.c

?5277 ast.c

?5600 ceval.c

?270 ceval_gil.h

?5329 compile.c

?958 pystate.c

?1596 pythonrun.c

?19030 total

這樣濃縮下來Include、Objects和Python三個文件夾中比較重要的代碼一共大約4.4萬行闪水,先不說我們這樣篩選出來的一波有沒有漏掉重要信息糕非,其他很多支持性的代碼都還沒有包含進(jìn)去。至少目前有了一個大的輪廓,接下來在深入代碼的時候可以慢慢擴(kuò)展開朽肥。

頂層調(diào)用樹

前面討論了Python源碼的主要目錄結(jié)構(gòu)禁筏,以及其中主要的源文件。這里我們換一個思路衡招,看看一個Python源文件是如何在Python解釋器里面運(yùn)行的篱昔。調(diào)用Python的可執(zhí)行文件~/.pyenv/versions/3.6.6/bin/python和調(diào)用我們編寫的其他C語言程序在方式上并沒有太大區(qū)別,不同之處在于Python可執(zhí)行文件讀取的Python源文件始腾,并執(zhí)行其中的代碼州刽。Python之于C就如同C之于匯編,只是Python編譯的字節(jié)碼在Python虛擬機(jī)上運(yùn)行浪箭,匯編代碼直接在物理機(jī)上運(yùn)行(嚴(yán)格來說還需要轉(zhuǎn)換成機(jī)器代碼)穗椅。

以下面這條Python源文件運(yùn)行為例來考察Python可執(zhí)行文件的執(zhí)行過程(大家可以玩玩這個生命游戲,運(yùn)氣好能看到滑翔機(jī))山林。

$ python ~/.pyenv/sources/3.6.6/Python-3.6.6/Tools/demo/life.py

既然Python的可執(zhí)行文件是C語言編譯成的房待,那么一定有C語言的入口函數(shù)main,它就位于Python源碼的./Programs/python.c文件中驼抹。

int?main(int?argc,?char?**argv){

// ...

?res = Py_Main(argc, argv_copy);

// ...

}

順藤摸瓜桑孩,我們可以梳理出調(diào)用樹的主干部分。下面的樹形結(jié)構(gòu)中框冀,冒號左邊為函數(shù)名流椒,右邊表示函數(shù)定義所在的C源文件,樹形結(jié)構(gòu)表示函數(shù)定義中包含的其他函數(shù)嵌套調(diào)用明也。

main: Programs/python.c

└─?Py_Main: Modules/main.c

├─?Py_Initialize: Python/pylifecycle.c

│?├─?PyInterpreterState_New: Python/pystate.c

│?├─?PyThreadState_New: Python/pystate.c

│?├─?_PyGILState_Init: Python/pystate.c

│?└─?_Py_ReadyTypes: Objects/object.c

├─?run_file: Modules/main.c

│?└─?PyRun_FileExFlags: Python/pythonrun.c

│?├─?PyParser_ASTFromFileObject: Python/pythonrun.c

│?│?├─?PyParser_ParseFileObject: Parser/parsetok.c

│?│?└─?PyAST_FromNodeObject: Python/ast.c

│?└─?run_mod: Python/pythonrun.c

│?├─?PyAST_CompileObject: Python/compile.c

│?└─?PyEval_EvalCode: Python/ceval.c

│?├─?PyFrame_New: Objects/frameobject.c

│?└─?PyEval_EvalFrameEx: Python/ceval.c

└─?Py_FinalizeEx: Python/pylifecycle.c

不得不說宣虾,Python源碼的可讀性非常好,這些函數(shù)的命名方式都是自解釋的温数。Python源文件的運(yùn)行大致分為兩個步驟:

1.?Py_Initialize:初始化過程绣硝,主要涉及到解釋器狀態(tài)線程狀態(tài)撑刺、全局解釋器鎖以及內(nèi)置類型的初始化鹉胖。

2.?run_file:運(yùn)行源文件,可以分為三個小步驟

????a.?PyParser_ASTFromFileObject:對源文件的文本進(jìn)行語法分析够傍,得到抽象語法樹甫菠。

????b.?PyAST_CompileObject:將抽象語法樹編譯成PyCodeObject對象。

????c.?PyEval_EvalCode:在Python虛擬機(jī)中運(yùn)行PyCodeObject對象冕屯。

3.?Py_FinalizeEx:源文件執(zhí)行結(jié)束后的清理工作寂诱。

用流程圖的形式表示上述調(diào)用樹的主干部分應(yīng)該更加清晰明了。


需要指出的是安聘,解釋器循環(huán)真正執(zhí)行的是PyEval_EvalFrameEx函數(shù)痰洒,它的參數(shù)是PyFrameObject對象瓢棒,該對象為PyCodeObject對象提供了執(zhí)行的上下文環(huán)境,所以PyFrameObject和PyCodeObject都是非常核心的對象丘喻。Python提供了一些工具讓我們可以查看編譯后的代碼對象音羞,即對編譯好的函數(shù)進(jìn)行反匯編。下面的例子雖然簡單仓犬,但已經(jīng)能給人清晰的直觀認(rèn)識

>>>?from?dis?import?dis

>>>?class?C(object):

...?????def?__init__(self, x):

...?????????self.x = x

...?????def?add(self, y):

...?????????return?self.x + y

...

>>>?dis(C)

Disassembly of __init__:

3?0?LOAD_FAST?????1?(x)

2?LOAD_FAST?????0?(self)

4?STORE_ATTR?????0?(x)

6?LOAD_CONST?????0?(None)

8?RETURN_VALUE

Disassembly of add:

5?0?LOAD_FAST?????0?(self)

2?LOAD_ATTR?????0?(x)

4?LOAD_FAST?????1?(y)

6?BINARY_ADD

8?RETURN_VALUE

反編譯的結(jié)果是一系列的操作碼。頭文件Include/opcode.h包含了Python虛擬機(jī)的所有操作碼舍肠。能看出上面simple_tuple和simple_list這兩個函數(shù)反編譯后的最大區(qū)別么搀继?tuple是作為常量被加載進(jìn)來的,而list的生成還需要調(diào)用BUILD_LIST翠语。原因在于tuple在Python的運(yùn)行時會進(jìn)行緩存叽躯,也就是每次使用無需請求操作系統(tǒng)內(nèi)核以獲得內(nèi)存空間。對比一下使用tuple和list的耗時情況

>>> %timeit x = (1, 2, 3)

10.9 ns ±?0.0617 ns per loop (mean?±?std. dev. of 7 runs, 100000000 loops each)

>>> %timeit x = [1, 2, 3]

46.5 ns ±?0.186 ns per loop (mean?±?std. dev. of 7 runs, 10000000 loops each)

從統(tǒng)計(jì)結(jié)果能看出肌括,tuple的在效率上的優(yōu)勢非常明顯点骑。如果某一段調(diào)用特別頻繁的代碼中有些list可以替換成tuple,千萬不要猶豫谍夭。

總結(jié)

我們可以試著為文章開頭第一個問題提供一些思路黑滴。我們知道,對計(jì)算機(jī)做任何形式上的抽象都有可能傷害到計(jì)算的效率紧索,對于Python來說有以下幾點(diǎn)

1.?Python對象的內(nèi)存部署方式是以在滿足一定效率的前提下足夠通用為目標(biāo)的袁辈,因此在面臨特定問題時它不一定是最優(yōu)的。

2.?Python是動態(tài)類型語言珠漂,并不是編譯型語言晚缩,導(dǎo)致代碼在運(yùn)行時是可變的,從Python將抽象語法樹和PyCodeObject對象暴露出來這一點(diǎn)就能看出媳危。

3.?全局解釋器鎖也會妨礙使用多進(jìn)程來實(shí)現(xiàn)性能的提升荞彼。

4.?Python虛擬機(jī)作為對CPU硬件的抽象也是沒法甩鍋的。

所以為了提高Python程序的效率待笑,我們需要深入了解Python對象的實(shí)現(xiàn)原理鸣皂、PyCodeObject的特性以及全局解釋器和Python虛擬機(jī)的限制。之于文章開頭的其他問題滋觉,我們將隨著Python源碼的深入研究慢慢展開签夭。

現(xiàn)在我們對Python代碼的運(yùn)行有了一個宏觀的理解,而且大量的細(xì)節(jié)都有待深入研究椎侠。通過對調(diào)用樹主干部分的梳理第租,能看出其他比較重要的支持性模塊還包括Python抽象對象PyObject,抽象語法樹及其編譯我纪,PyCodeObject對象慎宾,PyFrameObject對象丐吓,解釋器狀態(tài)線程狀態(tài)趟据,全局解釋器鎖券犁。在以后的文章中,我們會分別對這些模塊進(jìn)行探討汹碱。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末粘衬,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子咳促,更是在濱河造成了極大的恐慌稚新,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,277評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件跪腹,死亡現(xiàn)場離奇詭異褂删,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)冲茸,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評論 3 393
  • 文/潘曉璐 我一進(jìn)店門屯阀,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人轴术,你說我怎么就攤上這事难衰。” “怎么了膳音?”我有些...
    開封第一講書人閱讀 163,624評論 0 353
  • 文/不壞的土叔 我叫張陵召衔,是天一觀的道長。 經(jīng)常有香客問我祭陷,道長苍凛,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,356評論 1 293
  • 正文 為了忘掉前任兵志,我火速辦了婚禮醇蝴,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘想罕。我一直安慰自己悠栓,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,402評論 6 392
  • 文/花漫 我一把揭開白布按价。 她就那樣靜靜地躺著惭适,像睡著了一般。 火紅的嫁衣襯著肌膚如雪楼镐。 梳的紋絲不亂的頭發(fā)上癞志,一...
    開封第一講書人閱讀 51,292評論 1 301
  • 那天,我揣著相機(jī)與錄音框产,去河邊找鬼凄杯。 笑死错洁,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的戒突。 我是一名探鬼主播屯碴,決...
    沈念sama閱讀 40,135評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼膊存!你這毒婦竟也來了导而?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,992評論 0 275
  • 序言:老撾萬榮一對情侶失蹤隔崎,失蹤者是張志新(化名)和其女友劉穎嗡载,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體仍稀,經(jīng)...
    沈念sama閱讀 45,429評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,636評論 3 334
  • 正文 我和宋清朗相戀三年埂息,在試婚紗的時候發(fā)現(xiàn)自己被綠了技潘。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,785評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡千康,死狀恐怖享幽,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情拾弃,我是刑警寧澤值桩,帶...
    沈念sama閱讀 35,492評論 5 345
  • 正文 年R本政府宣布,位于F島的核電站豪椿,受9級特大地震影響奔坟,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜搭盾,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,092評論 3 328
  • 文/蒙蒙 一咳秉、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧鸯隅,春花似錦澜建、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,723評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至跟畅,卻和暖如春咽筋,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背碍彭。 一陣腳步聲響...
    開封第一講書人閱讀 32,858評論 1 269
  • 我被黑心中介騙來泰國打工晤硕, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留悼潭,地道東北人。 一個月前我還...
    沈念sama閱讀 47,891評論 2 370
  • 正文 我出身青樓舞箍,卻偏偏與公主長得像舰褪,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子疏橄,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,713評論 2 354

推薦閱讀更多精彩內(nèi)容

  • 1占拍、通過CocoaPods安裝項(xiàng)目名稱項(xiàng)目信息 AFNetworking網(wǎng)絡(luò)請求組件 FMDB本地?cái)?shù)據(jù)庫組件 SD...
    陽明先生_X自主閱讀 15,980評論 3 119
  • 一、Python簡介和環(huán)境搭建以及pip的安裝 4課時實(shí)驗(yàn)課主要內(nèi)容 【Python簡介】: Python 是一個...
    _小老虎_閱讀 5,744評論 0 10
  • 器材:華為榮耀 攝影:吉祥 后期:snapseed 歡迎拍磚哈
    吉祥在路上閱讀 289評論 4 5
  • 最近忙忙碌碌捎迫,有點(diǎn)疏于照顧孩子了晃酒,偶爾我會在腦子里掠過一絲內(nèi)疚:是否違背了初衷?還能做點(diǎn)什么來助力孩子高考窄绒?和其他...
    暫且這樣吧閱讀 1,133評論 0 0
  • 1 有些人仿佛自帶磁場彰导,總能讓與他交往的人喜歡上他蛔翅,讓別人對他好感倍增,甚至期待與他多多來往位谋。 貓叔(剽悍一只貓)...
    Mr波波閱讀 1,266評論 1 10