Python学习笔记(五)模块及面向对象编程
参考资料:https://www.liaoxuefeng.com/wiki/001374738125095c955c1e6d8bb493182103fac9270762a000/0013868200171577d6385bb5b4f4875bee9cbf0f0fa29c5000
https://www.liaoxuefeng.com/wiki/001374738125095c955c1e6d8bb493182103fac9270762a000/0013868200385680e8cf932dba9433ea367de9aba2b4784000
1、模块。
在Python中,一个.py文件就称之为一个模块(Module)。使用模块还可以避免函数名和变量名冲突。相同名字的函数和变量完全可以分别存在不同的模块中,因此,我们自己在编写模块时,不必考虑名字会与其他模块冲突。但是也要注意,尽量不要与内置函数名字冲突。
为了避免模块名冲突,Python又引入了按目录来组织模块的方法,称为包(Package)。引入了包以后,只要顶层的包名不与别人冲突,那所有模块都不会与别人冲突。每一个包目录下面都会有一个__init__.py的文件,这个文件是必须存在的,否则,Python就把这个目录当成普通目录,而不是一个包。__init__.py可以是空文件,也可以有Python代码,因为__init__.py本身就是一个模块,而它的模块名就是所在的目录名。
Python内置了很多模块,安装后即可使用。使用前,需要使用import关键字将其引用进来。
引用模块时,还可以使用别名,这样,可以在运行时根据当前环境选择最合适的模块。例子代码如下:
try:
import cStringIO as StringIO
except ImportError: # 导入失败会捕获到ImportError
import StringIO
这样就可以优先导入cStringIO。如果有些平台不提供cStringIO,还可以降级使用StringIO。导入cStringIO时,用import ... as ...指定了别名StringIO,因此,后续代码引用StringIO即可正常工作。
在一个模块中,我们可能会定义很多函数和变量,但有的函数和变量我们希望给别人使用,有的函数和变量我们希望仅仅在模块内部使用。
正常的函数和变量名是公开的(public),可以被直接引用,比如:abc,x123,PI等;
类似__xxx__这样的变量是特殊变量,可以被直接引用,但是有特殊用途,比如上面的__author__,__name__,我们自己的变量一般不要用这种变量名;
类似_xxx和__xxx这样的函数或变量按照约定是非公开的(private),不应该被直接引用,比如_abc,__abc等;尽管Python并没有一种方法可以完全限制访问private函数或变量,但是,从编程习惯上不应该引用private函数或变量。
在Python中,安装第三方模块,是通过setuptools这个工具完成的。Python有两个封装了setuptools的包管理工具:easy_install和pip。目前官方推荐使用pip。一般来说,第三方库都会在Python官方的pypi.python.org网站注册,要安装一个第三方库,必须先知道该库的名称,可以在官网或者pypi上搜索,比如Python Imaging Library的名称叫PIL,因此,安装Python Imaging Library的命令就是:
pip install PIL
当我们试图加载一个模块时,Python会在指定的路径下搜索对应的.py文件,如果找不到,就会报错。默认情况下,Python解释器会搜索当前目录、所有已安装的内置模块和第三方模块,搜索路径存放在sys模块的path变量中。如果我们要添加自己的搜索目录,有两种方法:
一是直接修改sys.path,添加要搜索的目录:
>>> import sys
>>> sys.path.append('...')
这种方法是在运行时修改,运行结束后失效。
第二种方法是设置环境变量PYTHONPATH,该环境变量的内容会被自动添加到模块搜索路径中。设置方式与设置Path环境变量类似。注意只需要添加你自己的搜索路径,Python自己本身的搜索路径不受影响。 Python的每个新版本都会增加一些新的功能,或者对原来的功能作一些改动。有些改动是不兼容旧版本的,也就是在当前版本运行正常的代码,到下一个版本运行就可能不正常了。Python提供了__future__模块,把下一个新版本的特性导入到当前版本,于是我们就可以在当前版本中测试一些新版本的特性。举例说明如下:
from __future__ import division
print 10 / 3
print 10.0 / 3
print 10 // 3
2、面向对象编程。面向对象编程——Object Oriented Programming,简称OOP,是一种程序设计思想。OOP把对象作为程序的基本单元,一个对象包含了数据和操作数据的函数。它是相对于传统的面向过程的程序设计而言。
面向过程的程序设计把计算机程序视为一系列的命令集合,即一组函数的顺序执行。为了简化程序设计,面向过程把函数继续切分为子函数,即把大块函数通过切割成小块函数来降低系统的复杂度。
而面向对象的程序设计把计算机程序视为一组对象的集合,而每个对象都可以接收其他对象发过来的消息,并处理这些消息,计算机程序的执行就是一系列消息在各个对象之间传递。
在Python中,所有数据类型都可以视为对象,当然也可以自定义对象。自定义的对象数据类型就是面向对象中的类(Class)的概念。面向对象的设计思想是从自然界中来的,因为在自然界中,类(Class)和实例(Instance)的概念是很自然的。Class是一种抽象概念,所以,面向对象的设计思想是抽象出Class,根据Class创建Instance。面向对象的抽象程度又比函数要高,因为一个Class既包含数据,又包含操作数据的方法。
Python中使用关键字class来定义类,语法格式:类名=class(父类名称)。Python类通过定义一个特殊的__init__方法(构造函数),在创建实例的时候,将类的属性强制绑定。例子代码如下:
class Student(object):
def __init__(self, name, score):
self.name = name
self.score = score
__init__方法的第一个参数永远是self,表示创建的实例本身,因此,在__init__方法内部,就可以把各种属性绑定到self,因为self就指向创建的实例本身。
有了__init__方法,在创建实例的时候,就不能传入空的参数了,必须传入与__init__方法匹配的参数,但self不需要传,Python解释器自己会把实例变量传进去,例子代码如下:
bart = Student('Bart Simpson', 59)
print bart.name, bart.score
和普通的函数相比,在类中定义的函数只有一点不同,就是第一个参数永远是实例变量self,并且,调用时,不用传递该参数。除此之外,类的方法和普通函数没有什么区别,所以,仍然可以用默认参数、可变参数和关键字参数。
在Python中,实例的变量名如果以__(双下划线)开头,就变成了一个私有变量(private),只有内部可以访问,外部不能访问。
Python中可使用type()函数输出实例的类名称,使用isinstance()函数判断实例是否为指定的类,dir()函数输出给定类名中包含的所有属性和方法名称列表,getattr()函数获取实例指定属性(方法)的值、setattr()函数设置实例指定属性(方法)的值、hasattr()函数判断实例是否包含指定名称的属性(方法)。例子代码如下:
class Student(object):
def __init__(self):
self.name = None
class Teacher(object):
def __init__(self):
self.age = 0
a = Student()
a.name = 'mary'
b = Teacher()
b.age = 30
print 'Type of a is ', type(a)
print 'Is a instance of Student?', isinstance(a, Student)
print 'Is a instance of Teacher?', isinstance(a, Teacher)
print 'Did a include name?', hasattr(a, 'name')
print 'Did b include name?', hasattr(b, 'name')
setattr(b, 'name', 'tom')
print 'Did b include name after setattr?', hasattr(b, 'name')
print 'Name of b is ', getattr(b, 'name')
本节学习完毕,下一节从面向对象高级编程学起!上一篇: python re sub