• Python模块与包


    模块

    模块是非常简单的Python文件,单个Python文件就是一个模块,两个文件就是两个模块。

    import语句是用来导入模块或者从模块里导入特定的类或者函数。如前面我们用过的math模块,从而可以使用sqrt函数来计算距离。

    假如有一个包含Database类的database.py的模块。现有另一个模块为product.py,它需要从database.py里实例化一个Database类,然后就可以在数据库中执行相关产品查询。

    import database
    db = database.Database()
    #数据库搜索操作

    这时任何在database这个模块里面的类或者函数,都可以通过database.<something>这种激发访问。或者,也可以用from ... import语法来导入一个类。

    from database import Database
    db = Database()

    也可以将导入的类进行重命名

    from database import Database as DB  # 重命名
    db = DB()

    也可以在一行里面导入多项,比如database还含有Query类

    from database import Database, Query

    但是,很多教程与经验建议不要导入模块里面所有的类,如下的写法是不采用的。

    from database import * 

    组织模块

    一个包(package)就是放在一个文件夹里的模块集合。包的名字就是文件夹的名字。我们需要做的是告诉python这个文件夹是一个包,并且把一个名为__init__.py的文件(通常是空的)放在这个文件夹里。如果我们忘记创建这个文件夹,就没法从这个文件夹里面导入那些模块。

    例如在我们的工作目录里,把我们的模块放在了一个叫ecommerce(电子商务)的包里,这个目录同样包含一个main.py的文件用来启动程序。在ecommerce包里再添加一个payments的包用来管理不同的付款方式,文件夹的层次结构如下所示:

    parent_directory/
        main.py
        ecommerce/
            __init__.py
            database.py
            products.py
            payments/
                __init__.py
                paypal.py
                authorizenet.py

    其中producs.py的有Product类

    class Product:
        pass

    database.py有Database类

    class Database:
        pass

    模块的导入方式有两种:绝对导入和相对导入。

    绝对导入

    要先给出这个模块、函数的完整路径,如在main.py需要访问produces模块中的Product类,使用使用如下的方法进行绝对导入:

    import ecommerce.products
    product = ecommerce.products.Product()

    或者(个人比较喜欢这种方式):

    from ecommerce.products import Product
    product = Product()

    或者:

    from ecommerce import products
    product = products.Product()

    import语句使用点号作为分隔符来分隔包或者模块

    上述的都可以使用,如果要导入一个模块中的很多类,使用使用第三种方法,如果是指导入一个模块的一两个类,则可以使用第二种方法具体指明。

    相对导入

    在包(package)的情况下,如果知道父模块的名称,那么就可以使用相对导入。比如当前在products模块下工作,想从隔壁的database模块导入Database类,就可以使用相对导入:

    from .database import Database   # 点号表示使用当前路径的database模块

    如果我们正在编辑ecommerce.payments包里的paypal模块,需要引用父包里的database模块:

    from ..database import Database  # 使用两个点号表示访问上层的父类

    如果ecommerce有contact包,该包里有email模块,需要将该模块的sendEmail函数导入到paypal模块中,

    from ..contact.email import sendEmail   

     数据访问权限

    大部分的面向对象的编程语言都有一个“访问控制”的概念,比如私有的(private)、受保护的(protected)和公共的(public)。但python并没有这种强制规定。在技术层面上,一个类里的所有方法和属性都是公共可访问的,以下有三种形式建议不同的访问形式:

    1、使用注释进行提示建议。如可以在docstring里面放一个提示来表明这个方法只是内部使用的

    2、给某个属性或者方法加一个下划线的前缀,大部分python程序员会把这个解释为“这是个内部变量,使用之前要三思”

    3、给某个属性或者方法添加一个双下划线的前缀,强烈建议为内部变量。访问时需要名称改编(name mangling),即在该方法或者属性前面自动加一个_<classname>的前缀(单下划线)。

    一般情况下,不会使用加下划线或者双下划线的变量。

    class SecretString:
        ''' A not-at-all secure way to store a secret string'''
    
        def __init__(self, plain_string, pass_phrase):
            self.__plain_string = plain_string
            self.__pass_phrase = pass_phrase 
    
        def decrypt(self, pass_phrase):
            ''' Only show the string if the pass_phrase is correct.'''
            if pass_phrase == self.__pass_phrase:
                return self.__plain_string
            else:
                return 

    将上述代码存储为filename.py,然后使用python -i filename.py执行这个脚本,然后在交互的解释器里进行如下的测试:

    >>> secret_string = SecretString("ACME: Top Secret", "antwerp")
    >>> print(secret_string.decrypt("antwerp"))
    ACME: Top Secret
    >>> print(secret_string.__plain_text)
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    AttributeError: 'SecretString' object has no attribute '__plain_text'
    >>> print(secret_string._SecretString__plain_string)
    ACME: Top Secret

    从包里直接导入变量

    在ecommerce包里有两个模块,一个是database.py,另一个是products.py,假设database里面有一个db变量,这个变量在很多地方都会被访问,那么我们下面的代码将可以实现用import ecommerce.db取代import ecommerce.database.db。

    通过在__init__.py文件(定义目录为包),在这里文件中可以包含任意变量或者类的生命,而且它会作为这个包的一部分被我们使用。在这个例子中,如果有ecommerce/__init__.py文件里包含这么一行:

    from .database import db

    那么我们就可以用下面的语句,在mian.py或者其他文件访问这个db属性了:

    from ecommerce import db

    以上主要在于导致ecommerce.py这个文件是一个模块而不是包的原因在于__init__.py。

    如果你把所有代码放在了一个单独的模块,之后又决定拆成一个包里的多个包,__init__.py文件同样对你有帮忙。

    其他模块如果想要访问这个新包,__init__.py文件仍然是主要的切入点。但是在内部,代码仍然可以被组织成许多不同模块或者子包。

    参考:

    1、《Python3 面向对象编程》 [加]Dusty Philips 著

  • 相关阅读:
    SpringCloud : yml文件配置 获取系统环境变量的值
    SpringCloud : 多个 @FeignClient 注解 value 设置为同一个应用的解决方案
    SpringCloud : Feign 不捆绑远程应用名称, 实现服务应用名称传入,调用通用自动化
    SpringCloud : Feign 使用 FastJson 解析数据
    Mybatis中在log日志或控制台打印执行的sql
    iOS 基于 itemServices 进行本地安装 ipa 应用安装包
    MySQL5.5 数据热备份
    如何在 Fiddler Script 中 自定义 修改 Request 、 Response
    Dubbo 分布式 日志 追踪
    shell脚本并发执行
  • 原文地址:https://www.cnblogs.com/anovana/p/8134520.html
Copyright © 2020-2023  润新知