Python:靜態方法和類方法

之前,在類中定義的方法都是給對象的方法
實際上我們寫在類中的方法不都是對象的方法
例如:
我們定義一個三角形類,通過傳入三邊的邊長來構造三角形,並提供計算周長和麪積的方法
但是傳入三條邊的長度不一定都能構造出三角形,
我們可以先寫一個方法來驗證三條邊能否構成三角形
這個方法肯定不是對象方法,因爲這件事情是我在創建三角形對象之前做的
這個方法屬於三角形類而不屬於三角形對象

單詞部分

triangle    英[ˈtraɪæŋɡl]
美[ˈtraɪæŋɡl]
n. 三角形; 三角形物體; 三角鐵(打擊樂器); 三角關係;
[例句]This design is in pastel colours with three rectangles and three triangles
這一設計由淡色的3個長方形和3個三角形構成。
[其他]   複數:triangles


static 英[ˈstætɪk]
美[ˈstætɪk]
adj.   靜止的; 靜態的; 停滯的; 靜力的;
n. 天電(干擾); 靜電; 靜力學;
[例句]The number of young people obtaining qualifications has remained static or decreased
獲得資格證的年輕人數量一直維持不變或出現下降。

 

from math import sqrt


class Triangle(object):
    def __init__(self, a, b, c):
        self._a = a
        self._b = b
        self._c = c

    # 定義靜態方法
    @staticmethod
    def is_valid(a, b, c):
        return a + b > c and a + c > b and b + c > a

    # 對象方法
    def perimeter(self):
        return self._a + self._b + self._c

    # 海倫公式 面積 = 半周長*(半周長-a)*(半周長-b)*(半周長-c)開平方
    def area(self):
        half = self.perimeter() / 2
        return sqrt(half * (half - self._a) * (half - self._b) * (half - self._c))


def main():
    a, b, c = 3, 4, 5
    if Triangle.is_valid(a, b, c):
        # 創建對象
        t = Triangle(a, b, c)
        print(t.perimeter())
        # 也可以給類發消息來調用對象方法但是要傳入接受消息的對象作爲參數
        print(Triangle.area(t))
    else:
        print('無法構成三角形')


if __name__ == '__main__':
    main()

示例圖:

這裏使用到了海倫公式,海倫公司需要勾股定理,我們來證明一下:

勾股定理:

圖示

化解得到:

 

海倫公式:

 

勾股定理和海倫公司大家自己證明一下吧,感覺開個新專欄講數學也不錯~~~哈哈哈,吾乃天才

 

# 類方法

"""
和靜態方法比較類似,Python中還可以在類中定義類方法,
類方法的第一個參數約定爲cls,它代表的是當前相關的信息的對象
(類本身也是一個對象,有的地方稱之爲類的元數據對象)
通過這個參數我們可以獲取和類相關的信息並且可以創建出類的對象
"""

 

import time


class Clock(object):
    """數字時鐘"""

    def __init__(self, hour=0, minute=0, second=0):
        self._hour = hour
        self._minute = minute
        self._second = second

    @classmethod
    def now(cls):
        current_time = time.localtime(time.time())
        return cls(current_time.tm_hour, current_time.tm_min, current_time.tm_sec)

    def run(self):
        """走字"""
        self._second += 1
        if self._second == 60:
            self._second = 0
            self._minute += 1
            if self._minute == 60:
                self._minute = 0
                self._hour = 0
                if self._hour == 24:
                    self._hour = 0

    def show(self):
        """顯示時間"""
        # 佔位符 留兩個位置
        return '%2d:%2d:%2d' % (self._hour, self._minute, self._second)


def main():
    # 通過類方法創建對象並獲取系統時間
    clock = Clock.now()
    while True:
        print(clock.show())
        time.sleep(1)
        clock.run()


if __name__ == '__main__':
    main()

示例圖:

"""
類之間的關係
is - a : 繼承(泛化) 比如說學生和人的關係,手機和電子產品的關係都屬於繼承關係
has - a : 關聯關係  部門和員工的關係,汽車和引擎的關係都屬於關聯關係
          關聯如果是整體和部分的關聯,稱爲聚合關係
          如何整體進一步負責了部分的生命週期(整體和部分不可分割,同時同在也同時消亡),這種關係是合成關係
use - a : 依賴    比如司機有一個駕駛的方法,其中參數用到了汽車,司機和汽車就是依賴關係
"""

 

在已有類的基礎上完成某些操作,也可以在已有類的基礎上創建新的類,這些都是實現代碼複用的重要手段,複用現有的代碼不僅可以減少開發的工作量,也利於代碼的維護和管理。

大學的UML課本不錯

UML面向對象設計基礎

提取碼: jy9x

資源鏈接放在這裏啦

