亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Python中通過@classmethod 實(shí)現(xiàn)多態(tài)的示例

 更新時(shí)間:2022年11月26日 16:01:09   作者:Bruce小鬼  
這篇文章主要介紹了Python中通過@classmethod 實(shí)現(xiàn)多態(tài),python中通常使用對(duì)象創(chuàng)建多態(tài)模式,python還支持類創(chuàng)建多態(tài)模式,下面通過一個(gè)例子展示它如何實(shí)現(xiàn)多態(tài),需要的朋友可以參考下

通過@classmethod 實(shí)現(xiàn)多態(tài)

1.概述

python中通常使用對(duì)象創(chuàng)建多態(tài)模式,python還支持類創(chuàng)建多態(tài)模式。下面通過一個(gè)例子展示它如何實(shí)現(xiàn)多態(tài)。

通過對(duì)象創(chuàng)建多態(tài)和類創(chuàng)建多態(tài)開發(fā)模式區(qū)別

  • 對(duì)象多態(tài)模式:接收的是一個(gè)父類類型對(duì)象,然后通過傳入父類的子類對(duì)象調(diào)用普通同名方法,實(shí)現(xiàn)不同的行為。
  • 類多態(tài)模式:接收的一個(gè)父類,然后通過傳入父類的子類調(diào)用同名的類方法,實(shí)現(xiàn)不通的行為

2.類方法創(chuàng)建多態(tài)模式示例

2.1.普通模式

先通過一個(gè)的示例看下常規(guī)方式發(fā)開的代碼沒有使用多態(tài)時(shí)候存在的問題,然后在通過類多態(tài)來優(yōu)化代碼。

下面實(shí)現(xiàn)一個(gè)讀取數(shù)據(jù),然后處理數(shù)據(jù)的示例,他有兩條繼承體系。
輸入信息體系:將輸入信息的方式創(chuàng)建為類繼承關(guān)系,可以根據(jù)讀取信息的方式創(chuàng)建不同的InputData子類。
處理數(shù)據(jù)體系:將處理信息的方式創(chuàng)建類繼承關(guān)系,根據(jù)對(duì)信息處理的方式創(chuàng)建不同的Worker子類。

然后通過mapreduce函數(shù)組合業(yè)務(wù)執(zhí)行邏輯,最后輸出運(yùn)行結(jié)果。

# 接收輸入信息類體系
class InputData:
    def read(self):
        raise NotImplementedError

class PathInputData(InputData):
    def __init__(self,path):
        super().__init__()
        self.path = path

    def read(self):
        with open(self.path) as f:
            return f.read()

# 處理信息類體系
class Worker:
    def __init__(self, input_data):
        self.input_data = input_data
        self.result = None

    def map(self):
        raise NotImplementedError

    def reduce(self, other):
        raise NotImplementedError

class LineCountWorker(Worker):
    def map(self):
        data = self.input_data
        self.result = data.count('/n')

    def reduce(self, other):
        self.result += other.result

# 組合業(yè)務(wù)
import os
def generate_inputs(data_dit):
    for name in os.listdir(data_dit):
        # 讀文件內(nèi)容
        yield PathInputData(os.path.join(data_dit, name))

def create_workers(input_list):
    workers = []
    for input_data in input_list:
        # 處理數(shù)據(jù)
        workers.append(LineCountWorker(input_data))
    return workers

from threading import Thread
def execute(workers):
    threads = [Thread(target=w.map) for w in workers]
    for thread in threads: thread.start()
    for thread in threads: thread.join()

    first, *rest = workers
    for worker in rest:
        first.reduce(worker)
    return first.result

def mapreduce(data_dir):
    inputs = generate_inputs(data_dir)
    workers = create_workers(inputs)
    return execute(workers)

import os
import random
def write_test_files(tmpdir):
    os.makedirs(tmpdir)
    for i in range(100):
        with open(os.path.join(tmpdir, str(i)), 'w') as f:
            f.write('\n' * random.randint(0, 100))
tmpdir = 'test_inputs'
write_test_files(tmpdir)
result = mapreduce(tmpdir)
print(f'There are  {result} lines')

