最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Python超細(xì)致探究面向?qū)ο?/h1>
 更新時間:2022年06月28日 10:31:15   作者:五包辣條!  
面向?qū)ο缶幊淌且环N編程方式,此編程方式的落地需要使用“類”和 “對象”來實(shí)現(xiàn),所以,面向?qū)ο缶幊唐鋵?shí)就是對 “類”和“對象” 的使用,今天給大家介紹下python 面向?qū)ο箝_發(fā)及基本特征,感興趣的朋友一起看看吧

前言

面向?qū)ο缶幊虒Τ鯇W(xué)者來說不難理解但很難應(yīng)用,雖然我們?yōu)榇蠹铱偨Y(jié)過面向?qū)ο蟮娜阶叻椒ǎǘx類、創(chuàng)建對象、給對象發(fā)消息),但是說起來容易做起來難。大量的編程練習(xí)和閱讀優(yōu)質(zhì)的代碼可能是這個階段最能夠幫助到大家的兩件事情。 接下來我們還是通過經(jīng)典的案例來剖析面向?qū)ο缶幊痰闹R,同時也通過這些案例為大家講解如何運(yùn)用之前學(xué)過的Python知識。

撲克游戲。

說明:簡單起見,我們的撲克只有52張牌(沒有大小王),游戲需要將52張牌發(fā)到4個玩家的手上,每個玩家手上有13張牌,按照黑桃、紅心、草花、方塊的順序和點(diǎn)數(shù)從小到大排列,暫時不實(shí)現(xiàn)其他的功能。

使用面向?qū)ο缶幊谭椒?,首先需要從問題的需求中找到對象并抽象出對應(yīng)的類,此外還要找到對象的屬性和行為。當(dāng)然,這件事情并不是特別困難,我們可以從需求的描述中找出名詞和動詞,名詞通常就是對象或者是對象的屬性,而動詞通常是對象的行為。撲克游戲中至少應(yīng)該有三類對象,分別是牌、撲克和玩家,牌、撲克、玩家三個類也并不是孤立的。類和類之間的關(guān)系可以粗略的分為is-a關(guān)系(繼承)、has-a關(guān)系(關(guān)聯(lián))和use-a關(guān)系(依賴)。很顯然撲克和牌是has-a關(guān)系,因?yàn)橐桓睋淇擞校╤as-a)52張牌;玩家和牌之間不僅有關(guān)聯(lián)關(guān)系還有依賴關(guān)系,因?yàn)橥婕沂稚嫌校╤as-a)牌而且玩家使用了(use-a)牌。

牌的屬性顯而易見,有花色和點(diǎn)數(shù)。我們可以用0到3的四個數(shù)字來代表四種不同的花色,但是這樣的代碼可讀性會非常糟糕,因?yàn)槲覀儾⒉恢篮谔?、紅心、草花、方塊跟0到3的數(shù)字的對應(yīng)關(guān)系。如果一個變量的取值只有有限多個選項(xiàng),我們可以使用枚舉。與C、Java等語言不同的是,Python中沒有聲明枚舉類型的關(guān)鍵字,但是可以通過繼承enum模塊的Enum類來創(chuàng)建枚舉類型,代碼如下所示。

from enum import Enum
class Suite(Enum):
    """花色(枚舉)"""
    SPADE, HEART, CLUB, DIAMOND = range(4)

通過上面的代碼可以看出,定義枚舉類型其實(shí)就是定義符號常量,如SPADE、HEART等。每個符號常量都有與之對應(yīng)的值,這樣表示黑桃就可以不用數(shù)字0,而是用Suite.SPADE;同理,表示方塊可以不用數(shù)字3, 而是用Suite.DIAMOND。注意,使用符號常量肯定是優(yōu)于使用字面常量的,因?yàn)槟軌蜃x懂英文就能理解符號常量的含義,代碼的可讀性會提升很多。Python中的枚舉類型是可迭代類型,簡單的說就是可以將枚舉類型放到for-in循環(huán)中,依次取出每一個符號常量及其對應(yīng)的值,如下所示。

for suite in Suite:
    print(f'{suite}: {suite.value}')

接下來我們可以定義牌類。

class Card:
    """牌"""
    def __init__(self, suite, face):
        self.suite = suite
        self.face = face
    def __repr__(self):
        suites = '????'
        faces = ['', 'A', '2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K']
        # 根據(jù)牌的花色和點(diǎn)數(shù)取到對應(yīng)的字符
        return f'{suites[self.suite.value]}{faces[self.face]}'

