python 运算符重载_一锅类似函数重载的小杂烩

优质文章,第一时间送达!

作者:🐲礁sir

这两天写一个爬虫的时候遇到一个场景,要求写一个类放在代码中运行,这个类针对不同的网站会有统一的验证有效性,清理数据步骤,但是不同网站每个步骤具体操作内容是不同的。

也就是说,要求写一个类,函数名称是统一的,但是要根据初始化实例的时候传入的域名修改每个步骤的操作内容。

于是我想到了材料里面的内容。

材料

  • functiontools.singledispatch

  • 抽象基类与切面

  • 多重继承与MRO

  • 重写,重载与猴子补丁

  • 运算符重载

  • 元编程

料理过程

  • functiontools.singledispatch:

  • 抽象基类:

  • 切面(Mixins):

  • 重写(override):

  • 函数重载(overload)和运算符重载:

  • 猴子补丁和鸭子类型:

成品1:

  • 类文件(SampleOperator.py):

from sample_operations import *

class SampleOperator:
def __init__(self, domain):
# 根据传入的域名,确认返回什么样的方法
self.domain = domain.replace('.', '_')
self.special_methods = ['is_valid', 'clean_data']
self.dynamic_load


# 用反射的方式加载方法
def dynamic_load(self):
print('--------{domain} start load--------'.format(domain=self.domain))
for method in self.special_methods:
print(method, hasattr(self, method))
special_method = '_'.join([method, self.domain])
setattr(self, method, globals[special_method])
print(method, hasattr(self, method))
func = getattr(self, method)
func
print('--------{domain} end load--------'.format(domain=self.domain))

if __name__ == '__main__':
test = SampleOperator('test.com')
test.is_valid
test.clean_data
abc = WebsiteOperator('abc.com')
abc.is_valid
abc.clean_data
  • 方法文件(sample_operations.py):

def is_valid_test_com:
print('is_valid_test_com')


def clean_data_test_com:
print('clean_data_test_com')

def is_valid_abc_com:
print('is_valid_abc_com')


def clean_data_abc_com:
print('clean_data_abc_com')
  • 运行效果: 实现了之前设想的通过传入不同域名来动态替换对应的方法内容,用同一个方法名调用

python SampleOperator.py
--------test_com start load--------
is_valid False
is_valid True
is_valid_test_com
clean_data False
clean_data True
clean_data_test_com
--------test_com end load--------
is_valid_test_com
clean_data_test_com
--------abc_com start load--------
is_valid False
is_valid True
is_valid_abc_com
clean_data False
clean_data True
clean_data_abc_com
--------abc_com end load--------
is_valid_abc_com
clean_data_abc_com

成品2:

>>> class A:
... def name(self):
... print('A')
...
>>> class B:
... def name(self):
... print('B')
...
>>> globals
{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': , '__spec__': None, '__annotations__': {}, '__builtins__': , 'A': , 'B': }
>>> globals['A']
>>> globals['A']<__main__.a object at>
>>> globals['A'].name
A

进一步料理:考虑到可能会有十几二十个网站,每个网站最好是单独放一个文件,这样更方便管理和调整。于是想到了python的反射里面动态载入模块

  • 先看看修改后的结构

tree
.
├── SampleOperator.py
└── web_operations
├── __pycache__
│ ├── abc_com.cpython-37.pyc
│ └── test_com.cpython-37.pyc
├── abc_com.py
└── test_com.py
  • SampleOperator.py

import importlib

class SampleOperator:
def __init__(self, domain):
self.domain = domain.replace('.', '_')
self.special_methods = ['is_valid', 'clean_data']
self.dynamic_load

# 用反射的方式加载方法
def dynamic_load(self):
print('--------{domain} start load--------'.format(domain=self.domain))
special_module = importlib.import_module(
'.'.join(['web_operations', self.domain])
)
for method in self.special_methods:
print(method, hasattr(self, method))
# 动态匹配到网站专门的方法
special_method = '_'.join([method, self.domain])
setattr(self, method, getattr(special_module, method))
print(method, hasattr(self, method))
print('--------{domain} end load--------'.format(domain=self.domain))

if __name__ == '__main__':
test = SampleOperator('test.com')
test.is_valid
test.clean_data
abc = SampleOperator('abc.com')
abc.is_valid
abc.clean_data
  • abc_com.py

def is_valid:
print('is_valid_abc_com')


def clean_data:
print('clean_data_abc_com')
  • test_com.py

def is_valid:
print('is_valid_test_com')


def clean_data:
print('clean_data_test_com')

作者个人简介:

大学时用记事本学写html以为这就是编程,后来学java才知面向对象的妙。再到python深入体会到函数式编程,响应式编程的独特风味。方才领悟到这就是我想要的味道。

于是看cpython源码的时候体会到c语言的稳当,再把python里面学到的语法,数据结构,算法,内在特性迁移对比到golang,ruby,lua,js等其他语言,最后能以更加宽广的视角看待编程语言。

我知道编程是片大海,我只是条小鱼,哪怕尽情扑腾也没有多少浪花,但是我只想慢慢感受。

回复下方「关键词」,获取优质资源

回复关键词「 pybook03」,立即获取主页君与小伙伴一起翻译的《Think Python 2e》电子版

回复关键词「入门资料」,立即获取主页君整理的 10 本 Python 入门书的电子版

回复关键词「m」,立即获取Python精选优质文章合集

回复关键词「」,将数字替换成 0 及以上数字,有惊喜好礼哦~

题图:pexels,CC0 授权。

好文章,我在看❤️

本文链接:https://my.lmcjl.com/post/11757.html

展开阅读全文

4 评论

留下您的评论.