1. 程式人生 > >python 中面向對象的概念

python 中面向對象的概念

sim 分支 display ica 3.0 輸出 全局 record 就會

原文

域和作用空間

本地域,函數域(nonlocal)和 全局域(global)

def scope_test():
    def do_local():
        spam = "local spam"
    def do_nonlocal():
        nonlocal spam
        spam = "nonlocal spam"
    def do_global():
        global spam
        spam = "global spam"

    spam = "test spam"
    do_local()
    print("After local assignment:", spam)
    do_nonlocal()
    print("After nonlocal assignment:", spam)
    do_global()
    print("After global assignment:", spam)

scope_test()
print("In global scope:", spam)
技術分享技術分享

輸出的結果是

After local assignment: test spam
After nonlocal assignment: nonlocal spam
After global assignment: nonlocal spam
In global scope: global spam
技術分享技術分享

* 簡要解釋一下:

本地域作用於當前子函數範圍,函數域作用於整個函數範圍,全局域作用於函數以及函數外部。優先級是本地域>函數域>全局域。

類的基本概念

最簡單的類的定義形式看起來像這樣:你可以將一個類定義放置於 if 語句的分支中, 或一個函數中.

class ClassName:
    <statement-1>
    .
    .
    .
    <statement-N>
技術分享技術分享

類的屬性和類的初始化方法

比如:

class MyClass:
    """A simple example class"""
    i = 12345
    def f(self):
        return ‘hello world‘
技術分享技術分享

可以給 MyClass.i 賦值以改變其數值. __doc__ 也是一個合法的屬性,返回屬於這個類的 docstring : "A simple example class".

實例化的操作 (“調用” 一個類對象) 創建了空的對象. 在創建實例時, 很多類可能都需要有特定的初始狀態. 所以一個類可以定義一個特殊的方法, 稱為 __init__()

, 像這樣:

>>> class Complex:
...     def __init__(self, realpart, imagpart):
...         self.r = realpart
...         self.i = imagpart
...
>>> x = Complex(3.0, -4.5)
>>> x.r, x.i
(3.0, -4.5)
技術分享技術分享

實例對象

可以對實例對象做什麽? 唯一能理解的操作就是屬性引用. 有兩種合法的屬性, 數據屬性和方法.(在 Python 中, 方法的概念並不是類實例所特有: 其他對象類型也可以有方法. 例如, 列表對象有 append, insert, remove, sort, 及等等的方法. 但是, 在下面的討論中, 我們指的就是類實例對象的方法, 除非特別指出.)(對象不等於類)

方法對象

調用方法對象

x.f()
技術分享技術分享

在多數情況下, 調用一個方法 (有個 n 個參數), 和調用相應的函數 (也有那 n 個參數, 但是再額外加入一個使用該方法的對象), 是等價的.

當一個實例屬性被引用時, 但是不是數據屬性, 那麽它的類將被搜索. 如果該名字代表一個合法的類屬性並且是一個函數對象, 一個方法對象就會被創建, 通過包裝 (指向) 實例對象, 而函數對象仍然只是在抽象的對象中: 這就是方法對象. 當方法對象用一個參數列表調用, 新的參數列表會從實例對象中重新構建, 然後函數對象則調用新的參數列表.

註意:

數據屬性覆寫了同名的方法屬性; 為了避免這個偶然的名字沖突, 在大型的程序中這會導致很難尋找的 bug, 使用某些命名約定是非常明智的, 這樣可以最小的避免沖突. 可能的約定包括大寫方法名稱, 在數據類型前增加特殊的前綴 (或者就是一個下劃線), 或對於方法使用動詞, 而數據成員則使用名詞.

繼承

派生類的定義:

class DerivedClassName(BaseClassName):
    <statement-1>
    .
    .
    .
    <statement-N>
技術分享技術分享

BaseClassName 的定義對於派生類而言必須是可見的. 在基類的地方, 任意的表達式都是允許的. 這就會非常有用, 比如基類定義在另一個模塊:

class DerivedClassName(modname.BaseClassName):
技術分享技術分享

Python 有兩個內置函數用於繼承:

  • 使用 isinstance() 檢查實例的類型: isinstance(obj, int) 只有在 obj.__class__int 或其派生類時才為 True.
  • 使用 issubclass() 用於檢查類的繼承關系: issubclass(bool, int) 會返回 True, 因為 boolint 的派生類. 但是, issubclass(float, int) 會是 False 因為 float 並不是 int 的派生類.

多重繼承

Python 支持多重繼承.

class DerivedClassName(Base1, Base2, Base3):
    <statement-1>
    .
    .
    .
    <statement-N>
技術分享技術分享

在繼承體系中, 同樣的類只會被搜尋一次. 如果一個屬性在 DerivedClassName 中沒有被找到, 它就會搜尋 Base1, 然後 (遞歸地) 搜尋 Base1 的基類, 然後如果還是沒有找到, 那麽就會搜索 Base2, 等等.

私有變量

在 Python 之中, 並不存在那種無法訪問的 “私有” 變量. 但是, 在多數的 Python 代碼中有個約定: 以一個下劃線帶頭的名字 (如 _spam) 應該作為非公共的 API (不管是函數, 方法或者數據成員). 這應該作為具體的實現, 而且變化它也無須提醒.

有這樣的一種機制稱為 name mangling. 任何如 __spam 形式的標識符, (在開頭至少有兩個下劃線) 將被替換為 _classname__spam, 此處的 classname 就是當前的類. 這樣的處理無須關註標識符的句法上的位置, 盡管它是在一個類的定義中.

數據類型

綁定一些命名的數據. 一個空的類定義就將很好:

class Employee:
    pass

john = Employee() # Create an empty employee record

# Fill the fields of the record
john.name = ‘John Doe‘
john.dept = ‘computer lab‘
john.salary = 1000
技術分享
技術分享

一段 Python 代碼中如果希望一個抽象的數據類型, 那麽可以通過傳遞一個類給那個方法, 就好像有了那個數據類型一樣.

python 中面向對象的概念