1. 程式人生 > >Python 類的基本定義詳解

Python 類的基本定義詳解

【摘要】Python是一種面向物件的語言,稍微複雜一點的程式,都應該採用類來進行設計,以使程式結構更加清晰,易於把控。本文將討論單類的基本內容定義,以後的博文再討論其它。

 

一. 成員的訪問範圍:

Python中的類,其實就是執行程式碼塊,這一點很重要,所有位於 class 語句中的程式碼,都是在特殊的類名稱空間中執行的,這個類名稱空間可由類內所有例項成員訪問。

類內成員包括類成員(用類名來訪問),例項成員(用self 或 例項物件變數來訪問)。

Python語言本身對成員的訪問範圍控制不是很嚴格,更是一種對程式設計師的提醒或約定,請不要在外部使用保護成員及私有成員

。以下是例項成員的訪問範圍的定義約定;如果是類成員,應該都是公用的,否則,請不要把它定義為類成員。

型別

名稱

python 中的定義方法

舉例

可訪問範圍

public

公用成員

不加入任何特殊字元

member

類例項,繼承類,當前類內部

protected

保護成員

加一個下劃線

_member

繼承類,當前類內部

private

私有成員

加二個下劃線

__member

當前類內部

 

二. 類成員的定義詳解:

成員名稱

說明

舉例

類本身

類名的命名規範為 CamelCase

每個單詞都以大寫字母開頭,單詞之間沒有分隔符

class DemoClass:

建構函式

建立類例項時,將觸發執行

def __init__(self):

解構函式

由系統的垃圾回收機制來自動執行,程式無法控制它何時執行,請謹慎使用

def __del__(self):

類程式碼

  1. 直接定義在類範圍,不定義在任何方法中
  2. 觸發執行:第一次例項化物件,或第一次呼叫類成員

class DemoClass:

    print('Class 執行程式碼塊開始執行了, 但整個過程只執行一次!')

類欄位(類特性)

 

  1. 直接定義在類範圍,不定義在任何方法內
  2. 訪問方法: DemoClass.class_scope_field
  3. 任何類例項,訪問的都是同一個類欄位
  4. self.class_scope_field的初始值為DemoClass.class_scope_field,  但隨後的改動,將被繫結在 self 例項範圍,跟類本身沒有關係

class DemoClass

   class_scope_field = “類作用域欄位”

類方法

  1. 帶裝飾器 @classmethod的函式
  2. 第一個引數一定為cls
  3. 訪問方式:DemoClass.class_method(),不帶 cls引數
  4. 不能訪問 self成員
  5. 可以通過cls, 直接訪問類成員

@classmethod

def class_method(cls):

    print("類方法: classmethod_hello()")

靜態方法

  1. 帶裝飾器 @staticmethod
  2. 不帶任何固定引數
  3. 訪問方式: DemoClass.static_method()
  4. 不能訪問self成員
  5. 靜態方法就是普通的函式,只不過碰巧定義在了類裡,而不是模組層。因此,完全可以將其放在跟類同模組的類定義前面或後面

@staticmethod

def static_method():

    print('靜態方法: static_hello')

成員欄位(成員特性)

  1. 在成員方法中,前面加self進行定義
  2. 按PEP8規範,所有成員欄位,應該定義在 def __init__(self)方法中
  3. 通過加下劃線,約定訪問範圍
  4. 訪問方式: 通過self 或 例項物件變數名來訪問

          self.__private_field

          demo_instance.public_field

def __init__(self, class_name):

    print("建構函式:__init__()")

    self.public_field = "公用欄位"

    self._protected_field = "受保護欄位"

    self.__private_field = "私有欄位"

    self._name = class_name

 

成員方法

  1. python的函式,第一個引數一定為self
  2. 通過加下劃線,約定訪問範圍
  3. 可通過self訪問所有例項成員
  4. 訪問方式: 通過self 或 例項物件變數名來訪問,訪問時,帶( ), 不需要帶self引數

           self.__private_method( )

           demo_instance.public_method( )

def public_method(self):

def _protected_method(self):

def __private_method(self):

 

成員屬性(讀)

  1. 帶裝飾器 @property的成員方法
  2. 可在返回結果前,進行邏輯控制處理,並遮蔽內部的欄位命名
  3. 訪問範圍,按設計初衷,成員屬性一般應該是公用的
  4. 訪問方式,通過 self 或 例項物件變數名來訪問,訪問時,不帶(),跟欄位一樣,直接使用

          self.public_property

          demo_instance.public_property

@property

def public_property(self):

    return self._name.upper()

成員屬性(寫)

  1. 帶裝飾器 @指定屬性名.setter的成員方法
  2. 方法名稱跟對應的成員屬性名稱一致
  3. 第二個引數,為傳入值引數
  4. 對傳入值可以進行邏輯處理,然後賦值給類的成員欄位
  5. 訪問範圍,跟對應的成員屬性一致
  6. 訪問方式,通過 self 或 例項物件變數名來訪問,只支援賦值,跟欄位賦值一樣        

