1. 程式人生 > >python基礎語法總結(六)-- python類與OOP面向物件特性

python基礎語法總結(六)-- python類與OOP面向物件特性

python常用系統函式方法與模組

python基礎語法總結(一)-- python型別轉換函式+檔案讀寫

python基礎語法總結(二)-- 函式function

python基礎語法總結(三)-- 數與字串

python基礎語法總結(四)-- list列表

python基礎語法總結(五)-- 字典dic + 元組tuple

python基礎語法總結(六)-- python類與OOP面向物件特性


目錄

一. 類

1. 定義

2. 建立例項物件

3. 讀寫屬性和呼叫方法

二. 繼承

1. 繼承語法

2. 多繼承

3. 指定多繼承下的繼承源

三. 操作符過載

四. 靜態方法、類方法、抽象方法

1. 靜態方法

2. 類方法

3. 抽象方法



一. 類

1. 定義

### 定義類
class Animal:                   # 定義一個類animal
    """測試類Animal"""

    color = "black"             # 定義屬性:顏色
    age = 0                     # 定義屬性:年齡
    name = ""                   # 定義姓名:name

    def jump(self):             # 定義類的方法,方法第一個入參必須是例項本身,可以不用字面量'self'表示,但本質仍然是例項本身為入參
        print("can't jump")

    def eat(self, food):        # 有引數的方法
        print("eat " + food)

    def __healthy(self):        # 私有方法
        print("easy")

    __habit = "think"  # 定義私有變數, 以__雙下劃線開頭的屬性,為私有屬性

    def get_habit(self):            # 讀取私有屬性
        """得到私有屬性__habit的值"""
        return self.__habit

    def set_habit(self, habit):     # 修改私有屬性
        """設定私有屬性__habit的值"""
        self.__habit = habit

    # 專有方法,以__開始,並且以__結束,有特殊的用途
    def __init__(self, **args):             #_init__()方法,在構造例項時,預設呼叫此方法創建出例項
        """專有方法__init__()"""
        if args:
            if 'name' in args.keys():
                self.name = args['name']
            if 'age' in args.keys():
                self.age =  args['age']
            if  'color' in args.keys():
                self.color = args['color']

 

2. 建立例項物件

### 建立類的例項
xh = Animal()
mm = Animal(color="Red", age=3)        # 呼叫的時 __init__方法

 

3. 讀寫屬性和呼叫方法

# 讀取例項的公有屬性
print(xh.color)                 # 訪問color屬性,得到預設值:black
print(mm.color)                 # 訪問color屬性,得到初始化的值Red

# 修改例項的公有屬性
xh.name = '小黃'                # 設定name屬性為:小黃
print(xh.name)                  # 可以看到name屬性確實改為:小黃
mm.age = 5
print(mm.age)                   # age改為5

# 私有屬性在類的外部無法讀取和修改,可以通過公有方法來讀寫
print(xh.__habit)               # 報錯:'Animal' object has no attribute '__habit'
print(xh.get_habit())           # 正確,得到私有屬性的值:think

# 呼叫類的公有方法
xh.jump()                       # 第一個預設入參self不用寫, 列印: can't jump
xh.eat("meat")                  # 呼叫有引數的方法,self同樣不用寫

 

二. 繼承

1. 繼承語法

### 繼承
class Cat(Animal):              # 繼承父類animal,得到父類所有公有屬性和公有方法
    """新建類Cat,繼承自父類 Animal"""

    def __init__(self):
        super().__init__(color='white')             # 呼叫父類的init方法,設定初始值color顏色為white

    # print(__habit)    私有屬性不能繼承,這裡會報錯


mimi = Cat()                    # 新建物件mimi
print(mimi.color)               # 顏色為white,預設值

2. 多繼承

## python支援多繼承
class A:
    """定義A父類"""
    __a = 'A'

    def show(self):
        print(self.__a)


class B:
    """定義B父類"""
    __b = "B"

    def show(self):
        print(self.__b)


class SubClass(A, B):            # 多繼承在括號內寫入所有要繼承的類,順序--從左到右
    """定義SubClass類,繼承A、B類"""
    pass                        # 佔位


