• <tbody id="baor6"></tbody>

  • <em id="baor6"><acronym id="baor6"><input id="baor6"></input></acronym></em>
    <strike id="baor6"></strike><li id="baor6"></li>
    <rp id="baor6"></rp>
    1. <em id="baor6"></em>
      <form id="baor6"></form>
      <nobr id="baor6"></nobr>

      <em id="baor6"><acronym id="baor6"><u id="baor6"></u></acronym></em>

          葵花寶典教程,一個自學編程平臺

          葵花寶典教程,一個自學編程平臺

          Python - 使用 C 進行擴展編程

          您使用任何編譯語言(如 C、C++ 或 Java)編寫的任何代碼都可以集成或導入到另一個 Python 腳本中。此代碼被視為“擴展”。


          Python 擴展模塊只不過是一個普通的 C 庫。在 Unix 機器上,這些庫通常以.so結尾(用于共享對象)。在 Windows 機器上,您通常會看到.dll(用于動態鏈接庫)。


          編寫擴展的先決條件

          要開始編寫擴展,您將需要 Python 頭文件。


          在 Unix 機器上,這通常需要安裝開發人員特定的包,例如python2.5-dev。


          Windows 用戶在使用二進制 Python 安裝程序時將這些標頭作為包的一部分。


          此外,假設您對 C 或 C++ 有很好的了解,可以使用 C 編程編寫任何 Python 擴展。


          先看一個 Python 擴展

          對于您第一次查看 Python 擴展模塊,您需要將您的代碼分為四部分 -


          頭文件Python.h。


          您要作為模塊接口公開的 C 函數。


          將 Python 開發人員看到的函數名稱映射到擴展模塊內的 C 函數的表。


          一個初始化函數。


          頭文件Python.h

          您需要在 C 源文件中包含Python.h頭文件,這使您可以訪問用于將模塊掛接到解釋器的內部 Python API。


          確保在您可能需要的任何其他標頭之前包含 Python.h。您需要遵循包含要從 Python 調用的函數。


          C 函數

          函數的 C 實現的簽名始終采用以下三種形式之一 -


          static PyObject *MyFunction( PyObject *self, PyObject *args );


          static PyObject *MyFunctionWithKeywords(PyObject *self,

                                           PyObject *args,

                                           PyObject *kw);


          static PyObject *MyFunctionWithNoArgs( PyObject *self );

          前面的每個聲明都返回一個 Python 對象。Python 中沒有像 C 中那樣的void函數。如果您不希望函數返回值,請返回 Python 的None值的 C 等效項。Python 頭文件定義了一個宏 Py_RETURN_NONE,它為我們做這件事。


          您的 C 函數的名稱可以是您喜歡的任何名稱,因為它們在擴展模塊之外永遠不會出現。它們被定義為靜態函數。


          您的 C 函數通常通過將 Python 模塊和函數名稱組合在一起來命名,如下所示 -


          static PyObject *module_func(PyObject *self, PyObject *args) {

             /* Do your stuff here. */

             Py_RETURN_NONE;

          }

          這是一個名為func的 Python 函數,位于模塊module中。您將把指向 C 函數的指針放入源代碼中通常出現的模塊的方法表中。


          方法對照表

          這個方法表是一個簡單的 PyMethodDef 結構數組。該結構看起來像這樣 -


          struct PyMethodDef {

             char *ml_name;

             PyCFunction ml_meth;

             int ml_flags;

             char *ml_doc;

          };

          這是該結構成員的描述 -


          ml_name - 這是 Python 解釋器在 Python 程序中使用時呈現的函數名稱。


          ml_meth - 這必須是具有前一節中描述的任何一個簽名的函數的地址。


          ml_flags - 這告訴解釋器 ml_meth 正在使用三個簽名中的哪一個。


          該標志的值通常為 METH_VARARGS。


          如果你想允許關鍵字參數進入你的函數,這個標志可以與 METH_KEYWORDS 進行按位或運算。


          這也可以具有 METH_NOARGS 值,表示您不想接受任何參數。


          ml_doc - 這是函數的文檔字符串,如果您不想寫一個,它可能是 NULL。


          該表需要使用一個標記來終止,該標記由相應成員的 NULL 和 0 值組成。


          例子

          對于上述定義的函數,我們有以下方法映射表 -


          static PyMethodDef module_methods[] = {

             { "func", (PyCFunction)module_func, METH_NOARGS, NULL },

             { NULL, NULL, 0, NULL }

          };

          初始化函數

          擴展模塊的最后一部分是初始化函數。該函數在模塊加載時由 Python 解釋器調用。需要將函數命名為init Module,其中Module是模塊的名稱。


          初始化函數需要從您將要構建的庫中導出。Python 頭文件定義 PyMODINIT_FUNC 以包含適當的咒語,以便在我們正在編譯的特定環境中發生這種情況。您所要做的就是在定義函數時使用它。


          您的 C 初始化函數通常具有以下總體結構 -


          PyMODINIT_FUNC initModule() {

             Py_InitModule3(func, module_methods, "docstring...");

          }

          這是Py_InitModule3函數的描述 -


          func - 這是要導出的函數。


          module _methods - 這是上面定義的映射表名稱。


          docstring - 這是您想在擴展中給出的評論。


          把這一切放在一起看起來像下面這樣 -


          #include <Python.h>


          static PyObject *module_func(PyObject *self, PyObject *args) {

             /* Do your stuff here. */

             Py_RETURN_NONE;

          }


          static PyMethodDef module_methods[] = {

             { "func", (PyCFunction)module_func, METH_NOARGS, NULL },

             { NULL, NULL, 0, NULL }

          };


          PyMODINIT_FUNC initModule() {

             Py_InitModule3(func, module_methods, "docstring...");

          }

          例子

          一個利用上述所有概念的簡單示例 -


          #include <Python.h>


          static PyObject* helloworld(PyObject* self) {

             return Py_BuildValue("s", "Hello, Python extensions!!");

          }


          static char helloworld_docs[] =

             "helloworld( ): Any message you want to put here!!\n";


          static PyMethodDef helloworld_funcs[] = {

             {"helloworld", (PyCFunction)helloworld, 

                METH_NOARGS, helloworld_docs},

                {NULL}

          };


          void inithelloworld(void) {

             Py_InitModule3("helloworld", helloworld_funcs,

                            "Extension module example!");

          }

          這里Py_BuildValue函數用于構建 Python 值。將上述代碼保存在 hello.c 文件中。我們將看到如何編譯和安裝這個模塊以從 Python 腳本中調用。


          構建和安裝擴展

          distutils包使以標準方式分發 Python 模塊(純 Python 模塊和擴展模塊)變得非常容易。模塊以源代碼形式分發,并通過通常稱為setup.py的安裝腳本構建和安裝,如下所示。


          對于上述模塊,您需要準備以下 setup.py 腳本 -


          from distutils.core import setup, Extension

          setup(name='helloworld', version='1.0',  \

                ext_modules=[Extension('helloworld', ['hello.c'])])

          現在,使用以下命令,它將執行所有需要的編譯和鏈接步驟,使用正確的編譯器和鏈接器命令和標志,并將生成的動態庫復制到適當的目錄 -


          $ python setup.py install

          在基于 Unix 的系統上,您很可能需要以 root 身份運行此命令才能獲得寫入站點包目錄的權限。這在 Windows 上通常不是問題。


          導入擴展

          安裝擴展后,您將能夠在 Python 腳本中導入和調用該擴展,如下所示 -


          #!/usr/bin/python

          import helloworld


          print helloworld.helloworld()

          這將產生以下結果 -


          Hello, Python extensions!!

          傳遞函數參數

          由于您很可能希望定義接受參數的函數,因此您可以為您的 C 函數使用其他簽名之一。例如,接受一些參數的以下函數將被定義如下 -


          static PyObject *module_func(PyObject *self, PyObject *args) {

             /* Parse args and do something interesting here. */

             Py_RETURN_NONE;

          }

          包含新函數條目的方法表如下所示 -


          static PyMethodDef module_methods[] = {

             { "func", (PyCFunction)module_func, METH_NOARGS, NULL },

             { "func", module_func, METH_VARARGS, NULL },

             { NULL, NULL, 0, NULL }

          };

          您可以使用 API PyArg_ParseTuple函數從傳遞給 C 函數的一個 PyObject 指針中提取參數。


          PyArg_ParseTuple 的第一個參數是 args 參數。這是您將要解析的對象。第二個參數是一個格式字符串,描述您希望它們出現的參數。每個參數由格式字符串中的一個或多個字符表示,如下所示。


          static PyObject *module_func(PyObject *self, PyObject *args) {

             int i;

             double d;

             char *s;


             if (!PyArg_ParseTuple(args, "ids", &i, &d, &s)) {

                return NULL;

             }

             

             /* Do something interesting here. */

             Py_RETURN_NONE;

          }

          編譯模塊的新版本并導入它使您能夠使用任意數量的任何類型的參數調用新函數 -


          module.func(1, s="three", d=2.0)

          module.func(i=1, d=2.0, s="three")

          module.func(s="three", d=2.0, i=1)

          你可能會想出更多的變化。


          PyArg_ParseTuple函數_

          這是PyArg_ParseTuple函數的標準簽名 -


          int PyArg_ParseTuple(PyObject* tuple,char* format,...)

          此函數返回 0 表示錯誤,不等于 0 的值表示成功。tuple 是 PyObject*,它是 C 函數的第二個參數。這里的格式是一個描述強制和可選參數的 C 字符串。


          這是PyArg_ParseTuple函數的格式代碼列表 -


          代碼 C型 意義

          C 字符 長度為 1 的 Python 字符串變為 C 字符。

          d 雙倍的 Python float 變成了 C double。

          F 漂浮 Python 浮點數變成了 C 浮點數。

          一世 整數 Python int 變成了 C int。

          l Python int 變成了 C long。

          大號 長長的 Python int 變成 C long long

          PyObject* 獲取對 Python 參數的非 NULL 借用引用。

          s 字符* 沒有嵌入 C char* 的空值的 Python 字符串。

          ## 字符*+整數 任何 Python 字符串到 C 地址和長度。

          ## 字符*+整數 只讀單段緩沖區到 C 地址和長度。

          Py_UNICODE* Python Unicode 沒有嵌入到 C 中的空值。

          你# Py_UNICODE*+int 任何 Python Unicode C 地址和長度。

          # 字符*+整數 讀/寫單段緩沖區到 C 地址和長度。

          z 字符* 與 s 一樣,也接受 None(將 C char* 設置為 NULL)。

          z# 字符*+整數 與 s# 一樣,也接受 None(將 C char* 設置為 NULL)。

          (...) 按照 ... Python 序列被視為每個項目的一個參數。

          | 以下參數是可選的。

          格式結束,后跟錯誤消息的函數名稱。

          ; 格式結束,后跟整個錯誤消息文本。

          返回值

          Py_BuildValue采用與PyArg_ParseTuple非常相似的格式字符串。不是傳入正在構建的值的地址,而是傳入實際值。這是一個顯示如何實現添加功能的示例 -


          static PyObject *foo_add(PyObject *self, PyObject *args) {

             int a;

             int b;


             if (!PyArg_ParseTuple(args, "ii", &a, &b)) {

                return NULL;

             }

             return Py_BuildValue("i", a + b);

          }

          如果在 Python 中實現,這就是它的樣子 -


          def add(a, b):

             return (a + b)

          您可以從函數中返回兩個值,如下所示,這將在 Python 中使用列表進行捕獲。


          static PyObject *foo_add_subtract(PyObject *self, PyObject *args) {

             int a;

             int b;


             if (!PyArg_ParseTuple(args, "ii", &a, &b)) {

                return NULL;

             }

             return Py_BuildValue("ii", a + b, a - b);

          }

          如果在 Python 中實現,這就是它的樣子 -


          def add_subtract(a, b):

             return (a + b, a - b)

          Py_BuildValue函數_

          這是Py_BuildValue函數的標準簽名 -


          PyObject* Py_BuildValue(char* format,...)

          這里的格式是一個描述要構建的 Python 對象的 C 字符串。Py_BuildValue的以下參數是從中構建結果的 C 值。PyObject *結果是一個新的參考。


          下表列出了常用的代碼字符串,其中零個或多個連接成字符串格式。


          代碼 C型 意義

          C 字符 AC char 變成長度為 1 的 Python 字符串。

          d 雙倍的 AC double 成為 Python 浮點數。

          F 漂浮 AC 浮點數變成了 Python 浮點數。

          一世 整數 AC int 成為 Python int。

          l AC long 成為 Python int。

          ? PyObject* 傳遞一個 Python 對象并竊取一個引用。

          PyObject* 傳遞一個 Python 對象并像往常一樣對其進行 INCREF。

          歐& 轉換+無效* 任意轉換

          s 字符* C 以 0 結尾的 char* 到 Python 字符串,或 NULL 到 None。

          ## 字符*+整數 C char* 和長度為 Python 字符串,或 NULL 為無。

          Py_UNICODE* C 范圍的、以 null 結尾的字符串到 Python Unicode,或 NULL 到 None。

          你# Py_UNICODE*+int C 范圍的字符串和長度到 Python Unicode,或 NULL 到 None。

          # 字符*+整數 讀/寫單段緩沖區到 C 地址和長度。

          z 字符* 與 s 一樣,也接受 None(將 C char* 設置為 NULL)。

          z# 字符*+整數 與 s# 一樣,也接受 None(將 C char* 設置為 NULL)。

          (...) 按照 ... 從 C 值構建 Python 元組。

          [...] 按照 ... 從 C 值構建 Python 列表。

          {...} 按照 ... 從 C 值、交替鍵和值構建 Python 字典。

          代碼 {...} 從偶數個 C 值(交替鍵和值)構建字典。例如,Py_BuildValue("{issi}",23,"zig","zag",42) 返回類似于 Python 的 {23:'zig','zag':42} 的字典。


          Python - GUI 編程 (Tkinter)

          Python 提供了各種用于開發圖形用戶界面 (GUI) 的選項。下面列出了最重要的。


          Tkinter - Tkinter 是 Python 隨附的 Tk GUI 工具包的 Python 接口。我們將在本章中查看此選項。


          wxPython - 這是 wxWindows http://wxpython.org的開源 Python 接口。


          JPython - JPython 是 Java 的 Python 端口,它使 Python 腳本可以無縫訪問本地機器http://www.jython.org上的 Java 類庫。


          還有許多其他可用的接口,您可以在網上找到它們。


          Tkinter 編程

          Tkinter 是 Python 的標準 GUI 庫。Python 與 Tkinter 結合使用提供了一種快速簡便的方式來創建 GUI 應用程序。Tkinter 為 Tk GUI 工具包提供了一個強大的面向對象接口。


          使用 Tkinter 創建 GUI 應用程序是一項簡單的任務。您需要做的就是執行以下步驟 -


          導入Tkinter模塊。


          創建 GUI 應用程序主窗口。


          將一個或多個上述小部件添加到 GUI 應用程序。


          進入主事件循環以針對用戶觸發的每個事件采取行動。


          例子

          #!/usr/bin/python


          import Tkinter

          top = Tkinter.Tk()

          # Code to add widgets will go here...

          top.mainloop()

          這將創建一個以下窗口 -


          傳統知識窗口

          Tkinter 小部件

          Tkinter 提供各種控件,例如 GUI 應用程序中使用的按鈕、標簽和文本框。這些控件通常稱為小部件。


          Tkinter 目前有 15 種類型的小部件。我們在下表中介紹了這些小部件以及簡要說明 -


          編號 運營商和描述

          1 按鈕

          Button 小部件用于在您的應用程序中顯示按鈕。


          2 帆布

          Canvas 小部件用于在您的應用程序中繪制形狀,例如線條、橢圓、多邊形和矩形。


          3 復選按鈕

          Checkbutton 小部件用于將許多選項顯示為復選框。用戶可以一次選擇多個選項。


          4 入口

          Entry 小部件用于顯示單行文本字段以接受來自用戶的值。


          5 框架

          Frame 小部件用作容器小部件來組織其他小部件。


          6 標簽

          Label 小部件用于為其他小部件提供單行標題。它還可以包含圖像。


          7 列表框

          Listbox 小部件用于向用戶提供選項列表。


          8 菜單按鈕

          Menubutton 小部件用于在應用程序中顯示菜單。


          9 菜單

          Menu 小部件用于向用戶提供各種命令。這些命令包含在 Menubutton 中。


          10 信息

          Message 小部件用于顯示多行文本字段以接受來自用戶的值。


          11 單選按鈕

          Radiobutton 小部件用于將許多選項顯示為單選按鈕。用戶一次只能選擇一個選項。


          12 規模

          Scale 小部件用于提供滑塊小部件。


          13 滾動條

          滾動條小部件用于向各種小部件(例如列表框)添加滾動功能。


          14 文本

          Text 小部件用于在多行中顯示文本。


          15 頂層

          Toplevel 小部件用于提供單獨的窗口容器。


          16 紡紗箱

          Spinbox 小部件是標準 Tkinter Entry 小部件的變體,可用于從固定數量的值中進行選擇。


          17 窗格窗口

          PanedWindow 是一個容器小部件,可以包含任意數量的窗格,水平或垂直排列。


          18 標簽框

          labelframe 是一個簡單的容器小部件。它的主要目的是充當復雜窗口布局的間隔器或容器。


          19 tkMessageBox

          該模塊用于在您的應用程序中顯示消息框。


          讓我們詳細研究這些小部件 -


          標準屬性

          讓我們看看它們的一些共同屬性是如何指定的,例如大小、顏色和字體。


          方面


          顏色


          字體


          錨點


          浮雕樣式


          位圖


          光標


          讓我們簡要研究一下 -


          幾何管理

          所有 Tkinter 小部件都可以訪問特定的幾何管理方法,這些方法的目的是在整個父小部件區域中組織小部件。Tkinter 公開了以下幾何管理器類:pack、grid 和 place。


          Pack()方法- 此幾何管理器在將小部件放置在父小部件中之前將小部件組織在塊中。


          grid()方法- 此幾何管理器在父小部件中以類似表格的結構組織小部件。


          place()方法- 此幾何管理器通過將小部件放置在父小部件中的特定位置來組織小部件。


          讓我們簡要研究幾何管理方法 -


          Python - XML 處理

          XML 是一種可移植的開源語言,它允許程序員開發可由其他應用程序讀取的應用程序,而不管操作系統和/或開發語言如何。


          什么是 XML?

          可擴展標記語言 (XML) 是一種與 HTML 或 SGML 非常相似的標記語言。這是萬維網聯盟推薦的,可作為開放標準使用。


          XML 對于跟蹤中小型數據量非常有用,無需基于 SQL 的主干。


          XML 解析器架構和 API

          Python 標準庫提供了一組最小但有用的接口來處理 XML。


          XML 數據的兩個最基本和最廣泛使用的 API 是 SAX 和 DOM 接口。


          Simple API for XML (SAX) - 在這里,您為感興趣的事件注冊回調,然后讓解析器繼續處理文檔。當您的文檔很大或您有內存限制時,這很有用,它會在從磁盤讀取文件時解析文件,并且整個文件永遠不會存儲在內存中。


          文檔對象模型 (DOM) API - 這是萬維網聯盟的建議,其中將整個文件讀入內存并以分層(基于樹的)形式存儲,以表示 XML 文檔的所有特征。


          在處理大文件時,SAX 顯然無法像 DOM 那樣快速處理信息。另一方面,僅使用 DOM 確實會殺死您的資源,尤其是在大量小文件上使用時。


          SAX 是只讀的,而 DOM 允許更改 XML 文件。由于這兩個不同的 API 實際上是相互補充的,所以沒有理由不能將它們都用于大型項目。


          對于我們所有的 XML 代碼示例,讓我們使用一個簡單的 XML 文件movies.xml作為輸入 -


          <collection shelf="New Arrivals">

          <movie title="Enemy Behind">

             <type>War, Thriller</type>

             <format>DVD</format>

             <year>2003</year>

             <rating>PG</rating>

             <stars>10</stars>

             <description>Talk about a US-Japan war</description>

          </movie>

          <movie title="Transformers">

             <type>Anime, Science Fiction</type>

             <format>DVD</format>

             <year>1989</year>

             <rating>R</rating>

             <stars>8</stars>

             <description>A schientific fiction</description>

          </movie>

             <movie title="Trigun">

             <type>Anime, Action</type>

             <format>DVD</format>

             <episodes>4</episodes>

             <rating>PG</rating>

             <stars>10</stars>

             <description>Vash the Stampede!</description>

          </movie>

          <movie title="Ishtar">

             <type>Comedy</type>

             <format>VHS</format>

             <rating>PG</rating>

             <stars>2</stars>

             <description>Viewable boredom</description>

          </movie>

          </collection>

          使用 SAX API 解析 XML

          SAX 是事件驅動的 XML 解析的標準接口。使用 SAX 解析 XML 通常需要您通過子類化 xml.sax.ContentHandler 創建自己的 ContentHandler。


          您的ContentHandler處理您的 XML 風格的特定標簽和屬性。ContentHandler 對象提供了處理各種解析事件的方法。它擁有的解析器在解析 XML 文件時調用 ContentHandler 方法。


          在 XML 文件的開頭和結尾調用方法startDocument和endDocument 。方法characters(text)通過參數text 傳遞XML 文件的字符數據。


          ContentHandler 在每個元素的開始和結束處被調用。如果解析器不處于命名空間模式,則調用方法startElement(tag, attributes)和endElement(tag);否則,調用相應的方法startElementNS和endElementNS。這里,tag 是元素標簽,attributes 是一個 Attributes 對象。


          以下是在繼續之前要了解的其他重要方法 -


          make_parser方法_

          以下方法創建一個新的解析器對象并返回它。創建的解析器對象將是系統找到的第一個解析器類型。


          xml.sax.make_parser( [parser_list] )

          這是參數的詳細信息 -


          parser_list - 可選參數,由要使用的解析器列表組成,這些解析器必須全部實現 make_parser 方法。


          解析方法_

          以下方法創建一個 SAX 解析器并使用它來解析文檔。


          xml.sax.parse( xmlfile, contenthandler[, errorhandler])

          這是參數的詳細信息 -


          xmlfile - 這是要讀取的 XML 文件的名稱。


          contenthandler - 這必須是一個 ContentHandler 對象。


          errorhandler - 如果指定,errorhandler 必須是 SAX ErrorHandler 對象。


          parseString方法_

          還有另一種方法可以創建 SAX 解析器并解析指定的XML 字符串。


          xml.sax.parseString(xmlstring, contenthandler[, errorhandler])

          這是參數的詳細信息 -


          xmlstring - 這是要讀取的 XML 字符串的名稱。


          contenthandler - 這必須是一個 ContentHandler 對象。


          errorhandler - 如果指定,errorhandler 必須是 SAX ErrorHandler 對象。


          例子

          #!/usr/bin/python


          import xml.sax


          class MovieHandler( xml.sax.ContentHandler ):

             def __init__(self):

                self.CurrentData = ""

                self.type = ""

                self.format = ""

                self.year = ""

                self.rating = ""

                self.stars = ""

                self.description = ""


             # Call when an element starts

             def startElement(self, tag, attributes):

                self.CurrentData = tag

                if tag == "movie":

                   print "*****Movie*****"

                   title = attributes["title"]

                   print "Title:", title


             # Call when an elements ends

             def endElement(self, tag):

                if self.CurrentData == "type":

                   print "Type:", self.type

                elif self.CurrentData == "format":

                   print "Format:", self.format

                elif self.CurrentData == "year":

                   print "Year:", self.year

                elif self.CurrentData == "rating":

                   print "Rating:", self.rating

                elif self.CurrentData == "stars":

                   print "Stars:", self.stars

                elif self.CurrentData == "description":

                   print "Description:", self.description

                self.CurrentData = ""


             # Call when a character is read

             def characters(self, content):

                if self.CurrentData == "type":

                   self.type = content

                elif self.CurrentData == "format":

                   self.format = content

                elif self.CurrentData == "year":

                   self.year = content

                elif self.CurrentData == "rating":

                   self.rating = content

                elif self.CurrentData == "stars":

                   self.stars = content

                elif self.CurrentData == "description":

                   self.description = content

            

          if ( __name__ == "__main__"):

             

             # create an XMLReader

             parser = xml.sax.make_parser()

             # turn off namepsaces

             parser.setFeature(xml.sax.handler.feature_namespaces, 0)


             # override the default ContextHandler

             Handler = MovieHandler()

             parser.setContentHandler( Handler )

             

             parser.parse("movies.xml")

          這將產生以下結果 -


          *****Movie*****

          Title: Enemy Behind

          Type: War, Thriller

          Format: DVD

          Year: 2003

          Rating: PG

          Stars: 10

          Description: Talk about a US-Japan war

          *****Movie*****

          Title: Transformers

          Type: Anime, Science Fiction

          Format: DVD

          Year: 1989

          Rating: R

          Stars: 8

          Description: A schientific fiction

          *****Movie*****

          Title: Trigun

          Type: Anime, Action

          Format: DVD

          Rating: PG

          Stars: 10

          Description: Vash the Stampede!

          *****Movie*****

          Title: Ishtar

          Type: Comedy

          Format: VHS

          Rating: PG

          Stars: 2

          Description: Viewable boredom

          有關 SAX API 文檔的完整詳細信息,請參閱標準Python SAX API。


          使用 DOM API 解析 XML

          文檔對象模型 (“DOM”) 是萬維網聯盟 (W3C) 的跨語言 API,用于訪問和修改 XML 文檔。


          DOM 對于隨機訪問應用程序非常有用。SAX 一次只允許您查看文檔的一個位。如果您正在查看一個 SAX 元素,則無法訪問另一個元素。


          這是快速加載 XML 文檔和使用 xml.dom 模塊創建 minidom 對象的最簡單方法。minidom 對象提供了一個簡單的解析器方法,可以從 XML 文件快速創建一個 DOM 樹。


          樣例語句調用minidom對象的parse(file[,parser])函數,將file指定的XML文件解析成DOM樹對象。


          #!/usr/bin/python


          from xml.dom.minidom import parse

          import xml.dom.minidom


          # Open XML document using minidom parser

          DOMTree = xml.dom.minidom.parse("movies.xml")

          collection = DOMTree.documentElement

          if collection.hasAttribute("shelf"):

             print "Root element : %s" % collection.getAttribute("shelf")


          # Get all the movies in the collection

          movies = collection.getElementsByTagName("movie")


          # Print detail of each movie.

          for movie in movies:

             print "*****Movie*****"

             if movie.hasAttribute("title"):

                print "Title: %s" % movie.getAttribute("title")


             type = movie.getElementsByTagName('type')[0]

             print "Type: %s" % type.childNodes[0].data

             format = movie.getElementsByTagName('format')[0]

             print "Format: %s" % format.childNodes[0].data

             rating = movie.getElementsByTagName('rating')[0]

             print "Rating: %s" % rating.childNodes[0].data

             description = movie.getElementsByTagName('description')[0]

             print "Description: %s" % description.childNodes[0].data

          這將產生以下結果 -


          Root element : New Arrivals

          *****Movie*****

          Title: Enemy Behind

          Type: War, Thriller

          Format: DVD

          Rating: PG

          Description: Talk about a US-Japan war

          *****Movie*****

          Title: Transformers

          Type: Anime, Science Fiction

          Format: DVD

          Rating: R

          Description: A schientific fiction

          *****Movie*****

          Title: Trigun

          Type: Anime, Action

          Format: DVD

          Rating: PG

          Description: Vash the Stampede!

          *****Movie*****

          Title: Ishtar

          Type: Comedy

          Format: VHS

          Rating: PG

          Description: Viewable boredom

          有關 DOM API 文檔的完整詳細信息,請參閱標準Python DOM API


          Python - 多線程編程

          運行多個線程類似于同時運行多個不同的程序,但具有以下好處 -


          一個進程中的多個線程與主線程共享相同的數據空間,因此可以比單獨的進程更容易地共享信息或相互通信。


          線程有時稱為輕量級進程,它們不需要太多內存開銷;它們比工藝便宜。


          一個線程有一個開始、一個執行順序和一個結束。它有一個指令指針,用于跟蹤它當前在其上下文中運行的位置。


          它可以被搶占(中斷)


          它可以在其他線程運行時暫時擱置(也稱為休眠) - 這稱為屈服。


          開始一個新線程

          要生成另一個線程,您需要調用線程模塊中可用的以下方法 -


          thread.start_new_thread ( function, args[, kwargs] )

          此方法調用支持在 Linux 和 Windows 中快速有效地創建新線程。


          方法調用立即返回,子線程啟動并使用傳遞的args列表調用函數。當函數返回時,線程終止。


          這里,args是一個參數元組;使用空元組調用函數而不傳遞任何參數。kwargs是關鍵字參數的可選字典。


          例子

          #!/usr/bin/python


          import thread

          import time


          # Define a function for the thread

          def print_time( threadName, delay):

             count = 0

             while count < 5:

                time.sleep(delay)

                count += 1

                print "%s: %s" % ( threadName, time.ctime(time.time()) )


          # Create two threads as follows

          try:

             thread.start_new_thread( print_time, ("Thread-1", 2, ) )

             thread.start_new_thread( print_time, ("Thread-2", 4, ) )

          except:

             print "Error: unable to start thread"


          while 1:

             pass

          執行上述代碼時,會產生以下結果 -


          Thread-1: Thu Jan 22 15:42:17 2009

          Thread-1: Thu Jan 22 15:42:19 2009

          Thread-2: Thu Jan 22 15:42:19 2009

          Thread-1: Thu Jan 22 15:42:21 2009

          Thread-2: Thu Jan 22 15:42:23 2009

          Thread-1: Thu Jan 22 15:42:23 2009

          Thread-1: Thu Jan 22 15:42:25 2009

          Thread-2: Thu Jan 22 15:42:27 2009

          Thread-2: Thu Jan 22 15:42:31 2009

          Thread-2: Thu Jan 22 15:42:35 2009

          雖然它對于低級線程非常有效,但是與較新的線程模塊相比,線程模塊非常有限。


          線程模塊_

          Python 2.4 中包含的較新的線程模塊為線程提供了比上一節中討論的線程模塊更強大、更高級的支持。


          threading模塊公開了thread模塊的所有方法并提供了一些額外的方法 -


          threading.activeCount() - 返回活動線程對象的數量。


          threading.currentThread() - 返回調用者線程控制中線程對象的數量。


          threading.enumerate() - 返回當前活動的所有線程對象的列表。


          除了方法之外,threading 模塊還有實現線程的Thread類。Thread類提供的方法如下 -


          run() - run() 方法是線程的入口點。


          start() - start() 方法通過調用 run 方法啟動線程。


          join([time]) - join() 等待線程終止。


          isAlive() - isAlive() 方法檢查線程是否仍在執行。


          getName() - getName() 方法返回線程的名稱。


          setName() - setName() 方法設置線程的名稱。


          使用線程模塊創建線程

          要使用 threading 模塊實現新線程,您必須執行以下操作 -


          定義Thread類的新子類。


          覆蓋__init__(self [,args])方法以添加其他參數。


          然后,重寫 run(self [,args]) 方法來實現線程在啟動時應該做什么。


          一旦你創建了新的Thread子類,你就可以創建它的一個實例,然后通過調用start()來啟動一個新線程,然后調用run()方法。


          例子

          #!/usr/bin/python


          import threading

          import time


          exitFlag = 0


          class myThread (threading.Thread):

             def __init__(self, threadID, name, counter):

                threading.Thread.__init__(self)

                self.threadID = threadID

                self.name = name

                self.counter = counter

             def run(self):

                print "Starting " + self.name

                print_time(self.name, 5, self.counter)

                print "Exiting " + self.name


          def print_time(threadName, counter, delay):

             while counter:

                if exitFlag:

                   threadName.exit()

                time.sleep(delay)

                print "%s: %s" % (threadName, time.ctime(time.time()))

                counter -= 1


          # Create new threads

          thread1 = myThread(1, "Thread-1", 1)

          thread2 = myThread(2, "Thread-2", 2)


          # Start new Threads

          thread1.start()

          thread2.start()


          print "Exiting Main Thread"

          執行上述代碼時,會產生以下結果 -


          Starting Thread-1

          Starting Thread-2

          Exiting Main Thread

          Thread-1: Thu Mar 21 09:10:03 2013

          Thread-1: Thu Mar 21 09:10:04 2013

          Thread-2: Thu Mar 21 09:10:04 2013

          Thread-1: Thu Mar 21 09:10:05 2013

          Thread-1: Thu Mar 21 09:10:06 2013

          Thread-2: Thu Mar 21 09:10:06 2013

          Thread-1: Thu Mar 21 09:10:07 2013

          Exiting Thread-1

          Thread-2: Thu Mar 21 09:10:08 2013

          Thread-2: Thu Mar 21 09:10:10 2013

          Thread-2: Thu Mar 21 09:10:12 2013

          Exiting Thread-2

          同步線程

          Python 提供的線程模塊包括一個易于實現的鎖定機制,允許您同步線程。通過調用Lock()方法創建一個新鎖,該方法返回新鎖。


          新鎖對象的acquire(blocking)方法用于強制線程同步運行??蛇x的阻塞參數使您能夠控制線程是否等待獲取鎖。


          如果阻塞設置為 0,則如果無法獲取鎖,則線程立即返回 0 值,如果獲取了鎖,則返回 1。如果blocking設置為1,線程阻塞并等待鎖被釋放。


          新鎖對象的release()方法用于在不再需要鎖時釋放鎖。


          例子

          #!/usr/bin/python


          import threading

          import time


          class myThread (threading.Thread):

             def __init__(self, threadID, name, counter):

                threading.Thread.__init__(self)

                self.threadID = threadID

                self.name = name

                self.counter = counter

             def run(self):

                print "Starting " + self.name

                # Get lock to synchronize threads

                threadLock.acquire()

                print_time(self.name, self.counter, 3)

                # Free lock to release next thread

                threadLock.release()


          def print_time(threadName, delay, counter):

             while counter:

                time.sleep(delay)

                print "%s: %s" % (threadName, time.ctime(time.time()))

                counter -= 1


          threadLock = threading.Lock()

          threads = []


          # Create new threads

          thread1 = myThread(1, "Thread-1", 1)

          thread2 = myThread(2, "Thread-2", 2)


          # Start new Threads

          thread1.start()

          thread2.start()


          # Add threads to thread list

          threads.append(thread1)

          threads.append(thread2)


          # Wait for all threads to complete

          for t in threads:

              t.join()

          print "Exiting Main Thread"

          執行上述代碼時,會產生以下結果 -


          Starting Thread-1

          Starting Thread-2

          Thread-1: Thu Mar 21 09:11:28 2013

          Thread-1: Thu Mar 21 09:11:29 2013

          Thread-1: Thu Mar 21 09:11:30 2013

          Thread-2: Thu Mar 21 09:11:32 2013

          Thread-2: Thu Mar 21 09:11:34 2013

          Thread-2: Thu Mar 21 09:11:36 2013

          Exiting Main Thread

          多線程優先隊列

          Queue模塊允許您創建一個新的隊列對象,該對象可以容納特定數量的項目。有以下方法來控制隊列 -


          get() - get() 從隊列中刪除并返回一個項目。


          put() - put 將項目添加到隊列中。


          qsize() - qsize() 返回當前隊列中的項目數。


          empty() - 如果隊列為空,則 empty() 返回 True;否則為假。


          full() - 如果隊列已滿,則 full() 返回 True;否則為假。


          例子

          #!/usr/bin/python


          import Queue

          import threading

          import time


          exitFlag = 0


          class myThread (threading.Thread):

             def __init__(self, threadID, name, q):

                threading.Thread.__init__(self)

                self.threadID = threadID

                self.name = name

                self.q = q

             def run(self):

                print "Starting " + self.name

                process_data(self.name, self.q)

                print "Exiting " + self.name


          def process_data(threadName, q):

             while not exitFlag:

                queueLock.acquire()

                   if not workQueue.empty():

                      data = q.get()

                      queueLock.release()

                      print "%s processing %s" % (threadName, data)

                   else:

                      queueLock.release()

                   time.sleep(1)


          threadList = ["Thread-1", "Thread-2", "Thread-3"]

          nameList = ["One", "Two", "Three", "Four", "Five"]

          queueLock = threading.Lock()

          workQueue = Queue.Queue(10)

          threads = []

          threadID = 1


          # Create new threads

          for tName in threadList:

             thread = myThread(threadID, tName, workQueue)

             thread.start()

             threads.append(thread)

             threadID += 1


          # Fill the queue

          queueLock.acquire()

          for word in nameList:

             workQueue.put(word)

          queueLock.release()


          # Wait for queue to empty

          while not workQueue.empty():

             pass


          # Notify threads it's time to exit

          exitFlag = 1


          # Wait for all threads to complete

          for t in threads:

             t.join()

          print "Exiting Main Thread"

          執行上述代碼時,會產生以下結果 -


          Starting Thread-1

          Starting Thread-2

          Starting Thread-3

          Thread-1 processing One

          Thread-2 processing Two

          Thread-3 processing Three

          Thread-1 processing Four

          Thread-2 processing Five

          Exiting Thread-3

          Exiting Thread-1

          Exiting Thread-2

          Exiting Main Thread


          Python - 使用 SMTP 發送電子郵件

          簡單郵件傳輸協議 (SMTP) 是一種協議,用于處理在郵件服務器之間發送電子郵件和路由電子郵件。


          Python 提供了smtplib模塊,該模塊定義了一個 SMTP 客戶端會話對象,該對象可用于將郵件發送到具有 SMTP 或 ESMTP 偵聽器守護程序的任何 Internet 機器。


          這是創建一個 SMTP 對象的簡單語法,稍后可用于發送電子郵件 -


          import smtplib


          smtpObj = smtplib.SMTP( [host [, port [, local_hostname]]] )

          這是參數的詳細信息 -


          host - 這是運行 SMTP 服務器的主機。您可以指定主機的 IP 地址或域名,如 tutorialspoint.com。這是可選參數。


          port - 如果您提供主機參數,那么您需要指定一個端口,SMTP 服務器正在偵聽該端口。通常這個端口是 25。


          local_hostname - 如果您的 SMTP 服務器在本地計算機上運行,那么您可以在此選項中僅指定localhost。


          SMTP 對象有一個名為sendmail的實例方法,通常用于完成郵寄消息的工作。它需要三個參數 -


          發件人- 帶有發件人地址的字符串。


          接收者- 字符串列表,每個接收者一個。


          消息- 作為字符串的消息,格式為各種 RFC 中指定的格式。


          例子

          這是使用 Python 腳本發送一封電子郵件的簡單方法。嘗試一次 -


          #!/usr/bin/python


          import smtplib


          sender = 'from@fromdomain.com'

          receivers = ['to@todomain.com']


          message = """From: From Person <from@fromdomain.com>

          To: To Person <to@todomain.com>

          Subject: SMTP e-mail test


          This is a test e-mail message.

          """


          try:

             smtpObj = smtplib.SMTP('localhost')

             smtpObj.sendmail(sender, receivers, message)         

             print "Successfully sent email"

          except SMTPException:

             print "Error: unable to send email"

          在這里,您在消息中放置了一個基本的電子郵件,使用三引號,注意正確格式化標題。電子郵件需要From、To和Subject標頭,并用空行與電子郵件正文分開。


          要發送郵件,您可以使用smtpObj連接到本地計算機上的 SMTP 服務器,然后使用sendmail方法以及消息、發件人地址和目標地址作為參數(即使發件人地址和發件人地址在 e -mail 本身,這些并不總是用于路由郵件)。


          如果您沒有在本地計算機上運行 SMTP 服務器,則可以使用smtplib客戶端與遠程 SMTP 服務器進行通信。除非您使用網絡郵件服務(例如 Hotmail 或 Yahoo! Mail),否則您的電子郵件提供商必須向您提供您可以提供的外發郵件服務器詳細信息,如下所示 -


          smtplib.SMTP('mail.your-domain.com', 25)

          使用 Python 發送 HTML 電子郵件

          當您使用 Python 發送文本消息時,所有內容都被視為簡單文本。即使您在文本消息中包含 HTML 標記,它也會顯示為簡單文本,并且 HTML 標記不會根據 HTML 語法進行格式化。但是 Python 提供了將 HTML 消息作為實際 HTML 消息發送的選項。


          發送電子郵件時,您可以指定 Mime 版本、內容類型和字符集以發送 HTML 電子郵件。


          例子

          以下是將 HTML 內容作為電子郵件發送的示例。嘗試一次 -


          #!/usr/bin/python


          import smtplib


          message = """From: From Person <from@fromdomain.com>

          To: To Person <to@todomain.com>

          MIME-Version: 1.0

          Content-type: text/html

          Subject: SMTP HTML e-mail test


          This is an e-mail message to be sent in HTML format


          <b>This is HTML message.</b>

          <h1>This is headline.</h1>

          """


          try:

             smtpObj = smtplib.SMTP('localhost')

             smtpObj.sendmail(sender, receivers, message)         

             print "Successfully sent email"

          except SMTPException:

             print "Error: unable to send email"

          以電子郵件形式發送附件

          要發送包含混合內容的電子郵件,需要將Content-type標頭設置為multipart/mixed。然后,可以在邊界內指定文本和附件部分。


          邊界以兩個連字符開頭,后跟一個唯一編號,該編號不能出現在電子郵件的消息部分中。表示電子郵件最后部分的最后邊界也必須以兩個連字符結尾。


          附加文件應使用pack("m")函數進行編碼,以便在傳輸前進行 base64 編碼。


          例子

          以下是示例,它將文件/tmp/test.txt作為附件發送。嘗試一次 -


          #!/usr/bin/python


          import smtplib

          import base64


          filename = "/tmp/test.txt"


          # Read a file and encode it into base64 format

          fo = open(filename, "rb")

          filecontent = fo.read()

          encodedcontent = base64.b64encode(filecontent)  # base64


          sender = 'webmaster@tutorialpoint.com'

          reciever = 'amrood.admin@gmail.com'


          marker = "AUNIQUEMARKER"


          body ="""

          This is a test email to send an attachement.

          """

          # Define the main headers.

          part1 = """From: From Person <me@fromdomain.net>

          To: To Person <amrood.admin@gmail.com>

          Subject: Sending Attachement

          MIME-Version: 1.0

          Content-Type: multipart/mixed; boundary=%s

          --%s

          """ % (marker, marker)


          # Define the message action

          part2 = """Content-Type: text/plain

          Content-Transfer-Encoding:8bit


          %s

          --%s

          """ % (body,marker)


          # Define the attachment section

          part3 = """Content-Type: multipart/mixed; name=\"%s\"

          Content-Transfer-Encoding:base64

          Content-Disposition: attachment; filename=%s


          %s

          --%s--

          """ %(filename, filename, encodedcontent, marker)

          message = part1 + part2 + part3


          try:

             smtpObj = smtplib.SMTP('localhost')

             smtpObj.sendmail(sender, reciever, message)

             print "Successfully sent email"

          except Exception:

             print "Error: unable to send email"


          Python - 網絡編程

          Python 提供了對網絡服務的兩個級別的訪問。在底層,您可以訪問底層操作系統中的基本套接字支持,這允許您為面向連接和無連接協議實現客戶端和服務器。


          Python 也有提供對特定應用程序級網絡協議(如 FTP、HTTP 等)的更高級別訪問的庫。


          本章讓您了解網絡中最著名的概念——套接字編程。


          什么是套接字?

          套接字是雙向通信通道的端點。套接字可以在進程內、同一臺機器上的進程之間或不同大陸上的進程之間進行通信。


          套接字可以通過多種不同的通道類型實現:Unix 域套接字、TCP、UDP 等等。套接字庫提供了用于處理公共傳輸的特定類以及用于處理其余部分的通用接口。


          套接字有自己的詞匯 -


          編號 術語和說明

          1

          領域


          用作傳輸機制的協議族。這些值是常量,例如 AF_INET、PF_INET、PF_UNIX、PF_X25 等。


          2

          類型


          兩個端點之間的通信類型,通常 SOCK_STREAM 用于面向連接的協議,SOCK_DGRAM 用于無連接協議。


          3

          協議


          通常為零,這可用于識別域和類型內的協議變體。


          4

          主機名


          網絡接口的標識符 -


          一個字符串,可以是主機名、點分四組地址或冒號(也可能是點)表示法的 IPV6 地址


          一個字符串“<broadcast>”,它指定一個 INADDR_BROADCAST 地址。


          一個零長度字符串,它指定 INADDR_ANY,或


          一個整數,解釋為主機字節順序的二進制地址。


          5

          港口


          每臺服務器都偵聽調用一個或多個端口的客戶端。端口可以是 Fixnum 端口號、包含端口號的字符串或服務名稱。


          插座模塊_

          要創建套接字,您必須使用套接字模塊中可用的socket.socket()函數,該函數具有一般語法 -


          s = socket.socket (socket_family, socket_type, protocol=0)

          這是參數的描述 -


          socket_family - 如前所述,這是 AF_UNIX 或 AF_INET。


          socket_type - 這是 SOCK_STREAM 或 SOCK_DGRAM。


          協議- 這通常被忽略,默認為 0。


          一旦你有了套接字對象,你就可以使用所需的函數來創建你的客戶端或服務器程序。以下是所需的功能列表 -


          服務器套接字方法

          編號 方法和說明

          1

          s.bind()


          此方法將地址(主機名、端口號對)綁定到套接字。


          2

          s.listen()


          此方法設置并啟動 TCP 偵聽器。


          3

          s.accept()


          這被動地接受 TCP 客戶端連接,等待連接到達(阻塞)。


          客戶端套接字方法

          編號 方法和說明

          1

          s.connect()


          該方法主動發起 TCP 服務器連接。


          通用套接字方法

          編號 方法和說明

          1

          s.recv()


          此方法接收 TCP 消息


          2

          s.send()


          此方法傳輸 TCP 消息


          3

          s.recvfrom()


          該方法接收UDP消息


          4

          s.sendto()


          此方法傳輸 UDP 消息


          5

          s.close()


          此方法關閉套接字


          6

          socket.gethostname()


          返回主機名。


          一個簡單的服務器

          為了編寫 Internet 服務器,我們使用 socket 模塊中可用的socket函數來創建一個 socket 對象。然后使用套接字對象調用其他函數來設置套接字服務器。


          現在調用bind(hostname, port)函數來為給定主機上的服務指定一個端口。


          接下來,調用返回對象的accept方法。此方法一直等到客戶端連接到您指定的端口,然后返回一個連接對象,該對象表示與該客戶端的連接。


          #!/usr/bin/python           # This is server.py file


          import socket               # Import socket module


          s = socket.socket()         # Create a socket object

          host = socket.gethostname() # Get local machine name

          port = 12345                # Reserve a port for your service.

          s.bind((host, port))        # Bind to the port


          s.listen(5)                 # Now wait for client connection.

          while True:

             c, addr = s.accept()     # Establish connection with client.

             print 'Got connection from', addr

             c.send('Thank you for connecting')

             c.close()                # Close the connection

          一個簡單的客戶端

          讓我們編寫一個非常簡單的客戶端程序,它打開到給定端口 12345 和給定主機的連接。使用 Python 的socket模塊函數創建一個 socket 客戶端非常簡單。


          socket.connect(hosname, port)在port上打開一個到hostname的 TCP 連接。一旦你打開了一個套接字,你就可以像任何 IO 對象一樣讀取它。完成后,記得關閉它,就像關閉文件一樣。


          以下代碼是一個非常簡單的客戶端,它連接到給定的主機和端口,從套接字讀取任何可用數據,然后退出 -


          #!/usr/bin/python           # This is client.py file


          import socket               # Import socket module


          s = socket.socket()         # Create a socket object

          host = socket.gethostname() # Get local machine name

          port = 12345                # Reserve a port for your service.


          s.connect((host, port))

          print s.recv(1024)

          s.close()                     # Close the socket when done

          現在在后臺運行這個 server.py,然后在 client.py 上面運行以查看結果。


          # Following would start a server in background.

          $ python server.py & 


          # Once server is started run client as follows:

          $ python client.py

          這將產生以下結果 -


          Got connection from ('127.0.0.1', 48437)

          Thank you for connecting

          Python 互聯網模塊

          Python網絡/互聯網編程中一些重要模塊的列表。


          協議 常用功能 端口號 Python 模塊

          HTTP 網頁 80 httplib、urllib、xmlrpclib

          NNTP 新聞網新聞 119 nntplib

          FTP 文件傳輸 20 ftplib, urllib

          SMTP 發送電子郵件 25 smtplib

          POP3 獲取電子郵件 110 流行音樂庫

          IMAP4 獲取電子郵件 143 imaplib

          遠程登錄 命令行 23 遠程登錄庫

          地鼠 文件傳輸 70 gopherlib, urllib

          請檢查上述所有庫以使用 FTP、SMTP、POP 和 IMAP 協議。


          進一步閱讀

          這是 Socket 編程的快速入門。這是一個廣闊的主題。建議通過以下鏈接查找更多詳細信息 -


          Unix 套接字編程。


          Python 套接字庫和模塊。


          Python - MySQL 數據庫訪問

          數據庫接口的 Python 標準是 Python DB-API。大多數 Python 數據庫接口都遵循這個標準。


          您可以為您的應用程序選擇正確的數據庫。Python 數據庫 API 支持廣泛的數據庫服務器,例如 -


          mSQL

          MySQL

          PostgreSQL

          微軟 SQL Server 2000

          Informix

          基地間

          甲骨文

          賽貝斯

          以下是可用 Python 數據庫接口的列表:Python 數據庫接口和 API。您必須為需要訪問的每個數據庫下載單獨的 DB API 模塊。例如,如果您需要訪問 Oracle 數據庫和 MySQL 數據庫,則必須同時下載 Oracle 和 MySQL 數據庫模塊。


          DB API 為盡可能使用 Python 結構和語法處理數據庫提供了最低標準。該 API 包括以下內容 -


          導入 API 模塊。

          獲取與數據庫的連接。

          發出 SQL 語句和存儲過程。

          關閉連接

          我們將使用 MySQL 學習所有概念,所以讓我們談談 MySQLdb 模塊。


          什么是 MySQLdb?

          MySQLdb 是一個用于從 Python 連接到 MySQL 數據庫服務器的接口。它實現了 Python 數據庫 API v2.0,并構建在 MySQL C API 之上。


          如何安裝 MySQLdb?

          在繼續之前,請確保您的機器上安裝了 MySQLdb。只需在您的 Python 腳本中輸入以下內容并執行它 -


          #!/usr/bin/python


          import MySQLdb

          如果它產生以下結果,則表示未安裝 MySQLdb 模塊 -


          Traceback (most recent call last):

             File "test.py", line 3, in <module>

                import MySQLdb

          ImportError: No module named MySQLdb

          要安裝 MySQLdb 模塊,請使用以下命令 -


          For Ubuntu, use the following command -

          $ sudo apt-get install python-pip python-dev libmysqlclient-dev

          For Fedora, use the following command -

          $ sudo dnf install python python-devel mysql-devel redhat-rpm-config gcc

          For Python command prompt, use the following command -

          pip install MySQL-python

          注意- 確保您具有安裝上述模塊的 root 權限。


          數據庫連接

          在連接到 MySQL 數據庫之前,請確保以下內容 -


          您已經創建了一個數據庫 TESTDB。


          您已經在 TESTDB 中創建了一個表 EMPLOYEE。


          此表包含字段 FIRST_NAME、LAST_NAME、AGE、SEX 和 INCOME。


          用戶 ID“testuser”和密碼“test123”設置為訪問 TESTDB。


          Python 模塊 MySQLdb 已正確安裝在您的機器上。


          您已通過 MySQL 教程了解MySQL 基礎知識。


          例子

          以下是連接 MySQL 數據庫“TESTDB”的示例


          #!/usr/bin/python


          import MySQLdb


          # Open database connection

          db = MySQLdb.connect("localhost","testuser","test123","TESTDB" )


          # prepare a cursor object using cursor() method

          cursor = db.cursor()


          # execute SQL query using execute() method.

          cursor.execute("SELECT VERSION()")


          # Fetch a single row using fetchone() method.

          data = cursor.fetchone()

          print "Database version : %s " % data


          # disconnect from server

          db.close()

          運行此腳本時,它會在我的 Linux 機器中產生以下結果。


          Database version : 5.0.45

          如果與數據源建立了連接,則返回一個連接對象并將其保存到db中以供進一步使用,否則db設置為 None。接下來,db對象用于創建游標對象,該對象又用于執行 SQL 查詢。最后,在出來之前,確保關閉數據庫連接并釋放資源。


          創建數據庫表

          一旦建立了數據庫連接,我們就可以使用創建的游標的執行方法在數據庫表中創建表或記錄。


          例子

          讓我們創建數據庫表 EMPLOYEE -


          #!/usr/bin/python


          import MySQLdb


          # Open database connection

          db = MySQLdb.connect("localhost","testuser","test123","TESTDB" )


          # prepare a cursor object using cursor() method

          cursor = db.cursor()


          # Drop table if it already exist using execute() method.

          cursor.execute("DROP TABLE IF EXISTS EMPLOYEE")


          # Create table as per requirement

          sql = """CREATE TABLE EMPLOYEE (

                   FIRST_NAME  CHAR(20) NOT NULL,

                   LAST_NAME  CHAR(20),

                   AGE INT,  

                   SEX CHAR(1),

                   INCOME FLOAT )"""


          cursor.execute(sql)


          # disconnect from server

          db.close()

          插入操作

          當您要將記錄創建到數據庫表中時,它是必需的。


          例子

          以下示例執行 SQL INSERT語句以在 EMPLOYEE 表中創建記錄 -


          #!/usr/bin/python


          import MySQLdb


          # Open database connection

          db = MySQLdb.connect("localhost","testuser","test123","TESTDB" )


          # prepare a cursor object using cursor() method

          cursor = db.cursor()


          # Prepare SQL query to INSERT a record into the database.

          sql = """INSERT INTO EMPLOYEE(FIRST_NAME,

                   LAST_NAME, AGE, SEX, INCOME)

                   VALUES ('Mac', 'Mohan', 20, 'M', 2000)"""

          try:

             # Execute the SQL command

             cursor.execute(sql)

             # Commit your changes in the database

             db.commit()

          except:

             # Rollback in case there is any error

             db.rollback()


          # disconnect from server

          db.close()

          上面的例子可以寫成如下動態創建 SQL 查詢 -


          #!/usr/bin/python


          import MySQLdb


          # Open database connection

          db = MySQLdb.connect("localhost","testuser","test123","TESTDB" )


          # prepare a cursor object using cursor() method

          cursor = db.cursor()


          # Prepare SQL query to INSERT a record into the database.

          sql = "INSERT INTO EMPLOYEE(FIRST_NAME, \

                 LAST_NAME, AGE, SEX, INCOME) \

                 VALUES ('%s', '%s', '%d', '%c', '%d' )" % \

                 ('Mac', 'Mohan', 20, 'M', 2000)

          try:

             # Execute the SQL command

             cursor.execute(sql)

             # Commit your changes in the database

             db.commit()

          except:

             # Rollback in case there is any error

             db.rollback()


          # disconnect from server

          db.close()

          例子

          以下代碼段是另一種執行形式,您可以直接傳遞參數 -


          ..................................

          user_id = "test123"

          password = "password"


          con.execute('insert into Login values("%s", "%s")' % \

                       (user_id, password))

          ..................................

          讀操作

          對任何數據庫的讀取操作意味著從數據庫中獲取一些有用的信息。


          一旦我們的數據庫連接建立,您就可以對該數據庫進行查詢了。您可以使用fetchone()方法獲取單個記錄,也可以使用 fetchall( )方法從數據庫表中獲取多個值。


          fetchone() - 它獲取查詢結果集的下一行。結果集是使用游標對象查詢表時返回的對象。


          fetchall() - 它獲取結果集中的所有行。如果已經從結果集中提取了一些行,則它會從結果集中檢索剩余的行。


          rowcount - 這是一個只讀屬性,返回受 execute() 方法影響的行數。


          例子

          以下過程從 EMPLOYEE 表中查詢工資超過 1000 的所有記錄 -


          #!/usr/bin/python


          import MySQLdb


          # Open database connection

          db = MySQLdb.connect("localhost","testuser","test123","TESTDB" )


          # prepare a cursor object using cursor() method

          cursor = db.cursor()


          sql = "SELECT * FROM EMPLOYEE \

                 WHERE INCOME > '%d'" % (1000)

          try:

             # Execute the SQL command

             cursor.execute(sql)

             # Fetch all the rows in a list of lists.

             results = cursor.fetchall()

             for row in results:

                fname = row[0]

                lname = row[1]

                age = row[2]

                sex = row[3]

                income = row[4]

                # Now print fetched result

                print "fname=%s,lname=%s,age=%d,sex=%s,income=%d" % \

                       (fname, lname, age, sex, income )

          except:

             print "Error: unable to fecth data"


          # disconnect from server

          db.close()

          這將產生以下結果 -


          fname=Mac, lname=Mohan, age=20, sex=M, income=2000

          更新操作

          UPDATE 對任何數據庫的操作意味著更新數據庫中已經存在的一條或多條記錄。


          以下過程更新所有 SEX 為'M'的記錄。在這里,我們將所有男性的 AGE 增加一年。


          例子

          #!/usr/bin/python


          import MySQLdb


          # Open database connection

          db = MySQLdb.connect("localhost","testuser","test123","TESTDB" )


          # prepare a cursor object using cursor() method

          cursor = db.cursor()


          # Prepare SQL query to UPDATE required records

          sql = "UPDATE EMPLOYEE SET AGE = AGE + 1

                                    WHERE SEX = '%c'" % ('M')

          try:

             # Execute the SQL command

             cursor.execute(sql)

             # Commit your changes in the database

             db.commit()

          except:

             # Rollback in case there is any error

             db.rollback()


          # disconnect from server

          db.close()

          刪除操作

          當您想從數據庫中刪除一些記錄時,需要執行 DELETE 操作。以下是從 AGE 超過 20 的 EMPLOYEE 中刪除所有記錄的過程 -


          例子

          #!/usr/bin/python


          import MySQLdb


          # Open database connection

          db = MySQLdb.connect("localhost","testuser","test123","TESTDB" )


          # prepare a cursor object using cursor() method

          cursor = db.cursor()


          # Prepare SQL query to DELETE required records

          sql = "DELETE FROM EMPLOYEE WHERE AGE > '%d'" % (20)

          try:

             # Execute the SQL command

             cursor.execute(sql)

             # Commit your changes in the database

             db.commit()

          except:

             # Rollback in case there is any error

             db.rollback()


          # disconnect from server

          db.close()

          執行交易

          事務是一種確保數據一致性的機制。交易具有以下四個屬性 -


          原子性- 交易完成或根本沒有發生任何事情。


          一致性- 事務必須以一致的狀態開始,并使系統處于一致的狀態。


          隔離- 交易的中間結果在當前交易之外不可見。


          持久性 - 一旦提交事務,即使在系統故障之后,效果也是持久的。


          Python DB API 2.0 提供了兩種提交或回滾事務的方法。


          例子

          您已經知道如何實現事務。這又是一個類似的例子 -


          # Prepare SQL query to DELETE required records

          sql = "DELETE FROM EMPLOYEE WHERE AGE > '%d'" % (20)

          try:

             # Execute the SQL command

             cursor.execute(sql)

             # Commit your changes in the database

             db.commit()

          except:

             # Rollback in case there is any error

             db.rollback()

          提交操作

          提交是操作,它向數據庫發出綠色信號以完成更改,并且在此操作之后,無法恢復任何更改。


          這是一個調用提交方法的簡單示例。


          db.commit()

          回滾操作

          如果您對一項或多項更改不滿意并且想要完全還原這些更改,請使用rollback()方法。


          這是一個調用rollback()方法的簡單示例。


          db.rollback()

          斷開數據庫

          要斷開數據庫連接,請使用 close() 方法。


          db.close()

          如果用戶使用 close() 方法關閉了與數據庫的連接,則數據庫將回滾任何未完成的事務。但是,您的應用程序最好不要顯式調用提交或回滾,而不是依賴于任何 DB 較低級別的實現細節。


          處理錯誤

          錯誤的來源有很多。一些示例是執行的 SQL 語句中的語法錯誤、連接失敗或為已取消或完成的語句句柄調用 fetch 方法。


          DB API 定義了每個數據庫模塊中必須存在的許多錯誤。下表列出了這些例外情況。


          編號 例外與說明

          1

          警告


          用于非致命問題。必須繼承 StandardError。


          2

          錯誤


          錯誤的基類。必須繼承 StandardError。


          3

          接口錯誤


          用于數據庫模塊中的錯誤,而不是數據庫本身。必須子類化錯誤。


          4

          數據庫錯誤


          用于數據庫中的錯誤。必須子類化錯誤。


          5

          數據錯誤


          DatabaseError 的子類,指數據中的錯誤。


          6

          操作錯誤


          DatabaseError 的子類,它指的是諸如丟失與數據庫的連接之類的錯誤。這些錯誤通常不受 Python 腳本編寫者的控制。


          7

          完整性錯誤


          DatabaseError 的子類,用于可能破壞關系完整性的情況,例如唯一性約束或外鍵。


          8

          內部錯誤


          DatabaseError 的子類,它引用數據庫模塊內部的錯誤,例如游標不再處于活動狀態。


          9

          編程錯誤


          DatabaseError 的子類,它指的是錯誤的表名和其他可以安全歸咎于您的錯誤。


          10

          不支持錯誤


          DatabaseError 的子類,指嘗試調用不受支持的功能。


          您的 Python 腳本應該處理這些錯誤,但在使用上述任何異常之前,請確保您的 MySQLdb 支持該異常。您可以通過閱讀 DB API 2.0 規范來獲得有關它們的更多信息。


          Python - CGI 編程

          通用網關接口 (CGI) 是一組標準,用于定義 Web 服務器和自定義腳本之間如何交換信息。CGI 規范目前由 NCSA 維護。


          什么是 CGI?

          通用網關接口 (CGI) 是外部網關程序與 HTTP 服務器等信息服務器接口的標準。


          當前版本是 CGI/1.1,CGI/1.2 正在開發中。


          網頁瀏覽

          為了理解 CGI 的概念,讓我們看看當我們點擊一個超鏈接來瀏覽一個特定的網頁或 URL 時會發生什么。


          您的瀏覽器聯系 HTTP Web 服務器并要求提供 URL,即文件名。


          Web 服務器解析 URL 并查找文件名。如果它找到該文件,則將其發送回瀏覽器,否則發送一條錯誤消息,指示您請求了錯誤的文件。


          Web 瀏覽器從 Web 服務器獲取響應并顯示接收到的文件或錯誤消息。


          但是,可以設置 HTTP 服務器,以便無論何時請求某個目錄中的文件,該文件都不會被發回;相反,它作為一個程序執行,并且該程序輸出的任何內容都會發送回您的瀏覽器以顯示。此功能稱為通用網關接口或 CGI,程序稱為 CGI 腳本。這些 CGI 程序可以是 Python 腳本、PERL 腳本、Shell 腳本、C 或 C++ 程序等。


          CGI 架構圖

          CGI 架構

          Web 服務器支持和配置

          在繼續進行 CGI 編程之前,請確保您的 Web 服務器支持 CGI 并且已配置為處理 CGI 程序。HTTP 服務器要執行的所有 CGI 程序都保存在預先配置的目錄中。這個目錄被稱為 CGI 目錄,按照慣例,它被命名為 /var/www/cgi-bin。按照慣例,CGI 文件的擴展名為。cgi,但您也可以使用 python 擴展名.py保存文件。


          默認情況下,Linux 服務器配置為僅運行 /var/www 中 cgi-bin 目錄中的腳本。如果要指定任何其他目錄來運行 CGI 腳本,請在 httpd.conf 文件中注釋以下行 -


          <Directory "/var/www/cgi-bin">

             AllowOverride None

             Options ExecCGI

             Order allow,deny

             Allow from all

          </Directory>


          <Directory "/var/www/cgi-bin">

          Options All

          </Directory>

          在這里,我們假設您已經成功啟動并運行了 Web 服務器,并且您能夠運行任何其他 CGI 程序,如 Perl 或 Shell 等。


          第一個 CGI 程序

          這是一個簡單的鏈接,它鏈接到一個名為hello.py的 CGI 腳本。該文件保存在 /var/www/cgi-bin 目錄下,內容如下。在運行 CGI 程序之前,請確保您已使用chmod 755 hello.py UNIX 命令更改文件模式以使文件可執行。


          #!/usr/bin/python


          print "Content-type:text/html\r\n\r\n"

          print '<html>'

          print '<head>'

          print '<title>Hello World - First CGI Program</title>'

          print '</head>'

          print '<body>'

          print '<h2>Hello World! This is my first CGI program</h2>'

          print '</body>'

          print '</html>'

          如果單擊 hello.py,則會產生以下輸出 -


          你好世界!這是我的第一個 CGI 程序

          這個 hello.py 腳本是一個簡單的 Python 腳本,它將其輸出寫入 STDOUT 文件,即屏幕。有一個重要且額外的功能可用,即要打印的第一行Content-type:text/html\r\n\r\n。該行被發送回瀏覽器,它指定要在瀏覽器屏幕上顯示的內容類型。


          至此,您一定已經了解了 CGI 的基本概念,并且可以使用 Python 編寫許多復雜的 CGI 程序。該腳本還可以與任何其他外部系統交互以交換信息,例如 RDBMS。


          HTTP 標頭

          行Content-type:text/html\r\n\r\n是 HTTP 標頭的一部分,發送到瀏覽器以了解內容。所有 HTTP 標頭都將采用以下形式 -


          HTTP Field Name: Field Content


          For Example

          Content-type: text/html\r\n\r\n

          很少有其他重要的 HTTP 標頭,您將在 CGI 編程中經常使用它們。


          編號 標題和說明

          1

          內容類型:


          定義返回文件格式的 MIME 字符串。示例是 Content-type:text/html


          2

          過期:日期


          信息失效的日期。瀏覽器使用它來決定何時需要刷新頁面。有效日期字符串的格式為 01 Jan 1998 12:00:00 GMT。


          3

          地點:網址


          返回的 URL,而不是請求的 URL。您可以使用此字段將請求重定向到任何文件。


          4

          最后修改:日期


          上次修改資源的日期。


          5

          內容長度:N


          返回的數據的長度(以字節為單位)。瀏覽器使用此值報告文件的估計下載時間。


          6

          設置 Cookie:字符串


          設置通過字符串傳遞的cookie


          CGI 環境變量

          所有 CGI 程序都可以訪問以下環境變量。這些變量在編寫任何 CGI 程序時都起著重要作用。


          編號 變量名稱和描述

          1

          內容類型


          內容的數據類型。當客戶端向服務器發送附加內容時使用。例如,文件上傳。


          2

          CONTENT_LENGTH


          查詢信息的長度。它僅適用于 POST 請求。


          3

          HTTP_COOKIE


          以鍵值對的形式返回設置的 cookie。


          4

          HTTP_USER_AGENT


          User-Agent request-header 字段包含有關發起請求的用戶代理的信息。它是 Web 瀏覽器的名稱。


          5

          PATH_INFO


          CGI 腳本的路徑。


          6

          請求參數


          使用 GET 方法請求發送的 URL 編碼信息。


          7

          遠程地址


          發出請求的遠程主機的 IP 地址。這對于日志記錄或身份驗證很有用。


          8

          遠程主機


          發出請求的主機的完全限定名稱。如果此信息不可用,則可以使用 REMOTE_ADDR 獲取 IR 地址。


          9

          REQUEST_METHOD


          用于發出請求的方法。最常用的方法是 GET 和 POST。


          10

          SCRIPT_FILENAME


          CGI 腳本的完整路徑。


          11

          SCRIPT_NAME


          CGI 腳本的名稱。


          12

          服務器名稱


          服務器的主機名或 IP 地址


          13

          服務器軟件


          服務器正在運行的軟件的名稱和版本。


          這是列出所有 CGI 變量的小型 CGI 程序。單擊此鏈接查看結果獲取環境


          #!/usr/bin/python


          import os


          print "Content-type: text/html\r\n\r\n";

          print "<font size=+1>Environment</font><\br>";

          for param in os.environ.keys():

             print "<b>%20s</b>: %s<\br>" % (param, os.environ[param])

          GET 和 POST 方法

          當您需要將一些信息從瀏覽器傳遞到 Web 服務器并最終傳遞到 CGI 程序時,您一定遇到過很多情況。最常見的是,瀏覽器使用兩種方法將這些信息傳遞給 Web 服務器。這些方法是 GET 方法和 POST 方法。


          使用 GET 方法傳遞信息

          GET 方法發送附加到頁面請求的編碼用戶信息。頁面和編碼信息由 ? 分隔。字符如下 -


          http://www.test.com/cgi-bin/hello.py?key1=value1&key2=value2

          GET 方法是將信息從瀏覽器傳遞到 Web 服務器的默認方法,它會生成一個長字符串,該字符串會出現在瀏覽器的 Location:box 中。如果您有密碼或其他敏感信息要傳遞給服務器,切勿使用 GET 方法。GET 方法有大小限制:請求字符串中只能發送 1024 個字符。GET 方法使用 QUERY_STRING 標頭發送信息,并且可以通過 QUERY_STRING 環境變量在您的 CGI 程序中訪問。


          您可以通過簡單地連接鍵和值對以及任何 URL 來傳遞信息,或者您可以使用 HTML <FORM> 標記使用 GET 方法傳遞信息。


          簡單的 URL 示例:Get 方法

          這是一個簡單的 URL,它使用 GET 方法將兩個值傳遞給 hello_get.py 程序。


          /cgi-bin/hello_get.py?first_name=ZARA&last_name=ALI

          下面是hello_get.py腳本,用于處理 Web 瀏覽器給出的輸入。我們將使用cgi模塊,這使得訪問傳遞的信息變得非常容易 -


          #!/usr/bin/python


          # Import modules for CGI handling 

          import cgi, cgitb 


          # Create instance of FieldStorage 

          form = cgi.FieldStorage() 


          # Get data from fields

          first_name = form.getvalue('first_name')

          last_name  = form.getvalue('last_name')


          print "Content-type:text/html\r\n\r\n"

          print "<html>"

          print "<head>"

          print "<title>Hello - Second CGI Program</title>"

          print "</head>"

          print "<body>"

          print "<h2>Hello %s %s</h2>" % (first_name, last_name)

          print "</body>"

          print "</html>"

          這將產生以下結果 -


          你好 ZARA 阿里

          簡單的FORM例子:GET方法

          此示例使用 HTML FORM 和提交按鈕傳遞兩個值。我們使用相同的 CGI 腳本 hello_get.py 來處理這個輸入。


          <form action = "/cgi-bin/hello_get.py" method = "get">

          First Name: <input type = "text" name = "first_name">  <br />


          Last Name: <input type = "text" name = "last_name" />

          <input type = "submit" value = "Submit" />

          </form>

          這是上述表單的實際輸出,輸入名字和姓氏,然后單擊提交按鈕以查看結果。


          名:


          姓:

           

          使用 POST 方法傳遞信息

          將信息傳遞給 CGI 程序的通常更可靠的方法是 POST 方法。這以與 GET 方法完全相同的方式打包信息,但不是在 ? 之后將其作為文本字符串發送。在 URL 中,它作為單獨的消息發送。此消息以標準輸入的形式進入 CGI 腳本。


          下面是處理 GET 和 POST 方法的相同 hello_get.py 腳本。


          #!/usr/bin/python


          # Import modules for CGI handling 

          import cgi, cgitb 


          # Create instance of FieldStorage 

          form = cgi.FieldStorage() 


          # Get data from fields

          first_name = form.getvalue('first_name')

          last_name  = form.getvalue('last_name')


          print "Content-type:text/html\r\n\r\n"

          print "<html>"

          print "<head>"

          print "<title>Hello - Second CGI Program</title>"

          print "</head>"

          print "<body>"

          print "<h2>Hello %s %s</h2>" % (first_name, last_name)

          print "</body>"

          print "</html>"

          讓我們再次采用與上面相同的示例,它使用 HTML FORM 和提交按鈕傳遞兩個值。我們使用相同的 CGI 腳本 hello_get.py 來處理這個輸入。


          <form action = "/cgi-bin/hello_get.py" method = "post">

          First Name: <input type = "text" name = "first_name"><br />

          Last Name: <input type = "text" name = "last_name" />


          <input type = "submit" value = "Submit" />

          </form>

          這是上述表格的實際輸出。您輸入名字和姓氏,然后單擊提交按鈕以查看結果。


          名:


          姓:

           

          將復選框數據傳遞給 CGI 程序

          當需要選擇多個選項時使用復選框。


          這是帶有兩個復選框的表單的示例 HTML 代碼 -


          <form action = "/cgi-bin/checkbox.cgi" method = "POST" target = "_blank">

          <input type = "checkbox" name = "maths" value = "on" /> Maths

          <input type = "checkbox" name = "physics" value = "on" /> Physics

          <input type = "submit" value = "Select Subject" />

          </form>

          此代碼的結果如下形式 -


          數學 物理 

          下面是 checkbox.cgi 腳本,用于處理 Web 瀏覽器為復選框按鈕提供的輸入。


          #!/usr/bin/python


          # Import modules for CGI handling 

          import cgi, cgitb 


          # Create instance of FieldStorage 

          form = cgi.FieldStorage() 


          # Get data from fields

          if form.getvalue('maths'):

             math_flag = "ON"

          else:

             math_flag = "OFF"


          if form.getvalue('physics'):

             physics_flag = "ON"

          else:

             physics_flag = "OFF"


          print "Content-type:text/html\r\n\r\n"

          print "<html>"

          print "<head>"

          print "<title>Checkbox - Third CGI Program</title>"

          print "</head>"

          print "<body>"

          print "<h2> CheckBox Maths is : %s</h2>" % math_flag

          print "<h2> CheckBox Physics is : %s</h2>" % physics_flag

          print "</body>"

          print "</html>"

          將單選按鈕數據傳遞給 CGI 程序

          當只需要選擇一個選項時,使用單選按鈕。


          這是帶有兩個單選按鈕的表單的示例 HTML 代碼 -


          <form action = "/cgi-bin/radiobutton.py" method = "post" target = "_blank">

          <input type = "radio" name = "subject" value = "maths" /> Maths

          <input type = "radio" name = "subject" value = "physics" /> Physics

          <input type = "submit" value = "Select Subject" />

          </form>

          此代碼的結果如下形式 -


          數學 物理 

          下面是 radiobutton.py 腳本,用于處理 Web 瀏覽器為單選按鈕提供的輸入 -


          #!/usr/bin/python


          # Import modules for CGI handling 

          import cgi, cgitb 


          # Create instance of FieldStorage 

          form = cgi.FieldStorage() 


          # Get data from fields

          if form.getvalue('subject'):

             subject = form.getvalue('subject')

          else:

             subject = "Not set"


          print "Content-type:text/html\r\n\r\n"

          print "<html>"

          print "<head>"

          print "<title>Radio - Fourth CGI Program</title>"

          print "</head>"

          print "<body>"

          print "<h2> Selected Subject is %s</h2>" % subject

          print "</body>"

          print "</html>"

          將文本區域數據傳遞給 CGI 程序

          當必須將多行文本傳遞給 CGI 程序時,使用 TEXTAREA 元素。


          這是帶有 TEXTAREA 框的表單的示例 HTML 代碼 -


          <form action = "/cgi-bin/textarea.py" method = "post" target = "_blank">

          <textarea name = "textcontent" cols = "40" rows = "4">

          Type your text here...

          </textarea>

          <input type = "submit" value = "Submit" />

          </form>

          此代碼的結果如下形式 -


          Type your text here...

           

          下面是處理網絡瀏覽器輸入的 textarea.cgi 腳本 -


          #!/usr/bin/python


          # Import modules for CGI handling 

          import cgi, cgitb 


          # Create instance of FieldStorage 

          form = cgi.FieldStorage() 


          # Get data from fields

          if form.getvalue('textcontent'):

             text_content = form.getvalue('textcontent')

          else:

             text_content = "Not entered"


          print "Content-type:text/html\r\n\r\n"

          print "<html>"

          print "<head>";

          print "<title>Text Area - Fifth CGI Program</title>"

          print "</head>"

          print "<body>"

          print "<h2> Entered Text Content is %s</h2>" % text_content

          print "</body>"

          將下拉框數據傳遞給 CGI 程序

          當我們有許多可用選項但只選擇一兩個時使用下拉框。


          這是帶有一個下拉框的表單的示例 HTML 代碼 -


          <form action = "/cgi-bin/dropdown.py" method = "post" target = "_blank">

          <select name = "dropdown">

          <option value = "Maths" selected>Maths</option>

          <option value = "Physics">Physics</option>

          </select>

          <input type = "submit" value = "Submit"/>

          </form>

          此代碼的結果如下形式 -



          數學

           

          下面是處理 Web 瀏覽器輸入的 dropdown.py 腳本。


          #!/usr/bin/python


          # Import modules for CGI handling 

          import cgi, cgitb 


          # Create instance of FieldStorage 

          form = cgi.FieldStorage() 


          # Get data from fields

          if form.getvalue('dropdown'):

             subject = form.getvalue('dropdown')

          else:

             subject = "Not entered"


          print "Content-type:text/html\r\n\r\n"

          print "<html>"

          print "<head>"

          print "<title>Dropdown Box - Sixth CGI Program</title>"

          print "</head>"

          print "<body>"

          print "<h2> Selected Subject is %s</h2>" % subject

          print "</body>"

          print "</html>"

          在 CGI 中使用 Cookie

          HTTP 協議是一種無狀態協議。對于商業網站,需要維護不同頁面之間的會話信息。例如,一個用戶注冊在完成許多頁面后結束。如何跨所有網頁維護用戶的會話信息?


          在許多情況下,使用 cookie 是記住和跟蹤偏好、購買、傭金和其他更好的訪問者體驗或網站統計所需的信息的最有效方法。


          這個怎么運作?

          您的服務器以 cookie 的形式向訪問者的瀏覽器發送一些數據。瀏覽器可以接受 cookie。如果是這樣,它將作為純文本記錄存儲在訪問者的硬盤上?,F在,當訪問者到達您網站上的另一個頁面時,cookie 就可以檢索了。檢索后,您的服務器知道/記住存儲的內容。


          Cookie 是 5 個可變長度字段的純文本數據記錄 -


          Expires - cookie 過期的日期。如果此項為空,則 cookie 將在訪問者退出瀏覽器時過期。


          Domain - 您網站的域名。


          Path - 設置 cookie 的目錄或網頁的路徑。如果您想從任何目錄或頁面檢索 cookie,這可能是空白的。


          Secure - 如果此字段包含“安全”一詞,則只能使用安全服務器檢索 cookie。如果此字段為空,則不存在此類限制。


          Name=Value - 以鍵值對的形式設置和檢索 Cookie。


          設置 Cookie

          將 cookie 發送到瀏覽器非常容易。這些 cookie 與 HTTP Header 一起發送到 Content-type 字段。假設您要將 UserID 和 Password 設置為 cookie。設置 cookie 如下:


          #!/usr/bin/python


          print "Set-Cookie:UserID = XYZ;\r\n"

          print "Set-Cookie:Password = XYZ123;\r\n"

          print "Set-Cookie:Expires = Tuesday, 31-Dec-2007 23:12:40 GMT";\r\n"

          print "Set-Cookie:Domain = www.tutorialspoint.com;\r\n"

          print "Set-Cookie:Path = /perl;\n"

          print "Content-type:text/html\r\n\r\n"

          ...........Rest of the HTML Content....

          從這個例子中,您一定已經了解了如何設置 cookie。我們使用Set-Cookie HTTP 標頭來設置 cookie。


          設置 cookie 屬性(如 Expires、Domain 和 Path)是可選的。值得注意的是,cookie 是在發送魔法行"Content-type:text/html\r\n\r\n之前設置的。


          檢索 Cookie

          檢索所有設置的 cookie 非常容易。Cookie 存儲在 CGI 環境變量 HTTP_COOKIE 中,它們將具有以下形式 -


          key1 = value1;key2 = value2;key3 = value3....

          以下是如何檢索 cookie 的示例。


          #!/usr/bin/python


          # Import modules for CGI handling 

          from os import environ

          import cgi, cgitb


          if environ.has_key('HTTP_COOKIE'):

             for cookie in map(strip, split(environ['HTTP_COOKIE'], ';')):

                (key, value ) = split(cookie, '=');

                if key == "UserID":

                   user_id = value


                if key == "Password":

                   password = value


          print "User ID  = %s" % user_id

          print "Password = %s" % password

          這將為上述腳本設置的 cookie 產生以下結果 -


          User ID = XYZ

          Password = XYZ123

          文件上傳示例

          要上傳文件,HTML 表單必須將 enctype 屬性設置為multipart/form-data。具有文件類型的輸入標簽會創建一個“瀏覽”按鈕。


          <html>

          <body>

             <form enctype = "multipart/form-data" 

                               action = "save_file.py" method = "post">

             <p>File: <input type = "file" name = "filename" /></p>

             <p><input type = "submit" value = "Upload" /></p>

             </form>

          </body>

          </html>

          此代碼的結果如下形式 -


          文件:未選擇任何文件



          上面的示例已被故意禁用以保存人們在我們的服務器上上傳文件,但您可以在您的服務器上嘗試上面的代碼。


          這是處理文件上傳的腳本save_file.py -


          #!/usr/bin/python


          import cgi, os

          import cgitb; cgitb.enable()


          form = cgi.FieldStorage()


          # Get filename here.

          fileitem = form['filename']


          # Test if the file was uploaded

          if fileitem.filename:

             # strip leading path from file name to avoid 

             # directory traversal attacks

             fn = os.path.basename(fileitem.filename)

             open('/tmp/' + fn, 'wb').write(fileitem.file.read())


             message = 'The file "' + fn + '" was uploaded successfully'

             

          else:

             message = 'No file was uploaded'

             

          print """\

          Content-Type: text/html\n

          <html>

          <body>

             <p>%s</p>

          </body>

          </html>

          """ % (message,)

          如果您在 Unix/Linux 上運行上述腳本,則需要注意替換文件分隔符,如下所示,否則在您的 windows 機器上,上面的 open() 語句應該可以正常工作。


          fn = os.path.basename(fileitem.filename.replace("\\", "/" ))

          如何彈出“文件下載”對話框?

          有時,您希望提供用戶可以單擊鏈接的選項,它會向用戶彈出“文件下載”對話框,而不是顯示實際內容。這很容易,可以通過 HTTP 標頭來實現。此 HTTP 標頭與上一節中提到的標頭不同。


          例如,如果您想從給定鏈接下載FileName文件,則其語法如下 -


          #!/usr/bin/python


          # HTTP Header

          print "Content-Type:application/octet-stream; name = \"FileName\"\r\n";

          print "Content-Disposition: attachment; filename = \"FileName\"\r\n\n";


          # Actual File Content will go here.

          fo = open("foo.txt", "rb")


          str = fo.read();

          print str


          # Close opend file

          fo.close()

          希望您喜歡本教程。如果是,請將您的反饋發送給我:聯系我們


          Python - 正則表達式

          正則表達式是一個特殊的字符序列,它使用模式中的特殊語法幫助您匹配或查找其他字符串或字符串集。正則表達式在 UNIX 世界中被廣泛使用。


          Python 模塊re完全支持 Python 中的類 Perl 正則表達式。如果在編譯或使用正則表達式時發生錯誤,re 模塊會引發異常 re.error。


          我們將介紹兩個重要的函數,它們將用于處理正則表達式。但首先要說一件小事:有各種各樣的字符,當它們用于正則表達式時會有特殊的含義。為避免在處理正則表達式時出現任何混淆,我們將使用原始字符串作為r'expression'。


          匹配函數_

          此函數嘗試將 RE模式匹配到帶有可選標志的字符串。


          這是此函數的語法 -


          re.match(pattern, string, flags=0)

          這是參數的描述 -


          編號 參數及說明

          1

          圖案


          這是要匹配的正則表達式。


          2

          細繩


          這是字符串,它將被搜索以匹配字符串開頭的模式。


          3

          旗幟


          您可以使用按位或 (|) 指定不同的標志。這些是修飾符,在下表中列出。


          re.match函數在成功時返回匹配對象,在失敗時返回None。我們使用match對象的group(num)或groups()函數來獲取匹配的表達式。


          編號 匹配對象方法和描述

          1

          組(數量=0)


          此方法返回整個匹配(或特定子組 num)


          2

          組()


          此方法返回元組中的所有匹配子組(如果沒有則為空)


          例子

          現場演示

          #!/usr/bin/python

          import re


          line = "Cats are smarter than dogs"


          matchObj = re.match( r'(.*) are (.*?) .*', line, re.M|re.I)


          if matchObj:

             print "matchObj.group() : ", matchObj.group()

             print "matchObj.group(1) : ", matchObj.group(1)

             print "matchObj.group(2) : ", matchObj.group(2)

          else:

             print "No match!!"

          執行上述代碼時,會產生以下結果 -


          matchObj.group() :  Cats are smarter than dogs

          matchObj.group(1) :  Cats

          matchObj.group(2) :  smarter

          搜索功能_

          此函數使用可選標志搜索字符串中第一次出現的 RE模式。


          這是此函數的語法 -


          re.search(pattern, string, flags=0)

          這是參數的描述 -


          編號 參數及說明

          1

          圖案


          這是要匹配的正則表達式。


          2

          細繩


          這是字符串,它將被搜索以匹配字符串中任何位置的模式。


          3

          旗幟


          您可以使用按位或 (|) 指定不同的標志。這些是修飾符,在下表中列出。


          re.search函數在成功時返回匹配對象,在失敗時返回無。我們使用match對象的group(num)或groups()函數來獲取匹配的表達式。


          編號 匹配對象方法和描述

          1

          組(數量=0)


          此方法返回整個匹配(或特定子組 num)


          2

          組()


          此方法返回元組中的所有匹配子組(如果沒有則為空)


          例子

          現場演示

          #!/usr/bin/python

          import re


          line = "Cats are smarter than dogs";


          searchObj = re.search( r'(.*) are (.*?) .*', line, re.M|re.I)


          if searchObj:

             print "searchObj.group() : ", searchObj.group()

             print "searchObj.group(1) : ", searchObj.group(1)

             print "searchObj.group(2) : ", searchObj.group(2)

          else:

             print "Nothing found!!"

          執行上述代碼時,會產生以下結果 -


          searchObj.group() :  Cats are smarter than dogs

          searchObj.group(1) :  Cats

          searchObj.group(2) :  smarter

          匹配與搜索

          Python 提供了兩種不同的基于正則表達式的原始操作:match僅在字符串的開頭檢查匹配,而search在字符串中的任何位置檢查匹配(這是 Perl 默認所做的)。


          例子

          現場演示

          #!/usr/bin/python

          import re


          line = "Cats are smarter than dogs";


          matchObj = re.match( r'dogs', line, re.M|re.I)

          if matchObj:

             print "match --> matchObj.group() : ", matchObj.group()

          else:

             print "No match!!"


          searchObj = re.search( r'dogs', line, re.M|re.I)

          if searchObj:

             print "search --> searchObj.group() : ", searchObj.group()

          else:

             print "Nothing found!!"

          執行上述代碼時,會產生以下結果 -


          No match!!

          search --> searchObj.group() :  dogs

          搜索和替換

          使用正則表達式的最重要的re方法之一是sub。


          句法

          re.sub(pattern, repl, string, max=0)

          此方法用repl替換字符串中所有出現的 RE模式,除非提供了max ,否則替換所有出現。此方法返回修改后的字符串。


          例子

          現場演示

          #!/usr/bin/python

          import re


          phone = "2004-959-559 # This is Phone Number"


          # Delete Python-style comments

          num = re.sub(r'#.*$', "", phone)

          print "Phone Num : ", num


          # Remove anything other than digits

          num = re.sub(r'\D', "", phone)    

          print "Phone Num : ", num

          執行上述代碼時,會產生以下結果 -


          Phone Num :  2004-959-559

          Phone Num :  2004959559

          正則表達式修飾符:選項標志

          正則表達式文字可能包括一個可選的修飾符來控制匹配的各個方面。修飾符被指定為可選標志。您可以使用異或 (|) 提供多個修飾符,如前所示,并且可以由以下之一表示 -


          編號 修飾符和說明

          1

          re.I


          執行不區分大小寫的匹配。


          2

          重L


          根據當前語言環境解釋單詞。這種解釋會影響字母組(\w 和 \W),以及單詞邊界行為(\b 和 \B)。


          3

          再M


          使 $ 匹配一行的結尾(不僅僅是字符串的結尾)并使 ^ 匹配任何行的開頭(不僅僅是字符串的開頭)。


          4

          回復


          使句點(點)匹配任何字符,包括換行符。


          5

          回復


          根據 Unicode 字符集解釋字母。此標志影響 \w、\W、\b、\B 的行為。


          6

          re.X


          允許“更可愛”的正則表達式語法。它忽略空格(除了在集合 [] 內或被反斜杠轉義時)并將未轉義的 # 視為注釋標記。


          正則表達式模式

          除了控制字符(+ ? . * ^ $ ( ) [ ] { } | \),所有字符都匹配自己。您可以通過在控制字符前面加上反斜杠來轉義它。


          下表列出了 Python 中可用的正則表達式語法 -


          編號 圖案和描述

          1

          ^


          匹配行首。


          2

          $


          匹配行尾。


          3

          .


          匹配除換行符以外的任何單個字符。使用 m 選項也可以匹配換行符。


          4

          [...]


          匹配括號中的任何單個字符。


          5

          [^...]


          匹配任何不在括號中的單個字符


          6

          回覆*


          匹配 0 次或多次出現的前面表達式。


          7

          重新+


          匹配 1 次或多次出現的前面表達式。


          8

          回覆?


          匹配 0 或 1 次出現的前面表達式。


          9

          重新{ n}


          精確匹配前面表達式的 n 次出現。


          10

          再{n,}


          匹配 n 次或多次出現的前面表達式。


          11

          重新{ n,米}


          匹配至少 n 次和最多 m 次出現的前面表達式。


          12

          一個| b


          匹配 a 或 b。


          13

          (回覆)


          對正則表達式進行分組并記住匹配的文本。


          14

          (?imx)


          臨時切換正則表達式中的 i、m 或 x 選項。如果在括號中,則只有該區域受到影響。


          15

          (?-imx)


          暫時關閉正則表達式中的 i、m 或 x 選項。如果在括號中,則只有該區域受到影響。


          16

          (?: 回覆)


          分組正則表達式而不記住匹配的文本。


          17

          (?imx:重新)


          臨時切換括號內的 i、m 或 x 選項。


          18

          (?-imx:重新)


          暫時關閉括號內的 i、m 或 x 選項。


          19

          (?#...)


          評論。


          20

          (?= 重新)


          使用模式指定位置。沒有范圍。


          21

          (?! 回覆)


          使用模式否定指定位置。沒有范圍。


          22

          (?>重新)


          匹配獨立模式而不回溯。


          23

          \w


          匹配單詞字符。


          24

          \W


          匹配非單詞字符。


          25

          \s


          匹配空格。等價于 [\t\n\r\f]。


          26

          \S


          匹配非空白。


          27

          \d


          匹配數字。相當于 [0-9]。


          28

          \D


          匹配非數字。


          29

          \一種


          匹配字符串的開頭。


          30

          \Z


          匹配字符串的結尾。如果存在換行符,它將在換行符之前匹配。


          31

          \z


          匹配字符串的結尾。


          32

          \G


          匹配上一場比賽結束的地點。


          33

          \b


          在括號外匹配單詞邊界。在括號內時匹配退格 (0x08)。


          34

          \B


          匹配非單詞邊界。


          35

          \n、\t 等


          匹配換行符、回車符、制表符等。


          36

          \1...\9


          匹配第 n 個分組的子表達式。


          37

          \10


          如果已經匹配,則匹配第 n 個分組子表達式。否則指字符代碼的八進制表示。


          正則表達式示例

          文字字符

          編號 示例和說明

          1

          Python


          匹配“蟒蛇”。


          字符類

          編號 示例和說明

          1

          [Pp]ython


          匹配“Python”或“python”


          2

          擦[耶]


          匹配“ruby”或“ruby”


          3

          [愛歐]


          匹配任意一個小寫元音


          4

          [0-9]


          匹配任何數字;與 [0123456789] 相同


          5

          [阿茲]


          匹配任何小寫 ASCII 字母


          6

          [AZ]


          匹配任何大寫 ASCII 字母


          7

          [a-zA-Z0-9]


          匹配以上任何一項


          8

          [^aeiou]


          匹配除小寫元音以外的任何內容


          9

          [^0-9]


          匹配除數字以外的任何內容


          特殊字符類

          編號 示例和說明

          1

          .


          匹配除換行符以外的任何字符


          2

          \d


          匹配一個數字:[0-9]


          3

          \D


          匹配非數字:[^0-9]


          4

          \s


          匹配一個空白字符:[ \t\r\n\f]


          5

          \S


          匹配非空白:[^ \t\r\n\f]


          6

          \w


          匹配單個單詞字符:[A-Za-z0-9_]


          7

          \W


          匹配一個非單詞字符:[^A-Za-z0-9_]


          重復案例

          編號 示例和說明

          1

          紅寶石?


          匹配“rub”或“ruby”:y 是可選的


          2

          紅寶石*


          匹配 "rub" 加上 0 個或多個 ys


          3

          紅寶石+


          匹配 "rub" 加上 1 個或多個 ys


          4

          \d{3}


          精確匹配 3 位數字


          5

          \d{3,}


          匹配 3 個或更多數字


          6

          \d{3,5}


          匹配 3、4 或 5 位數字


          非貪婪重復

          這匹配最少的重復次數 -


          編號 示例和說明

          1

          <.*>


          貪婪重復:匹配“<python>perl>”


          2

          <.*?>


          Nongreedy:匹配“<python>perl>”中的“<python>”


          用括號分組

          編號 示例和說明

          1

          \D\d+


          無組:+ 重復 \d


          2

          (\D\d)+


          分組:+ 重復 \D\d 對


          3

          ([Pp]ython(, )?)+


          匹配“Python”、“Python、python、python”等。


          反向引用

          這再次匹配先前匹配的組 -


          編號 示例和說明

          1

          ([Pp])ython&\1ails


          匹配 python&pails 或 Python&Pails


          2

          (['"])[^\1]*\1


          單引號或雙引號字符串。\1 匹配第一組匹配的任何內容。\2 匹配第二組匹配的任何內容,等等。


          備擇方案

          編號 示例和說明

          1

          蟒蛇|perl


          匹配“python”或“perl”


          2

          擦(y|le))


          匹配“紅寶石”或“盧布”


          3

          Python(!+|\?)


          “Python”后跟一個或多個!還是一個?


          錨點

          這需要指定匹配位置。


          編號 示例和說明

          1

          ^蟒蛇


          在字符串或內部行的開頭匹配“Python”


          2

          蟒蛇$


          在字符串或行的末尾匹配“Python”


          3

          \APython


          匹配字符串開頭的“Python”


          4

          蟒蛇\Z


          匹配字符串末尾的“Python”


          5

          \bPython\b


          在單詞邊界匹配“Python”


          6

          \刷\ B


          \B 是非單詞邊界:匹配“rube”和“ruby”中的“rub”,但不是單獨匹配


          7

          蟒蛇(?=?。?/p>


          如果后跟感嘆號,則匹配“Python”。


          8

          Python(??。。?/p>


          如果后面沒有感嘆號,則匹配“Python”。


          帶括號的特殊語法

          編號 示例和說明

          1

          R(?#comment)


          匹配“R”。其余的都是評論


          2

          R(?i)uby


          匹配“uby”時不區分大小寫


          3

          R(?i:uby)


          和上面一樣


          4

          擦(?:y|le))


          僅分組而不創建 \1 反向引用


          Python - 面向對象

          Python 從出現以來一直是一種面向對象的語言。因此,創建和使用類和對象非常容易。本章幫助您成為使用 Python 面向對象編程支持的專家。


          如果您以前沒有任何面向對象 (OO) 編程的經驗,您可能需要查閱有關它的入門課程或至少某種教程,以便掌握基本概念。


          但是,這里是面向對象編程 (OOP) 的小介紹,可讓您快速入門 -


          OOP 術語概述

          類- 對象的用戶定義原型,定義了一組表征類的任何對象的屬性。屬性是通過點符號訪問的數據成員(類變量和實例變量)和方法。


          類變量- 由類的所有實例共享的變量。類變量在類內定義,但在類的任何方法之外。類變量不像實例變量那樣頻繁使用。


          數據成員- 保存與類及其對象關聯的數據的類變量或實例變量。


          函數重載- 將多個行為分配給特定函數。執行的操作因所涉及的對象或參數的類型而異。


          Instance variable - 在方法內部定義的變量,僅屬于類的當前實例。


          繼承- 將類的特征轉移到從它派生的其他類。


          Instance - 某個類的單個對象。例如,屬于類 Circle 的對象 obj 是類 Circle 的一個實例。


          實例化- 創建一個類的實例。


          Method - 在類定義中定義的一種特殊函數。


          Object - 由其類定義的數據結構的唯一實例。一個對象包括數據成員(類變量和實例變量)和方法。


          運算符重載- 將多個函數分配給特定運算符。


          創建類

          class語句創建一個新的類定義。類的名稱緊跟關鍵字class后跟冒號,如下所示 -


          class ClassName:

             'Optional class documentation string'

             class_suite

          該類有一個文檔字符串,可以通過ClassName.__doc__訪問。


          class_suite由定義類成員、數據屬性和函數的所有組件語句組成。


          例子

          以下是一個簡單的 Python 類的示例 -


          class Employee:

             'Common base class for all employees'

             empCount = 0


             def __init__(self, name, salary):

                self.name = name

                self.salary = salary

                Employee.empCount += 1

             

             def displayCount(self):

               print "Total Employee %d" % Employee.empCount


             def displayEmployee(self):

                print "Name : ", self.name,  ", Salary: ", self.salary

          變量empCount是一個類變量,其值在此類的所有實例之間共享。這可以作為Employee.empCount從類內部或類外部訪問。


          第一個方法__init__()是一種特殊的方法,稱為類構造函數或初始化方法,Python 在創建此類的新實例時會調用該方法。


          您可以像普通函數一樣聲明其他類方法,但每個方法的第一個參數是self除外。Python 為您將self參數添加到列表中;調用方法時不需要包含它。


          創建實例對象

          要創建類的實例,您可以使用類名調用該類并傳入其__init__方法接受的任何參數。


          "This would create first object of Employee class"

          emp1 = Employee("Zara", 2000)

          "This would create second object of Employee class"

          emp2 = Employee("Manni", 5000)

          訪問屬性

          您可以使用帶有對象的點運算符訪問對象的屬性。類變量將使用類名訪問,如下所示 -


          emp1.displayEmployee()

          emp2.displayEmployee()

          print "Total Employee %d" % Employee.empCount

          現在,將所有概念放在一起 -


          現場演示

          #!/usr/bin/python


          class Employee:

             'Common base class for all employees'

             empCount = 0


             def __init__(self, name, salary):

                self.name = name

                self.salary = salary

                Employee.empCount += 1

             

             def displayCount(self):

               print "Total Employee %d" % Employee.empCount


             def displayEmployee(self):

                print "Name : ", self.name,  ", Salary: ", self.salary


          "This would create first object of Employee class"

          emp1 = Employee("Zara", 2000)

          "This would create second object of Employee class"

          emp2 = Employee("Manni", 5000)

          emp1.displayEmployee()

          emp2.displayEmployee()

          print "Total Employee %d" % Employee.empCount

          執行上述代碼時,會產生以下結果 -


          Name :  Zara ,Salary:  2000

          Name :  Manni ,Salary:  5000

          Total Employee 2

          您可以隨時添加、刪除或修改類和對象的屬性 -


          emp1.age = 7  # Add an 'age' attribute.

          emp1.age = 8  # Modify 'age' attribute.

          del emp1.age  # Delete 'age' attribute.

          您可以使用以下函數,而不是使用普通語句來訪問屬性 -


          getattr(obj, name[, default]) - 訪問對象的屬性。


          hasattr(obj,name) -檢查屬性是否存在。


          setattr (obj,name,value) - 設置屬性。如果屬性不存在,那么它將被創建。


          delattr (obj, name) - 刪除一個屬性。


          hasattr(emp1, 'age')    # Returns true if 'age' attribute exists

          getattr(emp1, 'age')    # Returns value of 'age' attribute

          setattr(emp1, 'age', 8) # Set attribute 'age' at 8

          delattr(empl, 'age')    # Delete attribute 'age'

          內置類屬性

          每個 Python 類都遵循內置屬性,并且可以像任何其他屬性一樣使用點運算符訪問它們 -


          __dict__ - 包含類名稱空間的字典。


          __doc__ - 類文檔字符串或無,如果未定義。


          __name__ - 類名。


          __module__ - 定義類的模塊名稱。此屬性在交互模式下為“__main__”。


          __bases__ - 包含基類的可能為空的元組,按照它們在基類列表中出現的順序排列。


          對于上面的類,讓我們嘗試訪問所有這些屬性 -


          現場演示

          #!/usr/bin/python


          class Employee:

             'Common base class for all employees'

             empCount = 0


             def __init__(self, name, salary):

                self.name = name

                self.salary = salary

                Employee.empCount += 1

             

             def displayCount(self):

               print "Total Employee %d" % Employee.empCount


             def displayEmployee(self):

                print "Name : ", self.name,  ", Salary: ", self.salary


          print "Employee.__doc__:", Employee.__doc__

          print "Employee.__name__:", Employee.__name__

          print "Employee.__module__:", Employee.__module__

          print "Employee.__bases__:", Employee.__bases__

          print "Employee.__dict__:", Employee.__dict__

          執行上述代碼時,會產生以下結果 -


          Employee.__doc__: Common base class for all employees

          Employee.__name__: Employee

          Employee.__module__: __main__

          Employee.__bases__: ()

          Employee.__dict__: {'__module__': '__main__', 'displayCount':

          <function displayCount at 0xb7c84994>, 'empCount': 2, 

          'displayEmployee': <function displayEmployee at 0xb7c8441c>, 

          '__doc__': 'Common base class for all employees', 

          '__init__': <function __init__ at 0xb7c846bc>}

          銷毀對象(垃圾收集)

          Python 會自動刪除不需要的對象(內置類型或類實例)以釋放內存空間。Python 定期回收不再使用的內存塊的過程稱為垃圾收集。


          Python 的垃圾收集器在程序執行期間運行,并在對象的引用計數達到零時觸發。對象的引用計數隨著指向它的別名數量的變化而變化。


          對象的引用計數在被分配新名稱或放置在容器(列表、元組或字典)中時會增加。使用del刪除對象、重新分配其引用或超出范圍時,對象的引用計數會減少。當一個對象的引用計數達到零時,Python 會自動收集它。


          a = 40      # Create object <40>

          b = a       # Increase ref. count  of <40> 

          c = [b]     # Increase ref. count  of <40> 


          del a       # Decrease ref. count  of <40>

          b = 100     # Decrease ref. count  of <40> 

          c[0] = -1   # Decrease ref. count  of <40> 

          當垃圾收集器銷毀孤立實例并回收其空間時,您通常不會注意到。但是一個類可以實現特殊方法__del__(),稱為析構函數,當實例即將被銷毀時調用該方法。此方法可用于清理實例使用的任何非內存資源。


          例子

          這個 __del__() 析構函數打印即將被銷毀的實例的類名 -


          現場演示

          #!/usr/bin/python


          class Point:

             def __init__( self, x=0, y=0):

                self.x = x

                self.y = y

             def __del__(self):

                class_name = self.__class__.__name__

                print class_name, "destroyed"


          pt1 = Point()

          pt2 = pt1

          pt3 = pt1

          print id(pt1), id(pt2), id(pt3) # prints the ids of the obejcts

          del pt1

          del pt2

          del pt3

          執行上述代碼時,會產生以下結果 -


          3083401324 3083401324 3083401324

          Point destroyed

          注意- 理想情況下,您應該在單獨的文件中定義您的類,然后您應該使用import語句將它們導入您的主程序文件中。


          類繼承

          您可以通過在新類名后面的括號中列出父類,從預先存在的類派生類來創建一個類,而不是從頭開始。


          子類繼承其父類的屬性,您可以像在子類中定義這些屬性一樣使用這些屬性。子類也可以覆蓋父類的數據成員和方法。


          句法

          派生類的聲明很像它們的父類;但是,在類名之后給出了要繼承的基類列表 -


          class SubClassName (ParentClass1[, ParentClass2, ...]):

             'Optional class documentation string'

             class_suite

          例子

          現場演示

          #!/usr/bin/python


          class Parent:        # define parent class

             parentAttr = 100

             def __init__(self):

                print "Calling parent constructor"


             def parentMethod(self):

                print 'Calling parent method'


             def setAttr(self, attr):

                Parent.parentAttr = attr


             def getAttr(self):

                print "Parent attribute :", Parent.parentAttr


          class Child(Parent): # define child class

             def __init__(self):

                print "Calling child constructor"


             def childMethod(self):

                print 'Calling child method'


          c = Child()          # instance of child

          c.childMethod()      # child calls its method

          c.parentMethod()     # calls parent's method

          c.setAttr(200)       # again call parent's method

          c.getAttr()          # again call parent's method

          執行上述代碼時,會產生以下結果 -


          Calling child constructor

          Calling child method

          Calling parent method

          Parent attribute : 200

          類似地,您可以從多個父類中驅動一個類,如下所示 -


          class A:        # define your class A

          .....


          class B:         # define your class B

          .....


          class C(A, B):   # subclass of A and B

          .....

          您可以使用 issubclass() 或 isinstance() 函數來檢查兩個類和實例的關系。


          如果給定的子類sub確實是超類sup的子類,則issubclass(sub, sup)布爾函數返回 true 。


          isinstance(obj, Class)布爾函數如果obj是Class 的實例或者是 Class的子類的實例,則返回 true


          覆蓋方法

          您始終可以覆蓋您的父類方法。重寫父類方法的一個原因是您可能希望子類中有特殊或不同的功能。


          例子

          現場演示

          #!/usr/bin/python


          class Parent:        # define parent class

             def myMethod(self):

                print 'Calling parent method'


          class Child(Parent): # define child class

             def myMethod(self):

                print 'Calling child method'


          c = Child()          # instance of child

          c.myMethod()         # child calls overridden method

          執行上述代碼時,會產生以下結果 -


          Calling child method

          基礎重載方法

          下表列出了您可以在自己的類中覆蓋的一些通用功能 -


          編號 方法、描述和樣品調用

          1

          __init__ ( self [,args...] )


          構造函數(帶有任何可選參數)


          示例調用:obj = className(args)


          2

          __del__(自我)


          析構函數,刪除一個對象


          示例調用:del obj


          3

          __repr__(自我)


          可評估的字符串表示


          示例調用:repr(obj)


          4

          __str__( 自我 )


          可打印的字符串表示


          示例調用:str(obj)


          5

          __cmp__ ( 自我, x )


          對象比較


          示例調用:cmp(obj, x)


          重載運算符

          假設您創建了一個 Vector 類來表示二維向量,當您使用加號運算符將它們相加時會發生什么?Python 很可能會對你大喊大叫。


          但是,您可以在您的類中定義__add__方法來執行向量加法,然后加號運算符將按預期運行 -


          例子

          現場演示

          #!/usr/bin/python


          class Vector:

             def __init__(self, a, b):

                self.a = a

                self.b = b


             def __str__(self):

                return 'Vector (%d, %d)' % (self.a, self.b)

             

             def __add__(self,other):

                return Vector(self.a + other.a, self.b + other.b)


          v1 = Vector(2,10)

          v2 = Vector(5,-2)

          print v1 + v2

          執行上述代碼時,會產生以下結果 -


          Vector(7,8)

          數據隱藏

          對象的屬性在類定義之外可能可見,也可能不可見。您需要使用雙下劃線前綴命名屬性,然后這些屬性對于外人來說是不直接可見的。


          例子

          現場演示

          #!/usr/bin/python


          class JustCounter:

             __secretCount = 0

            

             def count(self):

                self.__secretCount += 1

                print self.__secretCount


          counter = JustCounter()

          counter.count()

          counter.count()

          print counter.__secretCount

          執行上述代碼時,會產生以下結果 -


          1

          2

          Traceback (most recent call last):

             File "test.py", line 12, in <module>

                print counter.__secretCount

          AttributeError: JustCounter instance has no attribute '__secretCount'

          Python 通過在內部更改名稱以包含類名來保護這些成員。您可以訪問諸如object._className__attrName 之類的屬性。如果您將最后一行替換如下,那么它對您有用 -


          .........................

          print counter._JustCounter__secretCount

          執行上述代碼時,會產生以下結果 -


          1

          2

          2


          << 1 2 3 > >>

          Copyright www.voyageurimaginaire.com Rights Reserved葵花寶典教程.鄂icp2022001145號-1

          分享:

          支付寶

          微信

          精品一区二区三区无码毛片
        1. <tbody id="baor6"></tbody>

        2. <em id="baor6"><acronym id="baor6"><input id="baor6"></input></acronym></em>
          <strike id="baor6"></strike><li id="baor6"></li>
          <rp id="baor6"></rp>
          1. <em id="baor6"></em>
            <form id="baor6"></form>
            <nobr id="baor6"></nobr>

            <em id="baor6"><acronym id="baor6"><u id="baor6"></u></acronym></em>