可以通過下面的代碼來測試下Card類。

card1 = Card(Suite.SPADE, 5)
card2 = Card(Suite.HEART, 13)
print(card1, card2)    # ?5 ?K

接下來我們定義撲克類。

import random
class Poker:
    """撲克"""
    def __init__(self):
        # 通過列表的生成式語法創(chuàng)建一個裝52張牌的列表
        self.cards = [Card(suite, face) for suite in Suite
                      for face in range(1, 14)]
        # current屬性表示發(fā)牌的位置
        self.current = 0
    def shuffle(self):
        """洗牌"""
        self.current = 0
        # 通過random模塊的shuffle函數(shù)實(shí)現(xiàn)列表的隨機(jī)亂序
        random.shuffle(self.cards)
    def deal(self):
        """發(fā)牌"""
        card = self.cards[self.current]
        self.current += 1
        return card
    @property
    def has_next(self):
        """還有沒有牌可以發(fā)"""
        return self.current < len(self.cards)

可以通過下面的代碼來測試下Poker類。

poker = Poker()
poker.shuffle()
print(poker.cards)

定義玩家類。

class Player:
    """玩家"""
    def __init__(self, name):
        self.name = name
        self.cards = []
    def get_one(self, card):
        """摸牌"""
        self.cards.append(card)
    def arrange(self):
        self.cards.sort()

創(chuàng)建四個玩家并將牌發(fā)到玩家的手上。

poker = Poker()
poker.shuffle()
players = [Player('東邪'), Player('西毒'), Player('南帝'), Player('北丐')]
for _ in range(13):
    for player in players:
        player.get_one(poker.deal())
for player in players:
    player.arrange()
    print(f'{player.name}: ', end='')
    print(player.cards)

執(zhí)行上面的代碼會在player.arrange()那里出現(xiàn)異常,因?yàn)?code>Player的arrange方法使用了列表的sort對玩家手上的牌進(jìn)行排序,排序需要比較兩個Card對象的大小,而<運(yùn)算符又不能直接作用于Card類型,所以就出現(xiàn)了TypeError異常,異常消息為:'<' not supported between instances of 'Card' and 'Card'。

為了解決這個問題,我們可以對Card類的代碼稍作修改,使得兩個Card對象可以直接用<進(jìn)行大小的比較。這里用到技術(shù)叫運(yùn)算符重載,Python中要實(shí)現(xiàn)對<運(yùn)算符的重載,需要在類中添加一個名為__lt__的魔術(shù)方法。很顯然,魔術(shù)方法__lt__中的lt是英文單詞“less than”的縮寫,以此類推,魔術(shù)方法__gt__對應(yīng)>運(yùn)算符,魔術(shù)方法__le__對應(yīng)<=運(yùn)算符,__ge__對應(yīng)>=運(yùn)算符,__eq__對應(yīng)==運(yùn)算符,__ne__對應(yīng)!=運(yùn)算符。

修改后的Card類代碼如下所示。

class Card:
    """牌"""
    def __init__(self, suite, face):
        self.suite = suite
        self.face = face
    def __repr__(self):
        suites = '????'
        faces = ['', 'A', '2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K']
        # 根據(jù)牌的花色和點(diǎn)數(shù)取到對應(yīng)的字符
        return f'{suites[self.suite.value]}{faces[self.face]}'
    def __lt__(self, other):
        # 花色相同比較點(diǎn)數(shù)的大小
        if self.suite == other.suite:
            return self.face < other.face
        # 花色不同比較花色對應(yīng)的值
        return self.suite.value < other.suite.value

說明: 大家可以嘗試在上面代碼的基礎(chǔ)上寫一個簡單的撲克游戲,如21點(diǎn)游戲(Black Jack),游戲的規(guī)則可以自己在網(wǎng)上找一找。

工資結(jié)算系統(tǒng)。

要求:某公司有三種類型的員工,分別是部門經(jīng)理、程序員和銷售員。需要設(shè)計一個工資結(jié)算系統(tǒng),根據(jù)提供的員工信息來計算員工的月薪。其中,部門經(jīng)理的月薪是固定15000元;程序員按工作時間(以小時為單位)支付月薪,每小時200元;銷售員的月薪由1800元底薪加上銷售額5%的提成兩部分構(gòu)成。