上面接收信息處理信息的示例存在兩個(gè)問題:

  • mapreduce函數(shù)通用性不好,不易擴(kuò)展。例如現(xiàn)在創(chuàng)建了新的InputData、Worker子類,那么就要?jiǎng)?chuàng)建一個(gè)新的mapreduce函數(shù)來組合新的業(yè)務(wù)流程,這樣會(huì)導(dǎo)致重復(fù)的代碼越來越多,不利于維護(hù)。
  • python不能向java語言可以在一個(gè)類中以重載的形式創(chuàng)建多個(gè)構(gòu)造器,創(chuàng)建一個(gè)構(gòu)造器多態(tài)讓子類可以根據(jù)不同的構(gòu)造器接收不同的參數(shù)。而python不能這么做,因?yàn)閜ython的類只能有一個(gè)構(gòu)造方法(init),所以沒有辦法為不同的子類提供多種形式的形參構(gòu)造器,在繼承中也沒有辦法要求所有的子類都只接收只有一種方式參數(shù)的構(gòu)造方法。因?yàn)樽宇愐鶕?jù)自身的特點(diǎn)接收不同類型的參數(shù)。

這個(gè)問題最好能夠通過類方法多態(tài)來解決,這種多態(tài)與實(shí)例方法多態(tài)很像,只不過他針對(duì)的是,而不是這些類的對(duì)象。

2.2.類方法多態(tài)重構(gòu)業(yè)務(wù)

類方法多態(tài)的實(shí)現(xiàn)非常簡單,下面將代碼中關(guān)鍵的點(diǎn)提煉出來。

  • 在父類中創(chuàng)建一個(gè)通用的方法,不需要實(shí)現(xiàn)任何業(yè)務(wù)邏輯,然后讓子類中重寫該方法,實(shí)現(xiàn)不同的行為。在方法上使用@classmethod裝飾器聲明為類方法,方便調(diào)用時(shí)候可以以類調(diào)用,而不是實(shí)例對(duì)象調(diào)用,通過子類重寫父類的類方法就是類方法多態(tài)。
  • 在GenericInputData類中定義一個(gè)類方法(generate_inputs)用來解決python只有一個(gè)構(gòu)造方法不能實(shí)現(xiàn)多種方式接收參數(shù)的弊端,子類通過重寫該方法,實(shí)現(xiàn)接收多種參數(shù)行為。
class GenericInputData:
    def read(self):
        raise NotImplementedError
	# 創(chuàng)建一個(gè)多態(tài)的類方法,讓子類實(shí)現(xiàn)不同的功能
    @classmethod
    def generate_inputs(cls, config):
        raise NotImplementedError

class PathInputData(GenericInputData):
    def __init__(self, path):
        super().__init__()
        self.path = path

    def read(self):
        with open(self.path) as f:
            return f.read()
	# 子類重寫父類的類方法
    @classmethod
    def generate_inputs(cls, config):
        data_dir = config['data_dir']
        for name in os.listdir(data_dir):
            yield cls(os.path.join(data_dir, name))


class GenericWorker:
    def __init__(self, input_data):
        self.input_data = input_data
        self.result = None

    def map(self):
        raise NotImplementedError

    def reduce(self, other):
        raise NotImplementedError

    @classmethod
    def create_workers(cls, input_class, config):
        workers = []
        for input_data in input_class.generate_inputs(config):
            workers.append(cls(input_data))
        return workers

class LineCountWorker(GenericWorker):
    def map(self):
        data = self.input_data.read()
        self.result = data.count('\n')

    def reduce(self, other):
        self.result += other.result

# 定義的形參類型為父類,實(shí)現(xiàn)了類方法多態(tài)
def mapreduce(worker_class, input_class, config):
    workers = worker_class.create_workers(input_class, config)
    return execute(workers)
config = {'data_dir': tmpdir}
result = mapreduce(LineCountWorker, PathInputData, config)
print(f'There are {result} lines')

