资讯专栏INFORMATION COLUMN

Python 包、模块、类的管理方案优化

luqiuwen / 1380人阅读

摘要:需要解决的问题在编写代码的过程中,为了更好的管理代码,我们会使用到包模块类函数。所以用把里的成员,加入这是一个包内部的函数最终就可以实现我们前面所期望的导入方式了。

需要解决的问题

在编写Python代码的过程中,为了更好的管理代码,我们会使用到包(package)、模块(module)、类(class)、函数(function)。
介绍一下这几个概念:

首先是模块,module可以简单理解为就是一个.py文件,这个文件里面可以包含类、变量、常量和函数等;

然后是包,简单理解含有__init__.py的目录就算是一个包,需要明确的是在python中包其实是一种特殊的模块,但模块并不是包。原因其实很简单,sys.modules我们获取到的结果中包含包和模块,而module.__package__则会获取到包的信息;

最后是类(函数在这里就不说了),类会写在.py文件中,一般为了控制文件的大小,通常将一个或几个有关联的类写在一个文件中。当然个人还是觉得一个类独占一个文件比较好,除非你想看见一大堆乱糟糟的代码挤在一个超大的文件里。

然后再来看看我们日常使用包、模块和类的做法

# 目录结构
#|--demo.py
#|--package_a
#   |--__init__.py
#   |--class_a.py  类ClassA
#   |--class_b.py  类ClassB

# ./demo.py

# 导入方式一
from package_a.class_a import ClassA
from package_a.class_a import ClassB
a = ClassA()
b = ClassB()

# 导入方式二
import package_a.class_a as ca
import package_a.class_b as cb
a = ca.ClassA()
b = cb.ClassB()

好的,我们的问题来了,怎么样才能减少我们导入部分的代码呢?或者说怎么样才能使得一些相关联的模块不需要一个一个的进行导入呢?最终实现到下面的样子是不是会更好

# ./demo.py

from package_a import *
a = ClassA()
b = ClassB()
解决的方法
# ./common.py
import sys

_packet_ = {}
# 装饰器,func是类或者函数
def export(func):
    module = sys.modules[func.__module__]        # 获取func的模块对象
    package = sys.modules[module.__package__]    # 由模块对象得到包对象
    package.__dict__[func.__name__] = func       # 把func添加到包的__dict__里
    # 生成所有使用该解决方案的包的__all__变量,并把导出的func添加进去
    if not package.__name__ in _packet_:
        _packet_[package.__name__] = []
    _packet_[package.__name__].append(func.__name__)
    # 原封不动地把func返回
    return func

# 在包的__init__.py里用于获取__all__
def packet(name):
    if not name in _packet_:
        _packet_[name] = []
    return _packet_[name]
实际使用
# 目录结构
#|--common.py(就是上面的装饰器文件)
#|--demo.py
#|--package_a
#   |--__init__.py
#   |--class_a.py  类ClassA
#   |--class_b.py  类ClassB

首先在模块中处理我们创建的类

# ./package_a/class_a.py

import common

# 使用export装饰器,装饰要导出的类或函数
@common.export
class ClassB(object):
    def __init__(self):
        print "This is ClassB."

然后在包的__init__.py中修改包自身

# ./package_a/__init__.py

import common

# 注意,这步很重要!!!导入将要导出的子模块,需要具体模块名字,此处import * 不可用
from . import class_a, class_b

# 用packet初始化包的__all__,主要是用于支持 "from . import *" 导入
__all__ = common.packet(__name__)

# 因为用__all__会影响"from . import *"。所以用export把__init__.py里的成员,加入__all__
@common.export
def pafunc():
    """ 这是一个包内部的函数 """
    print("pafunc")

最终就可以实现我们前面所期望的导入方式了。

# ./demo.py

from package_a import *
a = ClassA()

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/41703.html

相关文章

  • Python-爬虫工程师-面试总结

    摘要:内存池机制提供了对内存的垃圾收集机制,但是它将不用的内存放到内存池而不是返回给操作系统。为了加速的执行效率,引入了一个内存池机制,用于管理对小块内存的申请和释放。 注:答案一般在网上都能够找到。1.对if __name__ == main的理解陈述2.python是如何进行内存管理的?3.请写出一段Python代码实现删除一个list里面的重复元素4.Python里面如何拷贝一个对象?...

    antz 评论0 收藏0
  • 宜信开源|数据库审核软件Themis部署攻略

    摘要:一介绍是宜信公司团队开发的一款数据库审核产品,可帮助开发人员快速发现数据库质量问题,提升工作效率。此平台可实现对数据库进行多维度对象结构文本执行计划及执行特征的审核,用以评估对象结构设计质量及运行效率。执行计划指数据库中的执行计划。 一、介绍 Themis是宜信公司DBA团队开发的一款数据库审核产品,可帮助DBA、开发人员快速发现数据库质量问题,提升工作效率。其名称源自希腊神话中的正义...

    fsmStudy 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<