通過對上述需求的分析,可以看出部門經(jīng)理、程序員、銷售員都是員工,有相同的屬性和行為,那么我們可以先設(shè)計一個名為Employee的父類,再通過繼承的方式從這個父類派生出部門經(jīng)理、程序員和銷售員三個子類。很顯然,后續(xù)的代碼不會創(chuàng)建Employee 類的對象,因?yàn)槲覀冃枰氖蔷唧w的員工對象,所以這個類可以設(shè)計成專門用于繼承的抽象類。Python中沒有定義抽象類的關(guān)鍵字,但是可以通過abc模塊中名為ABCMeta 的元類來定義抽象類。關(guān)于元類的知識,后面的課程中會有專門的講解,這里不用太糾結(jié)這個概念,記住用法即可。

from abc import ABCMeta, abstractmethod
class Employee(metaclass=ABCMeta):
    """員工"""
    def __init__(self, name):
        self.name = name
    @abstractmethod
    def get_salary(self):
        """結(jié)算月薪"""
        pass

在上面的員工類中,有一個名為get_salary的方法用于結(jié)算月薪,但是由于還沒有確定是哪一類員工,所以結(jié)算月薪雖然是員工的公共行為但這里卻沒有辦法實(shí)現(xiàn)。對于暫時無法實(shí)現(xiàn)的方法,我們可以使用abstractmethod裝飾器將其聲明為抽象方法,所謂抽象方法就是只有聲明沒有實(shí)現(xiàn)的方法,聲明這個方法是為了讓子類去重寫這個方法。接下來的代碼展示了如何從員工類派生出部門經(jīng)理、程序員、銷售員這三個子類以及子類如何重寫父類的抽象方法。

class Manager(Employee):
    """部門經(jīng)理"""
    def get_salary(self):
        return 15000.0
class Programmer(Employee):
    """程序員"""
    def __init__(self, name, working_hour=0):
        super().__init__(name)
        self.working_hour = working_hour
    def get_salary(self):
        return 200 * self.working_hour
class Salesman(Employee):
    """銷售員"""
    def __init__(self, name, sales=0):
        super().__init__(name)
        self.sales = sales
    def get_salary(self):
        return 1800 + self.sales * 0.05

上面的ManagerProgrammer、Salesman三個類都繼承自Employee,三個類都分別重寫了get_salary方法。重寫就是子類對父類已有的方法重新做出實(shí)現(xiàn)。相信大家已經(jīng)注意到了,三個子類中的get_salary各不相同,所以這個方法在程序運(yùn)行時會產(chǎn)生多態(tài)行為,多態(tài)簡單的說就是調(diào)用相同的方法,不同的子類對象做不同的事情。

我們通過下面的代碼來完成這個工資結(jié)算系統(tǒng),由于程序員和銷售員需要分別錄入本月的工作時間和銷售額,所以在下面的代碼中我們使用了Python內(nèi)置的isinstance函數(shù)來判斷員工對象的類型。我們之前講過的type函數(shù)也能識別對象的類型,但是isinstance函數(shù)更加強(qiáng)大,因?yàn)樗梢耘袛喑鲆粋€對象是不是某個繼承結(jié)構(gòu)下的子類型,你可以簡答的理解為type函數(shù)是對對象類型的精準(zhǔn)匹配,而isinstance函數(shù)是對對象類型的模糊匹配。

emps = [
    Manager('劉備'), Programmer('諸葛亮'), Manager('曹操'), 
    Programmer('荀彧'), Salesman('呂布'), Programmer('張遼'),
]
for emp in emps:
    if isinstance(emp, Programmer):
        emp.working_hour = int(input(f'請輸入{emp.name}本月工作時間: '))
    elif isinstance(emp, Salesman):
        emp.sales = float(input(f'請輸入{emp.name}本月銷售額: '))
    print(f'{emp.name}本月工資為: ¥{emp.get_salary():.2f}元')

總結(jié)

面向?qū)ο蟮木幊趟枷敕浅5暮?,也符合人類的正常思維習(xí)慣,但是要想靈活運(yùn)用面向?qū)ο缶幊讨械某橄蟆⒎庋b、繼承、多態(tài)需要長時間的積累和沉淀,這件事情無法一蹴而就,屬于“路漫漫其修遠(yuǎn)兮,吾將上下而求索”的東西。

