【Python】关键字import与super介绍

来源:互联网 发布:苹果授权网络经销商 编辑:程序博客网 时间:2024/05/22 21:43

import介绍


当开始学习python的时候第一个需要输入的应该就是这个关键字了,使用了那么多词对该关键字的作用没有进行深入了解过,找了机会通过测试和学习官方文档,了解到具体的运行机理。下面就通过文章简单的记录。
import的作用就不详细说明了,它就是在需要某个库或者方法的时候,把相应的库加载到运行目录下。该关键字和C中的include,java里的import是一样的作用。那除了import之外,还有其他方式可以显示加载第三方库吗?答案是肯定可以的。python提供了一个叫importlib的库,可以显示的直接操作import相关的内容。除此之外简单的使用方法__import__也是可以直接引用相应的库。
另外在使用import 的时候,是可以通过try-except关键字来处理相应的异常情况。
下面给出一个简单的例子,开始讲解import的是使用。下面代码是把time模块导入当前路径下,调用time方法输出当前时间的秒数。
import timeprint time.time()
对于import,它是执行了两步操作,search module、load and initialize module
1:search module
当编译器发现import的时候,接下来就开始搜索该module,具体的搜索路径如下:
搜索系统自建的标准库
搜索sys.path下是否存在这些库
sys.path是一个系统变量,它是一个列表形式的数据,这个系统变量可以通过print sys.path打印查看。其中sys.path主要有几种路径组成:首先是当前运行目录下的路径,然后是python安装目录路径,然后还有python的PYTHONPATH的变量规定的目录。除了这些固定的目录之外,我们自己也可以通过修改sys.path来添加python的搜索路径。在这里也可以看出,python中很多东西都是可以很方便的修改,程序员可以操控的。
在sys.path下,当搜索到需要导入的库的时候,该步骤正常返回,进行下一个load module的步骤;如果没有搜索到相应模块,那么返回错误。
2:load module
当搜索模块过程结束,接下来就是执行加载模块的过程。在执行加载的过程中,python会提前检查sys.modules。sys.modules是python的一个缓存,用来缓存已经加载过的模块。该变量是一个dict格式,也可以在代码里print出来。当执行加载过程的时候,检查出缓存里如果存在该模块,那么加载过程直接返回;否则就执行加载过程,把相应模块加载到运行环境,然后在缓存里添加给库的相应信息。

对于import,其不同于C/C++中的include。对于include的实现机制是找到文件之后一般会直接把代码拷贝到当前文件里。但是import只是会做个指向,而不会把import的代码也拷贝到当前文件的运行环境中。

super介绍

在写排序算法的时候,想到使用继承来定义一个顶层父类,来为各种排序算法定义一个算法框架,然后让各种排序算法继承基类,覆盖算法规则,实现自己的排序。所以稍微学习了python的继承实现机制

排序方法父类:

# -*- coding:utf-8 -*-#所有排序方法的基类import randomclass MySort(object):    def __init__(self, name, initial_len):        self.name = name        self.initial_len = initial_len        print "init..."    def init(self):        self.data = []        i = self.initial_len        while (i > 0):            i = i - 1            r = random.randint(0, 99)            self.data.append(r)        return self.data        def sort(self):        pass        def outName(self):        print self.name            def outData(self):        print self.data

子类归并排序:

#-*- coding:utf-8 -*-import MySortclass MergeSort(MySort.MySort):    def __init__(self):        super(MergeSort, self).__init__("mergeSort", 11)        self.pre()            def pre(self):        self.data = self.init()        print self.data            def sort(self):        data = self.data        tmp = [0 for i in range(11)]        i = 1  #子序列长度        size = len(data)        while i < size:            self.mergeSort(data, tmp, i, size)            i = i * 2            self.mergeSort(tmp, data, i, size)            i = i * 2            def mergeSort(self, data, tmp, s, e):        pass                     def outName(self):        super(MergeSort,self).outName()            def outData(self):        super(MergeSort,self).outData()        if __name__ == "__main__":    s = MergeSort()    s.outName()    s.sort()    s.outData() 

