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

python常用系統函數方法與模塊

python基礎語法總結(一)-- python類型轉換函數+文件讀寫

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

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

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

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

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


一. 類

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()

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章