美文网首页
package, module, script(二)

package, module, script(二)

作者: deep2world | 来源:发表于2018-08-26 21:52 被阅读0次

    package的目标是为了让客户使用,客户可能是你,可能是组里的合作者,甚至分享给其他需要的人,也就是一个distribution。因此package应当便于安装,引用。package可以有子package。

    使用package里的资源

    有如下结构的pacakge, 外层package名称是test2, 内嵌subpackage1


    package结构

    __init__.py

    #!/usr/bin/python
    # -*- coding: utf-8 -*-
    #filename: __init__.py
    #nothing here, only flag the path as a package
    

    module1.py

    #!/usr/bin/python
    # -*- coding: utf-8 -*-
    #filename: module1.py
    
    def sub(x, y):
      return x - y
    

    module2.py

    #!/usr/bin/python
    # -*- coding: utf-8 -*-
    #filename: module2.py
    
    def add(x, y):
      return x + y
    

    如何使用?
    由于__init__.py中没有进行引用,现在为了使用add或者sub资源,我们需要如下引用

    >>> from test2.module1 import sub
    >>> sub(2, 1)
    1
    >>> 
    

    namespace

    有时,认为像上面那样引用函数,class比较麻烦,希望像from test2 import sub一样引用。将模块,或者子包(sub-package)中的资源通过上层package导出,是一种比较好的命名管理方式。

    • 如何使用
      直接在__init__.py文件中使用import
      __init__.py
    #!/usr/bin/python
    # -*- coding: utf-8 -*-
    #filename: __init__.py
    
    from module1 import sub
    from module2 import add
    

    现在可以直接从test2 package中引入sub和add函数

    >>> from test2 import sub, add
    >>> add(1,2)
    3
    >>> sub(3,1)
    2
    >>> 
    

    如果想在test2 package中导入module1中所有的资源,可以直接from module2 import *, 导入所有除了_开始的资源(_开始的资源应当是私有资源,不应当对外界可见)。

    test2.__init__.py文件

    #!/usr/bin/python
    # -*- coding: utf-8 -*-
    #filename: __init__.py
    
    from module1 import *
    from module2 import add
    
    

    现在可以直接从test2 package中导入module1的资源, 而不用显式的写出test2.module1。

    >>> from test2 import *
    >>> sub(2, 1)
    1
    >>> length(3, 4)
    5.0
    #_power不会被导入
    >>> _power(2)
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    NameError: name '_power' is not defined
    
    • 限制资源
      有时,从某个模块或者sub-package中导入资源,需要限制某些资源,需要使用__all__列表变量明确列出可以导出的资源。

    因此, *表示
    if __all__ list exists in module or __init__.py file of sub-package
         导出__all__列表中指定的资源。
    else
         导出所有资源(_xxx除外)。

    方法如下:
    在__init__.py中, 使用__all__变量,__all__ = ['resource1', 'resource2'..., 'resourceN']。__all__列表变量可以帮助控制当使用import *时,该module或者package哪些模块被导出。但是,不在__all__列表中的,也可以显示的直接导出。

    在module1.py中增加__all__列表变量,将需要导出的资源(函数,类,变量)名称(字符串形式)写在列表中。

    #!/usr/bin/python
    # -*- coding: utf-8 -*-
    #filename: module1.py
    
    from math import sqrt
    
    #需要导出的资源名称
    __all__ = ['sub']
    
    def sub(x, y):
      return x - y
    
    def length(x, y):
      return sqrt(_power(x)+_power(y))
    
    def _power(x):
      return x*x
    
    

    使用

    >>> from test2.module1 import *
    >>> sub(3,1)
    2
    #length没有写在__all__中,因此,这个没有通过*导出来
    >>> length(3,4)
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    NameError: name 'length' is not defined
    #虽然没有通过*导出,但是可以显示引用length函数
    >>> from test2.module1 import length
    >>> length(3,4)
    5.0
    >>> 
    

    当模块或者sub-package中使用__all__时,可以在package的__init__.py中, 这样package也限制了对外暴露的资源。

    #!/usr/bin/python
    # -*- coding: utf-8 -*-
    #filename: __init__.py
    __all__ = []
    __all__.extends(module1.__all__)
    

    总结

    • 在module或package中可以通过引用改变资源的命名空间,这与java或者C#很不一样
    • 可以通过__all__限制资源的导出
    • 可以强制显式的引用资源

    关键字

    • __all__
    • __init__.py
    • import
    • *
    • list
    • extends

    参考

    相关文章

      网友评论

          本文标题:package, module, script(二)

          本文链接:https://www.haomeiwen.com/subject/kbwoiftx.html