其中对于继承来说,如果父类有__init__方法,那么子类定义了__init__方法的时候必须通过super方法显式调用父类的init的方法,用以对父类进行初始化。对于super,其是python的一个内置方法,可以直接调用。python的所有内置函数可以查看https://docs.python.org/3.4/library/functions.html。在旧的类风格中不可以使用super,可以通过调用FatherClass.__init__()方法。

super方法必须使用在新的类风格中。新的类风格从python2.2引入,而旧的类风格在python3中将彻底去除。新的类是所有的类都默认继承一个顶层父类object类,这一点类似与java的设计思想。在python3之前,通过原始的创建类的方式是采用的默认的旧风格的类,即通过class ClassName方式创建;要想使用新的类风格,则必须指定一个集成的父类(如果没有,则继承object),即class ClassName(object)。

这里调用父类的初始化方法就像java中子类中定义了非默认构造函数则必须调用父类的构造函数是一个概念。但是需要注意的是,编译器在你不主动调用的时候,它是不会给出错误警告。

使用super的好处之一,当继承的父类更改之后,不用在每个子类都去修改父类名字。就如本例,MergeSort继承MySort,如果不使用 super(MergeSort,self).outName()来调用顶层方法,那就必须使用MySort.outName()。如果父类改名之后,那必须在每个子类中都修改此处调用才可以,但是使用super的话就不必如此麻烦。

一篇比较好的介绍super用法的文章:http://rhettinger.wordpress.com/2011/05/26/super-considered-super/

新旧类风格

上文对super的讲解已经说其super方法必须使用在新的类风格中,那新旧类的风格有哪些区别那?

在python2.1之前,只存在旧类风格;在python3之后,只存在新类风格。在这之间是新、旧类风格并存。在新、旧类风格并存的这段时间,通过不同的定义方式,来决定你是采用的哪种类的风格。当定义的时候,最顶层的类没有继承object类的时候,那么这中定义方式就是旧的类风格;否则就是新的类风格。在python 3以后,无论你是否显示写出继承object,都是新的类风格。

# old styleclass OldStyle: passclass SubClass(OldStyle): pass# new styleclass Father(object):    def __init__(self, **param):        passclass Son(Father): pass

在python 2.1的时候已经有了类的成熟定义,为何还要定义一种新的类风格那?因为在之前,在python中type和class是两种截然不同的东西。当声明一个对象instance的时候,type(instance)和instance.__class__是不同的定义。在新的类风格中,这两个将会是同一个东西。

instance =  OldStyle()instance2 =  Father()print type(instance)print instance.__class__print type(instance2)print instance2.__class__print Father.__class__ == type.__class__#通过类直接访问__class__属性是只能在新的类风格中使用。#输出<type 'instance'>__main__.OldStyle<class '__main__.Father'><class '__main__.Father'>True

从输出可以看出,对于旧的类风格,对于一个对象的类型是由一个内建类型'instance'实现的,而其class属性却又是另一种定义。因为此种不统一,导致一些问题的出现。因此,在python 2.1之后提出了一种新的类风格。在这种风格中,一个对象的类型,还有其class属性全是统一一种类型;也就是说对一个对象调用type方法和通过instance访问__class__属性,它们的值是一样的。

除此之外,在新的类风格中也有其他的改变。比如上述所讲的添加了对super的支持、MRO相应的改变。对于一个旧的类风格,当通过子类访问一个属性的时候,比如subClass.value,它首先会在本类中进行查找,查找到则返回;否则去父类查找,如果多个父类,则是从左到有依次进行查找。其实可以从此看出python和java的集成在很多情况下都是差不多的。但是相对与新的类风格,通过子类访问属性的时候就比较复杂。


1:module search oder : https://docs.python.org/2/tutorial/modules.html#the-module-search-path

原创粉丝点击