Python入门教程之python对象与面向对象

发布时间:2020-11-30编辑:脚本学堂
本文介绍了python中对象与面向对象的相关知识,有关python入门教程中python面向对象的部分,感兴趣的朋友参考下。

一、模块导入
python有两种导入模块的方法,import module和from module import,二者功能基本相同,但也有细微差别,举例说明如下:
 

复制代码 代码示例:
>>> import types
>>> types.FunctionType(1)
<type 'function'>
>>> FunctionType(2)
Traceback (innermost last):
    File "<interactive input>", line 1, in ?
NameError: There is no variable named 'FunctionType'
>>> from types import FunctionType     (3)
>>> FunctionType       (4)
<type 'function'>
 

(1)types模块不包含方法,只是表示每种Python对象类型的属性,注意这个属性必须要用模块名types进行限定。
(2)FunctionType本身没有被定义在当前名字空间中,它只存在于types的上下文环境中。
(3)这个语法从types模块中直接将FunctionType属性导入到局部名字空间中。
(4)现在FunctionType可以直接使用,与types无关了。

从上不难看出,二者区别在于后者被导入模块types的属性和方法被直接导入到局部名字空间去了,所以它们可以直接使用,而不需要加上模块名的限定。
那么什么时候使用from module import呢:
(1)如果你要经常访问模块的属性和方法,且不想一遍又一遍地敲入模块名,使用from module import。
(2)如果你想要有选择地导入某些属性和方法,而不想要其它的,使用from module import。
(3)如果模块包含的属性和方法与你的某个模块同名,你必须使用import module来避免名字冲突。
需要注意的是:应该尽量少用from module import *,因为判定一个特殊的函数或属性是从哪里来的有些困难,并且会造成调试和重构都更困难。
更多关于二者的区别,请参看这里。   

二、类的定义
Python是完全面向对象的,你可以定义自己的类,从自己的或者内置的类继承,然后从你定义的类创建实例。
1、简单类或基类
在Python中定义类很简单,Python类以保留字class开始,后面跟着类名:
class Loaf:(1)
    pass    (2)(3)
(1)类名通常第一个字母大写,但这不是必须的。
(2)类可以没有任何方法或属性,但从语法上,需要在定义中有些东西,所以需要一个占位符pass,它是Python的保留字,其什么都不做仅仅表示“向前看,不要往这里看”。pass语句类似于C/C++中的大括号空集{}。
(3)在类中所有东西都要缩进,第一条不缩进的语句不属于这个类。

2、继承类或子类
 

复制代码 代码示例:
from UserDict import UserDict
class FileInfo(UserDict):

在Python中,类的基类只是简单地列在类名后面的小括号里,所以FileInfo类是从UserDict类继承而来的。Python支持多重继承,在类名后面的小括号中,列出所有基类,以逗号分隔。
Python类没有显示的构造函数析构函数,但有类似构造函数的方法__init__。
 

复制代码 代码示例:
class FileInfo(UserDict)
"store file metadata"   (1)
def __init__(self, filename=None):(2)
UserDict.__init__(self) (3)
self["name"] = filename   

(1)类可以并且应该有doc strings,就像方法和函数一样。
(2)__init__在类的实例创建后被立即调用,其行为与C++中的构造函数相似,但区别是Python中对象在调用__init__时已经被构造出来了,且已经有一个对类的新实例的有效引用。每个类方法的第一个参数,包括__init__,都是指向类的当前实例的引用,按照习惯为self,但不是必须如此命名,self类似于C++中的this,在__init__方法中,self指向新创建的对象,在其它类方法中,self指向方法被调用的类实例,在方法定义时需要明确指定self,但在调用方法时,不用指定self,Python会自动替你加上。__init__方法可以接受任意个数的参数,参数可以用缺省值定义,可以设置成对于调用者可选,比如:filename的缺省值为None,即Python的空值。__init__方法从不返回一个值。
(3)Python中,父类的方法不会在子类方法执行前被自动调用,而必须显示地调用父类中的适合方法。

3、何时使用self和__init__
(1)当定义你自己的类方法时,必须明确将self作为每个方法的第一个参数列出,包括__init__。
(2)当从你的类中调用一个父类的一个方法时,必须包括self参数,但是当你从类的外部调用类的方法时,不必对self参数指定任何值,Python会自动地替你增加实例的引用即self。
(3)__init__方法是可选的,但是一旦定义了,就必须记得显示调用父类的__init__方法(如果它定义了)。引申行为:无论何时子类想扩展父类的行为,子类方法必须在适当的时机,使用适当的参数,显示调用父类方法。
      