self.public_property = ‘new property’

demo_instance.public_property = “new property 2”

@public_property.setter

def public_property(self, value):

    self._name = value.lower()

 

三. 例項程式碼及演示:

# coding:utf-8
# -----------------------------------------------------------------------------
# Comments  : 演示說明python類的基本成員定義及使用
# Developer : Edwin.Zhang
# Date      : 2018-8-28
# -----------------------------------------------------------------------------

def normal_method():
    print("*.呼叫正常函式:normal_hello()")


# 類名的命名規範為: CamelCase
class DemoClass:
    print('【演示】Class 執行程式碼塊開始執行了, 但整個過程只執行一次!\n')

    class_scope_field = "類作用域欄位"

    def __init__(self, class_name):
        print("建構函式:__init__()")
        self.public_field = "公用欄位"
        self._protected_field = "受保護欄位"
        self.__private_field = "私有欄位"
        self._name = class_name

    def __del__(self):
        print("析構方法:__del__() for [" + self._name + "],  什麼時候被呼叫,不確定,請謹慎使用!")

    @property
    def public_property(self):
        return self._name.upper()

    @public_property.setter
    def public_property(self, value):
        self._name = value.lower()

    def public_method(self):
        print('*.公用方法:public_hello() : ' + self.public_field + " " + self.public_property)

    def _protected_method(self):
        print('*.受保護方法:_private_hello() : ' + self.__private_field)

    def __private_method(self):
        print('*.私有方法:_private_hello() : ' + self.__private_field)

    @classmethod
    def class_method(cls):
        print("*.類方法: classmethod_hello()")
        print("*.類方法訪問 " + cls.class_scope_field)

    @staticmethod
    def static_method():
        print('*.靜態方法: static_hello')

    def internal_call(self):
        self.public_method()
        self._protected_method()
        self.__private_method()

        self.class_method()
        self.static_method()

        DemoClass.class_method()
        DemoClass.static_method()

        normal_method()

        self.public_property = "new setting property"
        print("*.訪問公共屬性 :" + self.public_property)
        print("*.通過self, 訪問:" + self.class_scope_field)
        print("*.通過類名, 訪問:" + DemoClass.class_scope_field)


def demo0():
    print(DemoClass.public_property)


def demo1():
    instance = DemoClass('My Demo Class')

    print("\n【演示】類內部,呼叫的成員")
    instance.internal_call()

    print("\n【演示】通過物件例項,呼叫的方法")
    instance.public_method()
    instance.class_method()
    instance.static_method()

    print("\n【演示】通過物件例項,訪問欄位及屬性")
    print(instance.public_field)
    print(instance.public_property)
    instance.public_property = "new class name"
    print(instance.public_property)

    print("\n【演示】通過類名,訪問類欄位及類方法")
    print(DemoClass.class_scope_field)
    DemoClass.class_method()
    DemoClass.static_method()


def demo2():
    print("\n\n\n【演示2】型別欄位可以在多個類例項共享,若繫結到self並修改,則只作用於當前例項")
    print("Case 1 : \n*.例項初始化時: 兩者一致")
    ins1 = DemoClass("Instance 01")
    print("ins1.class_scope_field = " + ins1.class_scope_field)
    print("DemoClass.class_scope_field = " + DemoClass.class_scope_field)

    print("\n*.基於(例項)修改後, 成員已經繫結self, 兩者不一致")
    ins1.class_scope_field = "基於(例項)修改類作用域欄位"
    print("ins1.class_scope_field = " + ins1.class_scope_field)
    print("DemoClass.class_scope_field = " + DemoClass.class_scope_field)

    print("\n*.基於類修改後:(已經發生基於(例項)修改過):兩者不一致")
    DemoClass.class_scope_field = "基於類修改類作用域欄位"
    print("ins1.class_scope_field = " + ins1.class_scope_field)
    print("DemoClass.class_scope_field = " + DemoClass.class_scope_field)
    print("")

    print("\nCase 2 : \n*.建立新的例項:開始兩者一致,為類成員當前值")
    ins2 = DemoClass("Instance 02")
    print("ins2.class_scope_field = " + ins2.class_scope_field)
    print("DemoClass.class_scope_field = " + DemoClass.class_scope_field)

    print("\n*.基於類修改後:(沒有基於(例項)修改過),兩者一致,為更新值")
    DemoClass.class_scope_field = "基於類修改類作用域欄位 (新)"
    print("ins1.class_scope_field = " + ins2.class_scope_field)
    print("DemoClass.class_scope_field = " + DemoClass.class_scope_field)
    print("")

    print("\nCase 3: \n*.建立新的例項:兩者一致,為類成員的更新值")
    ins3 = DemoClass("Instance 03")
    print("ins2.class_scope_field = " + ins3.class_scope_field)
    print("DemoClass.class_scope_field = " + DemoClass.class_scope_field)
    print("")


if __name__ == "__main__":
    demo0()
    demo1()
    demo2()