"""
類之間的關係
is - a : 繼承(泛化) 比如說學生和人的關係,手機和電子產品的關係都屬於繼承關係
has - a : 關聯關係  部門和員工的關係,汽車和引擎的關係都屬於關聯關係
          關聯如果是整體和部分的關聯,稱爲聚合關係
          如何整體進一步負責了部分的生命週期(整體和部分不可分割,同時同在也同時消亡),這種關係是合成關係
use - a : 依賴    比如司機有一個駕駛的方法,其中參數用到了汽車,司機和汽車就是依賴關係
"""
"""
在已有類的基礎上完成某些操作,
也可以在已有類的基礎上創建新的類,
這些都是實現代碼複用的重要手段,
複用現有的代碼不僅可以減少開發的工作量,
也利於代碼的維護和管理。
"""
'''
在已有類的基礎上創建新類,
這其中的一種做法就是讓一個類從另外一個類那裏把屬性和方法全部繼承下來
從而減少重複代碼的編寫。
提供繼承信息的我們稱爲父類,也叫超類或者基類
得到繼承信息的我們稱爲子類,也叫派生類或者衍生類
子類除了可以繼承父類提供的屬性和方法,還可以定義自己的屬性和方法
子類比父類擁有更多的能力
在實際開發中,我們通常會用子類對象替換一個父類對象,這是面向對象編程中常見行爲
對應的原則稱爲里氏替換原則
'''

 

# 繼承和多態

class Person(object):
    """人"""

    def __init__(self, name, age):
        self._name = name
        self._age = age

    @property
    def name(self):
        return self._name

    @property
    def age(self):
        return self._age

    @age.setter
    def age(self, age):
        self._age = age

    def play(self):
        print('%s正在快樂的玩耍' % self._name)

    def watch_av(self):
        if self._age >= 18:
            print('%s正在觀看愛情動作片' % self._name)
        else:
            print('%s正在畫圈圈' % self._name)


class Student(Person):
    """學生"""

    def __init__(self, name, age, grade):
        super().__init__(name, age)
        self._grade = grade

    @property
    def grade(self):
        return self._grade

    @grade.setter
    def grade(self, grade):
        self._grade = grade

    def study(self, course):
        print('%s的%s正在學習%s' % (self._grade, self._name, course))


class Teacher(Person):
    def __init__(self, name, age, title):
        super().__init__(name, age)
        self._title = title

    @property
    def title(self):
        return self._title

    @title.setter
    def title(self, title):
        self._title = title

    def teach(self, course):
        print('%s%s正在講%s' % (self._name, self._title, course))


def main():
    stu = Student('王大錘', 15, '初三')
    # 使用子類的方法
    stu.study('數學')
    # 使用父類的方法
    stu.watch_av()
    t = Teacher('她與斷劍', 22, '叫獅')
    # 使用子類的方法
    t.teach('python')
    # 使用父類的方法
    t.watch_av()


if __name__ == '__main__':
    main()

示例圖:

'''

override   英[ˌəʊvəˈraɪd]
美[ˌoʊvərˈraɪd]
v. (以權力) 否決,推翻,不理會; 比…更重要; 凌駕; 超馳控制,超控(使自動控制暫時失效,改用手工控制);
[例句]The welfare of a child should always override the wishes of its parents
孩子的幸福安康應該永遠比父母的願望來得更重要。
[其他]   第三人稱單數:overrides 現在分詞:overriding 過去式:overrode 過去分詞:overridden

poly   英[ˈpɒli]
美[ˈpɑːli]
n. 同 polytechnic; (舊時英國的)理工學院(現在多已改爲大學) ;
[例句]He portrays the psyche as poly-centric.
在他的描繪中精神是多中心的。
[其他]   複數:polys

morphology
英[mɔːˈfɒlədʒi]
美[mɔːrˈfɑːlədʒi]
n. 形態學; 形態論; 詞法;
[例句]This paper the morphology of gastric glands and mucous surface in the hatchlings of alligator sinensis.
本文觀察了初孵揚子鱷胃粘膜表面及胃腺的形態。

子類繼承了父類的方法之後,可以對父類已有的方法給出一個新的版本,即爲重寫(override)
通過方法重寫可以讓父類的同一個行爲在子類中擁有不同的版本
當我們調用這個經過子類改寫的方法時,不同的子類對象會表現出不同的行爲,即爲多態(poly-morphology)
'''

 

多態

"""
下面代碼中,我們將Pet處理爲一個抽象類,就是不能夠創建對象的類,
這種類就是專爲其它類去繼承它
Python從語法層並沒有提供像java/c#那樣的抽象類支持
通過abc模塊的ABCMeta元類和abstactmethod包裝器來達到抽象類的效果

重點:
下面代碼中
Dog和Cat兩個子類分別對Pet類中的make_voice抽象方法進行了重寫
調用方法時,同樣的方法做了不同的事情(多態行爲)
"""

 

from abc import ABCMeta, abstractmethod


class Pet(object, metaclass=ABCMeta):
    """寵物"""

    def __init__(self, nickname):
        self._nickname = nickname

    @abstractmethod
    def make_voice(self):
        """發出聲音"""
        pass


class Dog(Pet):
    """狗"""

    def make_voice(self):
        print('%s:汪汪汪...' % self._nickname)


class Cat(Pet):
    """貓"""

    def make_voice(self):
        print('%s:喵喵喵...' % self._nickname)


def main():
    pets = [Dog('旺財'), Cat('凱蒂'), Dog('大黃')]
    for pet in pets:
        pet.make_voice()


if __name__ == '__main__':
    main()

示例圖:

發佈了79 篇原創文章 · 獲贊 64 · 訪問量 8209
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章