Python中通过@classmethod 实现多态的示例

 更新时间:2022年11月26日 16:01:09   作者:Bruce小鬼  
这篇文章主要介绍了Python中通过@classmethod 实现多态,python中通常使用对象创建多态模式,python还支持类创建多态模式,下面通过一个例子展示它如何实现多态,需要的朋友可以参考下

通过@classmethod 实现多态

1.概述

python中通常使用对象创建多态模式,python还支持类创建多态模式。下面通过一个例子展示它如何实现多态。

通过对象创建多态和类创建多态开发模式区别

  • 对象多态模式:接收的是一个父类类型对象,然后通过传入父类的子类对象调用普通同名方法,实现不同的行为。
  • 类多态模式:接收的一个父类,然后通过传入父类的子类调用同名的类方法,实现不通的行为

2.类方法创建多态模式示例

2.1.普通模式

先通过一个的示例看下常规方式发开的代码没有使用多态时候存在的问题,然后在通过类多态来优化代码。

下面实现一个读取数据,然后处理数据的示例,他有两条继承体系。
输入信息体系:将输入信息的方式创建为类继承关系,可以根据读取信息的方式创建不同的InputData子类。
处理数据体系:将处理信息的方式创建类继承关系,根据对信息处理的方式创建不同的Worker子类。

然后通过mapreduce函数组合业务执行逻辑,最后输出运行结果。

# 接收输入信息类体系
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

# 组合业务
import os
def generate_inputs(data_dit):
    for name in os.listdir(data_dit):
        # 读文件内容
        yield PathInputData(os.path.join(data_dit, name))

def create_workers(input_list):
    workers = []
    for input_data in input_list:
        # 处理数据
        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')

上面接收信息处理信息的示例存在两个问题:

  • mapreduce函数通用性不好,不易扩展。例如现在创建了新的InputData、Worker子类,那么就要创建一个新的mapreduce函数来组合新的业务流程,这样会导致重复的代码越来越多,不利于维护。
  • python不能向java语言可以在一个类中以重载的形式创建多个构造器,创建一个构造器多态让子类可以根据不同的构造器接收不同的参数。而python不能这么做,因为python的类只能有一个构造方法(init),所以没有办法为不同的子类提供多种形式的形参构造器,在继承中也没有办法要求所有的子类都只接收只有一种方式参数的构造方法。因为子类要根据自身的特点接收不同类型的参数。

这个问题最好能够通过类方法多态来解决,这种多态与实例方法多态很像,只不过他针对的是,而不是这些类的对象

2.2.类方法多态重构业务

类方法多态的实现非常简单,下面将代码中关键的点提炼出来。

  • 在父类中创建一个通用的方法,不需要实现任何业务逻辑,然后让子类中重写该方法,实现不同的行为。在方法上使用@classmethod装饰器声明为类方法,方便调用时候可以以类调用,而不是实例对象调用,通过子类重写父类的类方法就是类方法多态。
  • 在GenericInputData类中定义一个类方法(generate_inputs)用来解决python只有一个构造方法不能实现多种方式接收参数的弊端,子类通过重写该方法,实现接收多种参数行为。
class GenericInputData:
    def read(self):
        raise NotImplementedError
	# 创建一个多态的类方法,让子类实现不同的功能
    @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

# 定义的形参类型为父类,实现了类方法多态
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')

通过类方法多态重构代码后,mapreduce函数支持了多态,它接收的是一个父类类型,根据传入的实际子类实现把不同的功能。当再扩展GenericInputData、GenericWorker子类后,mapreduce函数不需要修改代码,实现了左开右闭原则。

到此这篇关于Python中通过@classmethod 实现多态的文章就介绍到这了,更多相关@classmethod 实现多态内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Python关键字yield的用法详解

    Python关键字yield的用法详解

    在Python编程中,有一个强大而神秘的关键字,那就是yield,初学者常常被它搞得晕头转向,而高级开发者则借助它实现高效的代码,到底yield是什么?它又是如何在Python代码中发挥作用的呢?让我们一起来揭开它的面纱
    2024-07-07
  • 使用Python下的XSLT API进行web开发的简单教程

    使用Python下的XSLT API进行web开发的简单教程

    这篇文章主要介绍了使用Python下的XSLT API进行web开发的简单教程,本文来自于IBM官方网站技术文档,需要的朋友可以参考下
    2015-04-04
  • Python并发执行的几种实现方法

    Python并发执行的几种实现方法

    在Python中多线程是实现并发的一种方式,多线程可以让程序在同一时间内进行多个任务,从而提高程序的效率和执行速度,这篇文章主要给大家介绍了关于Python并发执行的几种实现方法,需要的朋友可以参考下
    2024-08-08
  • 基于Python编写一个根据姓名测性别的小程序

    基于Python编写一个根据姓名测性别的小程序

    这篇文章主要为大家介绍了如何利用Python编写一款根据中文名能猜测性别的一款界面化的小程序,文中的示例代码讲解详细,感兴趣的小伙伴可以了解一下
    2022-03-03
  • Python从Excel中读取日期一列的方法

    Python从Excel中读取日期一列的方法

    今天小编就为大家分享一篇Python从Excel中读取日期一列的方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-11-11
  • python实现图片转字符画

    python实现图片转字符画

    这篇文章主要为大家详细介绍了python实现图片转字符画,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-02-02
  • Python实现基于SVM的分类器的方法

    Python实现基于SVM的分类器的方法

    这篇文章主要介绍了Python实现基于SVM的分类器的方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-07-07
  • Python装饰器用法实例总结

    Python装饰器用法实例总结

    这篇文章主要介绍了Python装饰器用法,结合实例形式总结分析了Python常用装饰器的概念、功能、使用方法及相关注意事项,需要的朋友可以参考下
    2018-02-02
  • Python3实现发送QQ邮件功能(附件)

    Python3实现发送QQ邮件功能(附件)

    这篇文章主要为大家详细介绍了Python3实现发送QQ邮件功能,附件方面,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-12-12
  • Python虚拟环境的创建和使用详解

    Python虚拟环境的创建和使用详解

    这篇文章主要给大家介绍了关于Python虚拟环境的创建和使用的相关资料,文中通过图文介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-09-09

最新评论