Python反射应用场景(一)

2022-06-07 18:26:27 浏览数 (1)

了解了反射中四个函数的基本用法。那么反射到底有什么用呢?它的应用场景是什么呢?答案是,当不确定所需要的属性和函数是否存在时,可以使用反射。另外一个重要作用是,可以提高代码的扩展性和可维护性。假如我们把所有的加密算法都放到一个叫做encryption的模块中维护 ,并且允许使用这个模块的用户添加更多的加密算法到这个模块中。

encryption的模块内容如下:

代码语言:javascript复制
import hashlib
import os
import sys
def md5(content=None):
    """生成字符串的SHA256值"""
    if content is None:
        return ''
    md5_gen = hashlib.md5()
    md5_gen.update(content.encode('utf-8'))
    md5code = md5_gen.hexdigest()
    return md5code

def sha256(content=None):
    """生成字符串的SHA256值"""
    if content is None:
        return ''
    sha256_gen = hashlib.sha256()
    sha256_gen.update(content.encode('utf-8'))
    sha256code = sha256_gen.hexdigest()
    return sha256code

def sha256_file(filename):
    """生成文件的SHA256值"""
    if not os.path.isfile(filename):
        return ""
    sha256gen = hashlib.sha256()
    size = os.path.getsize(filename)  # 获取文件大小,单位是Byte
    with open(filename, 'rb') as fd:  # 以二进制方式读取文件
        while size >= 1024 * 1024:  # 当文件大于1MB时分块读取文件内容
            sha256gen.update(fd.read(1024 * 1024))
            size -= 1024 * 1024
        sha256gen.update(fd.read())
    sha256code = sha256gen.hexdigest()
    return sha256code

def md5_file(filename):
    """生成文件的MD5值"""
    if not os.path.isfile(filename):
        return ""
    md5gen = hashlib.md5()
    size = os.path.getsize(filename)  # 获取文件大小,单位是Byte
    with open(filename, 'rb') as fd:
        while size >= 1024 * 1024:  # 当文件大于1MB时分块读取文件内容
            md5gen.update(fd.read(1024 * 1024))
            size -= 1024 * 1024
        md5gen.update(fd.read())
    md5code = md5gen.hexdigest()
    return md5code

def encrypt_something(something, algorithm):
    """
    通用加密算法
    :param something: 待加密的内容,字符串或者文件
    :param algorithm: 加密算法
    :return:  加密后的内容
    """
    result = ""
    if algorithm == "md5":
        result = md5(something)
    elif algorithm == "sh256":
        result = sha256(something)
    elif algorithm == "sh256_file":
        result = sha256_file(something)
    elif algorithm == "md5_file":
        result = md5_file(something)
    return result

其中,encrypt_something函数提供了通用加密算法,需要调用者传入待加密的内容和加密算法,这样当调用者使用encryption.py模块时,只需导入encrypt_something函数即可。就像这样:

代码语言:javascript复制
import encryption
print(encryption.encrypt_something("learn_python_by_coding", "sh256"))
print(encryption.encrypt_something("learn_python_by_coding", "md5"))

通过分析encrypt_something函数发现,当我们在encryption.py模块添加更多的加密算法后,就要修改encrypt_something函数,在其中增加新的if分支,随着加密算法的增加,encrypt_something函数的分支会越来越多。

学了反射之后,encrypt_something代码部分就可以这样写:

代码语言:javascript复制
def encrypt_something(something, algorithm):
    """
    通用加密算法
    :param something: 待加密的内容,字符串或者文件
    :param algorithm: 加密算法
    :return:  加密后的内容
    """
    this_module = sys.modules[__name__]
    if hasattr(this_module, algorithm):
        algorithm = getattr(this_module, algorithm)
        result = algorithm(something)
    else:
        raise ValueError("Not support {} algorithm".format(algorithm))
    return result

相比前面的采用if分支语句方式,反射更加简洁明了,可维护性更强,要想增加新的加密方法,只需要在encryption.py模块添加更多的加密算法即可,encrypt_something代码不需要任何变更。

0 人点赞