三、类的实例化
1、实例化
在Python中对类进行实例化很直接,为了对类进行实例化,只要调用类,就像类是一个函数一样,传入定义在__init__方法中的参数,返回值将是新创建的对象:
 

复制代码 代码示例:
>>> import fileinfo
>>> f = fileinfo.FileInfo("/music/_singles/kairo.mp3")    (1)
>>> f.__class__      (2)
<class fileinfo.FileInfo at 010EC204>
>>> f.__doc__       (3)
'store file metadata'
>>> f   
{'name': '/music/_singles/kairo.mp3'}
 

(1)创建类FileInfo(定义在fileinfo模块中)的实例,将新创建的实例赋值给变量f,传入参数/music/_singles/kairo.mp3给__init__方法中的filename参数。
(2)每个类的实例有一个内置属性,__class__是对象的类,类元数据可以通过对象本身的属性得到,包括__class__、__name__、__bases__等。
(3)可以像对象函数或模块一样来访问实例的doc string,一个类的所有实例共享相同的doc string。
2、垃圾回收
类实例的销毁非常简单,通常不需要明确地释放实例,当指派给实例的变量超出作用域时,会被自动地释放,内存泄露在Python中很少见,在Python中使用引用计数来实现垃圾回收。

四、类属性
在Python中,类属性由类本身所拥有,数据属性由一个特定的类实例所拥有,类属性相当于C++中类的静态变量,数据属性相当于C++中类的成员变量,类属性定义在类定义之后,数据属性定义在__init__方法中。
1、类属性
 

复制代码 代码示例:
class MP3FileInfo(FileInfo):
"store ID3V1.0 MP3 tags"
tagDataMap = {"title"    :    (3, 33, stripnulls),
      "year"   :    (93, 97, stripnulls),
      "genre" :    (127, 128, ord)}
>>> import fileinfo
>>> fileinfo.MP3FileInfo    (1)
<class fileinfo.MP3FileInfo at 01257FDC>
>>> fileinfo.MP3FileInfo.tagDataMap   (2)
{'title' : (3, 33, <function stripnulls at 0260C8D4>),
'genre': (127, 128, <built-in function ord>),
'year' : (93, 97, <function stripnulls at 0260C8D4>)}
>>> m = fileinfo.MP3FileInfo()   (3)
>>> m.tagDataMap
{'title' : (3, 33, <function stripnulls at 0260C8D4>),
'genre': (127, 128, <built-in function ord>),
'year' : (93, 97, <function stripnulls at 0260C8D4>)}
 

(1)MP3FileInfo是类本身,不是任何类的特别实例。
(2)tagDataMap是一个类属性,其在创建任何类实例之前就有效了。
(3)类属性既可以通过直接对类的引用,也可以通过对类的任意实例的引用来使用。
类属性可以作为类级别的常量来使用,但是类属性不是真正的常量,你可以修改它:
 

复制代码 代码示例:
>>> class counter:
count = 0     (1)
def __init__(self):
self.__class__.count += 1(2)
>>> counter
<class __main__.counter at 010EAECC>
>>> counter.count(3)
0
>>> c = counter()
>>> c.count  (4)
1
>>> counter.count
1
>>> d = counter() (5)
>>> d.count
2
>>> c.count
2
>>> counter.count
2
 

(1)count是counter类的一个类属性。
(2)__class__是每个类实例的一个内置属性(也是每个类的),其是一个类的引用,而self是一个类的实例。
(3)因为count是一个类属性,它可以在我们创建任何类实例之前,通过直接对类引用而得到。
(4)创建一个类实例会调用__init__方法,它会给类属性count加1,这样会影响到类自身,不只是新创建的实例。
(5)创建第二个实例将再次增加类属性count,注意类属性是如何被类和所有类实例所共享的。
2、数据属性
 

复制代码 代码示例:
class CType(object):
    a = 1     (1)
class DType(object):
    def __init__(self):
self.a = 1    (2)
 

(1)在类CType中,a就是类本身的属性,即类属性或静态变量。
(2)在类DType中,a就是类实例的属性,即数据属性或成员变量。

五、私有函数
与大多数语言一样,Python也有私有的概念:
(1)私有函数不可以从它们的模块外面被调用;
(2)私有类方法不能够从它们的类外面被调用;
(3)私有属性不能够从它们的类外面被访问。
与大多数语言不同,一个python函数、方法或属性是私有还是公有,完全取决于它的名字。
如果一个Python函数、类方法或属性的名字以两个下划线开始(但不是结束),它是私有的(只能在自己的类中使用),其它所有的都是公有的(任何地方都可使用)。Python没有类方法保护的概念。如果试图调用一个私有方法,Python将会引发一个有误导的异常,宣称该方法不存在。