到此這篇關(guān)于Python超細(xì)致探究面向?qū)ο蟮奈恼戮徒榻B到這了,更多相關(guān)Python 面向?qū)ο髢?nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Python CSV文件模塊的使用案例分析

    Python CSV文件模塊的使用案例分析

    這篇文章主要介紹了Python CSV文件模塊的使用,結(jié)合具體案例形式分析了Python使用csv模塊操作csv文件的相關(guān)使用技巧與相關(guān)注意事項(xiàng),需要的朋友可以參考下
    2019-12-12
  • Python實(shí)現(xiàn)的HTTP并發(fā)測試完整示例

    Python實(shí)現(xiàn)的HTTP并發(fā)測試完整示例

    這篇文章主要介紹了Python實(shí)現(xiàn)的HTTP并發(fā)測試,涉及Python多線程并發(fā)操作相關(guān)實(shí)現(xiàn)技巧,需要的朋友可以參考下
    2015-05-05
  • Python Flask-web表單使用詳解

    Python Flask-web表單使用詳解

    這篇文章主要為大家詳細(xì)介紹了Python Flask-web表單的使用方法,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-11-11
  • python接口自動化測試數(shù)據(jù)和代碼分離解析

    python接口自動化測試數(shù)據(jù)和代碼分離解析

    代碼的可維護(hù)性除了代碼冗余之外還有就是數(shù)據(jù)盡量不要和代碼摻雜在一起,因?yàn)殚喿x起來會非常的凌亂;數(shù)據(jù)分離能更好的增加代碼可讀性和可維護(hù)性,也能更好的二次修改使用
    2021-09-09
  • Python列表排序 list.sort方法和內(nèi)置函數(shù)sorted用法

    Python列表排序 list.sort方法和內(nèi)置函數(shù)sorted用法

    這篇文章主要介紹了Python列表排序 list.sort方法和內(nèi)置函數(shù)sorted用法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2021-03-03
  • 詳細(xì)分析Python可變對象和不可變對象

    詳細(xì)分析Python可變對象和不可變對象

    這篇文章主要介紹了Python可變對象和不可變對象的相關(guān)資料,文中講解非常細(xì)致,代碼幫助大家更好的理解和學(xué)習(xí),感興趣的朋友可以了解下
    2020-07-07
  • Python中使用pypdf2合并、分割、加密pdf文件的代碼詳解

    Python中使用pypdf2合并、分割、加密pdf文件的代碼詳解

    這篇文章主要介紹了Python中使用pypdf2合并、分割、加密pdf文件的代碼,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價值,需要的朋友可以參考下
    2019-05-05
  • Python利用matplotlib實(shí)現(xiàn)動態(tài)可視化詳解

    Python利用matplotlib實(shí)現(xiàn)動態(tài)可視化詳解

    Python中的數(shù)據(jù)可視化是指原始數(shù)據(jù)的圖形表示,以更好地可視化、理解和推理,Python提供了各種庫,包含用于可視化數(shù)據(jù)的不同特性,下面我們就來看看如何利用matplotlib實(shí)現(xiàn)動態(tài)可視化吧
    2023-08-08
  • Python爬豆瓣電影實(shí)例

    Python爬豆瓣電影實(shí)例

    本篇文章給大家通過Python爬豆瓣電影實(shí)例對Python爬蟲更深入的講解,有興趣的學(xué)習(xí)下。
    2018-02-02
  • python中列表(list)和元組(tuple)的深入講解

    python中列表(list)和元組(tuple)的深入講解

    這篇文章主要給大家介紹了關(guān)于python中列表(list)和元組(tuple)的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-03-03

最新評論

盐津县| 吉林市| 常山县| 灌云县| 探索| 辉南县| 远安县| 邻水| 门头沟区| 札达县| 蒙自县| 个旧市| 滁州市| 湖州市| 博乐市| 肇源县| 从化市| 康乐县| 得荣县| 九龙坡区| 嘉义市| 宜良县| 保定市| 萨迦县| 确山县| 浪卡子县| 本溪| 樟树市| 恩平市| 大兴区| 钟山县| 蓝田县| 北安市| 逊克县| 安庆市| 罗田县| 钟山县| 河池市| 唐河县| 资溪县| 枝江市|