通過類方法多態(tài)重構(gòu)代碼后,mapreduce函數(shù)支持了多態(tài),它接收的是一個(gè)父類類型,根據(jù)傳入的實(shí)際子類實(shí)現(xiàn)把不同的功能。當(dāng)再擴(kuò)展GenericInputData、GenericWorker子類后,mapreduce函數(shù)不需要修改代碼,實(shí)現(xiàn)了左開右閉原則。

到此這篇關(guān)于Python中通過@classmethod 實(shí)現(xiàn)多態(tài)的文章就介紹到這了,更多相關(guān)@classmethod 實(shí)現(xiàn)多態(tài)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Python關(guān)鍵字yield的用法詳解

    Python關(guān)鍵字yield的用法詳解

    在Python編程中,有一個(gè)強(qiáng)大而神秘的關(guān)鍵字,那就是yield,初學(xué)者常常被它搞得暈頭轉(zhuǎn)向,而高級(jí)開發(fā)者則借助它實(shí)現(xiàn)高效的代碼,到底yield是什么?它又是如何在Python代碼中發(fā)揮作用的呢?讓我們一起來揭開它的面紗
    2024-07-07
  • 使用Python下的XSLT API進(jìn)行web開發(fā)的簡單教程

    使用Python下的XSLT API進(jìn)行web開發(fā)的簡單教程

    這篇文章主要介紹了使用Python下的XSLT API進(jìn)行web開發(fā)的簡單教程,本文來自于IBM官方網(wǎng)站技術(shù)文檔,需要的朋友可以參考下
    2015-04-04
  • Python并發(fā)執(zhí)行的幾種實(shí)現(xiàn)方法

    Python并發(fā)執(zhí)行的幾種實(shí)現(xiàn)方法

    在Python中多線程是實(shí)現(xiàn)并發(fā)的一種方式,多線程可以讓程序在同一時(shí)間內(nèi)進(jìn)行多個(gè)任務(wù),從而提高程序的效率和執(zhí)行速度,這篇文章主要給大家介紹了關(guān)于Python并發(fā)執(zhí)行的幾種實(shí)現(xiàn)方法,需要的朋友可以參考下
    2024-08-08
  • 基于Python編寫一個(gè)根據(jù)姓名測性別的小程序

    基于Python編寫一個(gè)根據(jù)姓名測性別的小程序

    這篇文章主要為大家介紹了如何利用Python編寫一款根據(jù)中文名能猜測性別的一款界面化的小程序,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以了解一下
    2022-03-03
  • Python從Excel中讀取日期一列的方法

    Python從Excel中讀取日期一列的方法

    今天小編就為大家分享一篇Python從Excel中讀取日期一列的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2018-11-11
  • python實(shí)現(xiàn)圖片轉(zhuǎn)字符畫

    python實(shí)現(xiàn)圖片轉(zhuǎn)字符畫

    這篇文章主要為大家詳細(xì)介紹了python實(shí)現(xiàn)圖片轉(zhuǎn)字符畫,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-02-02
  • Python實(shí)現(xiàn)基于SVM的分類器的方法

    Python實(shí)現(xiàn)基于SVM的分類器的方法

    這篇文章主要介紹了Python實(shí)現(xiàn)基于SVM的分類器的方法,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-07-07
  • Python裝飾器用法實(shí)例總結(jié)

    Python裝飾器用法實(shí)例總結(jié)

    這篇文章主要介紹了Python裝飾器用法,結(jié)合實(shí)例形式總結(jié)分析了Python常用裝飾器的概念、功能、使用方法及相關(guān)注意事項(xiàng),需要的朋友可以參考下
    2018-02-02
  • Python3實(shí)現(xiàn)發(fā)送QQ郵件功能(附件)

    Python3實(shí)現(xiàn)發(fā)送QQ郵件功能(附件)

    這篇文章主要為大家詳細(xì)介紹了Python3實(shí)現(xiàn)發(fā)送QQ郵件功能,附件方面,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-12-12
  • Python虛擬環(huán)境的創(chuàng)建和使用詳解

    Python虛擬環(huán)境的創(chuàng)建和使用詳解

    這篇文章主要給大家介紹了關(guān)于Python虛擬環(huán)境的創(chuàng)建和使用的相關(guān)資料,文中通過圖文介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-09-09

最新評(píng)論