sub = SubClass()
sub.show()                      # 因為順序從左到右,所以show()方法繼承自第一個有show()的父類:A

 

3. 指定多繼承下的繼承源

# 指定屬性或方法的繼承源
class SubClass(A,B):            # 多繼承在括號內寫入所有要繼承的類,順序--從左到右
    """定義SubClass類,繼承A、B類"""
    show = B.show                # 指定子類的show為父類B的show


sub = SubClass()
sub.show()                      # 因為指定B.show,所以子類的show()方法執行結果為:B

 

三. 操作符過載

### 操作符過載
class SpecalList:
    """操作符過載測試類"""
    __list = []

    def __init__(self, l):
        self.__list = l

    def __add__(self, other):           # 過載__add__()操作符,使得SpecalList有特殊的 + 運算子實現
        """建立合併兩個list的 + 操作符實現"""
        result = self.__list
        for item in other.getList():
            result.append(item)
        return SpecalList(result)

    def getList(self):
        return self.__list


# 呼叫實現
list1 = SpecalList([1,2,3])
list2 = SpecalList([8,7,6])
list3 = list1 + list2           # 通過操作符+, 實現呼叫__add__()方法
print(list3.getList())          # 可以看到結果為:[1, 2, 3, 8, 7, 6]
運算子與專有方法的對應關係
+       __add__()
-       __sub__()
*       __mul__()
/       __div__()
%       __mod__()
**      __pow__()
len()   __len__()

 

四. 靜態方法、類方法、抽象方法

可以參考文章:《Python 中的 classmethod 和 staticmethod 有什麼具體用途?

1. 靜態方法

@staticmethod註解

class StaticClass:
    """靜態方法"""
    @staticmethod                       # 關鍵字
    def treble_string(string):          # 靜態方法,不需要有self入參
        return string * 3

StaticClass.treble_string("abc")        # 直接呼叫,不用建立例項,本例:'abcabcabc'

 

2. 類方法

import math
class Pizza:
    """類方法"""
    def __init__(self, radius, height):
        self.radius = radius
        self.height = height

    @staticmethod
    def compute_area(radius):
        return math.pi * (radius ** 2)

    @classmethod                                    # 類方法的關鍵字
    def compute_volume(cls, height, radius):        # 類方法第一個引數是類本身
        '''類方法與靜態方法畢肖像,使用類方法主要是為了避免硬編碼類名本身.
        如果不使用類方法而改用靜態方法@staticmethod,那麼在呼叫本類其他方法和屬性時,將不得不硬編碼(本例需要寫:Pizza.compute_area(),硬編碼寫了Pizza)
        這樣在Pizza類被繼承後,compute_volume()這個方法可能會有問題,重寫的方法和屬性無效  '''
        return height * cls.compute_area(radius)

    def get_volume(self):
        return self.compute_volume(self.height, self.radius)

# 呼叫類方法
Pizza.compute_volume(3,1)           # 返回計算的體積9.42477796076938

 

3. 抽象方法

import abc
from abc import ABCMeta

class AbstractClass(metaclass=ABCMeta):         # 引入抽象基礎類
    """抽象類測試"""
    def method1(self):               # 設定method1()為抽象方法
        """ python本身的語法沒有抽象方法,子類可以直接重寫此方法,來達到抽象方法的效果,這裡定義一個空方法就可以
            但是method1()這種方式有很大問題,如果程式設計師忘記重寫,程式本身不會提示,這樣不利於開發和除錯"""

    def method2(self):
        """ 在要設定的抽象方法method2()中,方法體主動丟擲異常
            但這樣也有小問題,只有在呼叫method2()時,才會報錯,在編譯階段沒有提醒"""
        raise NotImplementedError

    @abc.abstractmethod
    def method3(self):
        """ 引入@abc.abstractmethod,在開發(依賴IDE工具自身的檢測)和編譯階段如果檢查出子類沒有重寫此方法,則會報錯"""


class SubClass(AbstractClass):
    """抽象類的子類,要重寫父類抽象方法"""

    def method1(self):
        print("method1")

    def method2(self):
        print("method2")

    def method3(self):
        print("method3")


sc = SubClass()         # 如果沒有重寫抽象類method3(),這裡會報錯
sc.method2()
sc.method3()