• Python3.5入门学习记录-模块


    模块让你能够有逻辑地组织你的Python代码段。

    把相关的代码分配到一个 模块里能让你的代码更好用,更易懂。

    模块也是Python对象,具有随机的名字属性用来绑定或引用。

    简单地说,模块就是一个保存了Python代码的文件。模块能定义函数,类和变量。模块里也能包含可执行的代码。

    例子

    一个叫做aname的模块里的Python代码一般都能在一个叫aname.py的文件中找到。下例是个简单的模块common.py。

    def printFunc(param):
        print(("Hello:{0}".format(param)))
        return

    import 语句

    想使用Python源文件,只需在另一个源文件里执行import语句,语法如下:

    import module1[, module2[,... moduleN]

    当解释器遇到import语句,如果模块在当前的搜索路径就会被导入。

    搜索路径是一个解释器会先进行搜索的所有目录的列表。如想要导入模块common.py,需要把命令放在脚本的顶端:

    #导入模块
    import Common
    
    #调用模块里的函数
    Common.printFunc("name")

    From…import语句

    Python的from语句让你从模块中导入一个指定的部分到当前命名空间中。语法如下:

    from modname import name1[, name2[, ... nameN]]

    例如,要导入模块fib的fibonacci函数,使用如下语句:

    from fib import fibonacci
    实例:
    我们在Common.py中在添加一个方法
    def printFunc(param):
        print(("Hello:{0}".format(param)))
        return
    
    def printFunc1(param):
        print(("Hello1:{0}".format(param)))
        return

    然后引入printFunc1

    from Common import printFunc1
    
    printFunc1("printFunc1")

    大家发现了么?from…import引入的函数,不需要使用模块名称就可以直接调用

    From…import* 语句

    把一个模块的所有内容全都导入到当前的命名空间也是可行的,只需使用如下声明:

    from modname import *

    这提供了一个简单的方法来导入一个模块中的所有项目

    命名空间和作用域

    一个Python表达式可以访问局部命名空间和全局命名空间里的变量。如果一个局部变量和一个全局变量重名,则局部变量会覆盖全局变量。

    每个函数都有自己的命名空间。类的方法的作用域规则和通常函数的一样。

    Python会智能地猜测一个变量是局部的还是全局的,它假设任何在函数内赋值的变量都是局部的。

    因此,如果要给全局变量在一个函数里赋值,必须使用global语句。

    global VarName的表达式会告诉Python, VarName是一个全局变量,这样Python就不会在局部命名空间里寻找这个变量了。

    例如,我们在全局命名空间里定义一个变量money。我们再在函数内给变量money赋值,然后Python会假定money是一个局部变量。然而,我们并没有在访问前声明一个局部变量money,结果就是会出现一个UnboundLocalError的错误。取消global语句的注释就能解决这个问题

    Money = 2000
    def AddMoney():
       # 想改正代码就取消以下注释:
       # global Money
       Money = Money + 1
     
    print Money
    AddMoney()
    print Money

    dir()函数

    dir()函数一个排好序的字符串列表,内容是一个模块里定义过的名字。

    返回的列表容纳了在一个模块里定义的所有模块,变量和函数。如下一个简单的实例:

    import Common
    
    list = dir(Common)
    
    print(list)

    输出结果:

    image

    Python中的包

    包是一种管理 Python 模块命名空间的形式,采用"点模块名称"。

    比如一个模块的名称是 A.B, 那么他表示一个包 A中的子模块 B 。

    就好像使用模块的时候,你不用担心不同模块之间的全局变量相互影响一样,采用点模块名称这种形式也不用担心不同库之间的模块重名的情况。

    这样不同的作者都可以提供 NumPy 模块,或者是 Python 图形库。

    不妨假设你想设计一套统一处理声音文件和数据的模块(或者称之为一个"包")。

    现存很多种不同的音频文件格式(基本上都是通过后缀名区分的,例如: .wav,:file:.aiff,:file:.au,),所以你需要有一组不断增加的模块,用来在不同的格式之间转换。

    并且针对这些音频数据,还有很多不同的操作(比如混音,添加回声,增加均衡器功能,创建人造立体声效果),所你还需要一组怎么也写不完的模块来处理这些操作。

    这里给出了一种可能的包结构(在分层的文件系统中):

    sound/                          顶层包
          __init__.py               初始化 sound 包
          formats/                  文件格式转换子包
                  __init__.py
                  wavread.py
                  wavwrite.py
                  aiffread.py
                  aiffwrite.py
                  auread.py
                  auwrite.py
                  ...
          effects/                  声音效果子包
                  __init__.py
                  echo.py
                  surround.py
                  reverse.py
                  ...
          filters/                  filters 子包
                  __init__.py
                  equalizer.py
                  vocoder.py
                  karaoke.py
                  ...

    在导入一个包的时候,Python 会根据 sys.path 中的目录来寻找这个包中包含的子目录。

    目录只有包含一个叫做 __init__.py 的文件才会被认作是一个包,主要是为了避免一些滥俗的名字(比如叫做 string)不小心的影响搜索路径中的有效模块。

    最简单的情况,放一个空的 :file:__init__.py就可以了。当然这个文件中也可以包含一些初始化代码或者为(将在后面介绍的) __all__变量赋值。

    用户可以每次只导入一个包里面的特定模块,比如:

    import sound.effects.echo

    这将会导入子模块:mod:song.effects.echo。 他必须使用全名去访问:

    sound.effects.echo.echofilter(input, output, delay=0.7, atten=4)

    还有一种导入子模块的方法是:

    from sound.effects import echo

    这同样会导入子模块:mod:echo,并且他不需要那些冗长的前缀,所以他可以这样使用:

    echo.echofilter(input, output, delay=0.7, atten=4)

    还有一种变化就是直接导入一个函数或者变量:

    from sound.effects.echo import echofilter

    同样的,这种方法会导入子模块:mod:echo,并且可以直接使用他的:func:echofilter函数:

    echofilter(input, output, delay=0.7, atten=4)

    注意当使用from package import item这种形式的时候,对应的item既可以是包里面的子模块(子包),或者包里面定义的其他名称,比如函数,类或者变量。

    import语法会首先把item当作一个包定义的名称,如果没找到,再试图按照一个模块去导入。如果还没找到,恭喜,一个:exc:ImportError 异常被抛出了。

    反之,如果使用形如import item.subitem.subsubitem这种导入形式,除了最后一项,都必须是包,而最后一项则可以是模块或者是包,但是不可以是类,函数或者变量的名字。


    从一个包中导入*

    设想一下,如果我们使用 from sound.effects import *会发生什么?

    Python 会进入文件系统,找到这个包里面所有的子模块,一个一个的把它们都导入进来。

    但是很不幸,这个方法在 Windows平台上工作的就不是非常好,因为Windows是一个大小写不区分的系统。

    在这类平台上,没有人敢担保一个叫做 ECHO.py 的文件导入为模块:mod:echo还是:mod:Echo甚至:mod:ECHO。

    (例如,Windows 95就很讨厌的把每一个文件的首字母大写显示)而且 DOS 的 8+3 命名规则对长模块名称的处理会把问题搞得更纠结。

    为了解决这个问题,只能烦劳包作者提供一个精确的包的索引了。

    导入语句遵循如下规则:如果包定义文件 __init__.py 存在一个叫做 __all__ 的列表变量,那么在使用 from package import * 的时候就把这个列表中的所有名字作为包内容导入。

    作为包的作者,可别忘了在更新包之后保证 __all__ 也更新了啊。你说我就不这么做,我就不使用导入*这种用法,好吧,没问题,谁让你是老板呢。这里有一个例子,在:file:sounds/effects/__init__.py中包含如下代码:

    __all__ = ["echo", "surround", "reverse"]

    这表示当你使用from sound.effects import *这种用法时,你只会导入包里面这三个子模块。

    如果__all__真的而没有定义,那么使用from sound.effects import *这种语法的时候,就*不会*导入包:mod:sound.effects里的任何子模块。他只是把包:mod:sound.effects和它里面定义的所有内容导入进来(可能运行:file:__init__.py里定义的初始化代码)。

    这会把 :file:__init__.py里面定义的所有名字导入进来。并且他不会破坏掉我们在这句话之前导入的所有明确指定的模块。看下这部分代码:

    import sound.effects.echo
    import sound.effects.surround
    from sound.effects import *

    这个例子中,在执行from...import前,包:mod:sound.effects中的echo和surround模块都被导入到当前的命名空间中了。(当然如果定义了__all__就更没问题了)

    通常我们并不主张使用*这种方法来导入模块,因为这种方法经常会导致代码的可读性降低。不过这样倒的确是可以省去不少敲键的功夫,而且一些模块都设计成了只能通过特定的方法导入。

    记住,使用from Package import specific_submodule这种方法永远不会有错。事实上,这也是推荐的方法。除非是你要导入的子模块有可能和其他包的子模块重名。

    如果在结构中包是一个子包(比如这个例子中对于包:mod:sound来说),而你又想导入兄弟包(同级别的包)你就得使用导入绝对的路径来导入。比如,如果模块:mod:sound.filters.vocoder 要使用包:mod:sound.effects中的模块:mod:echo,你就要写成 from sound.effects import echo。

    from . import echo
    from .. import formats
    from ..filters import equalizer

    无论是隐式的还是显式的相对导入都是从当前模块开始的。主模块的名字永远是"__main__",一个Python应用程序的主模块,应当总是使用绝对路径引用。

    包还提供一个额外的属性,:attr:__path__。这是一个目录列表,里面每一个包含的目录都有为这个包服务的:file:__init__.py,你得在其他:file:__init__.py被执行前定义哦。可以修改这个变量,用来影响包含在包里面的模块和子包。

    这个功能并不常用,一般用来扩展包里面的模块。

  • 相关阅读:
    第13篇-通过InterpreterCodelet存储机器指令片段
    第12篇-认识CodeletMark
    第11篇-认识Stub与StubQueue
    第10篇-初始化模板表
    第9篇-字节码指令的定义
    Java虚拟机漫漫学习路,我终于悟了
    Unity真机连接profiler
    提取图片中文字方法
    登录锁定个人收藏代码
    java判断密码是否为复杂类型(同时包含大小写和数字)
  • 原文地址:https://www.cnblogs.com/jimmy-y/p/5404082.html
Copyright © 2020-2023  润新知