Python 学习#9 面向对象编程

本章将首先熟悉pyhton中类的定义、创建并操作类实例对象的机制和写法。理解_init_,_new_,_del_的用法和在类生命周期中的调用时机。理解类和类实例对象之间的关系,熟悉类方法和静态方法的机制和写法,熟悉继承和派生的机制和写法。

python中的面向对象编程

面向对象中的基本概念无论在什么编程语言中都是相同的,如果没有接触过建议详细看13.1、13.2节、

类的声明

在python中类的声明与函数声明很相似:

class ClassName(obj):
'class document'
	class suite

类和函数都允许在他们的声明中创建函数、闭包或者内部函数。
最大的不同在于运行函数,而类会创建一个对象。类就像一个python容器类型。当你创建一个类,你就实际创建了一个你自己的数据类型。所以这个类的实例都是相似的,但类之间彼此是有区别的。
声明与定义类是同时进行的,python中并不支持C++中的纯虚函数(只定义不实现)。

类属性

属性就是属于另一对象的数据或函数元素,可以通过句点来访问。访问属性时,它同时也是对象,可以拥有自己的属性。

类的数据属性:类的变量,在类被创建后使用,类似于C++中的静态变量,它不依赖于任何实例,是与类对象绑定的。

方法:类中的方法,作为类定义的一部分定义函数。与C++不同的是,python中没有实例,方法是不能被调用的,方法必须绑定到一个实例中才能被使用。

要查看一个类拥有哪些属性,需要通过内建函数dir(MyClass)或查看_dict_属性。

在python中,对于任何类,都有以下特殊属性:

  • C._name_:类C的名字
  • C._doc_:类C的文档字符串
  • C._bases_:类C的所有父类构成的元组
  • C._dict_:类C的属性
  • C._module_:类C定义所在的模块
  • C._class_:实例C对应的类

实例

初始化类:与其他语言使用new关键字不同,python的方式更简单。
c1=c()

  • _init_():当类被调用,实例化的第一步就是创建实例对象,一旦对象创建了,python检查是否实现了_init_()方法。默认情况下,如果没有定义或覆盖init,则不会进行任何特别的操作。

  • _new_():与init相比,new方法更像是一个真正的构造器。new的调用会在init之前进行,主要是用来实例化不可变对象,例如派生字符串、数字等等。

  • _del_():解构器方法,由于python具有垃圾回收机制(引用计数),这个函数要直到该实例对象所有的引用都被清除掉后才执行。当_del_没有在预期的时候被调用,则说明实例对象由于某些原因,其引用计数不为0,有可能还有对其的引用活着。

同样dir()也可以用于查看实例的属性。

类属性仅是与类相关的数据值,和实例属性不同,类属性和实例无关。类和实例都是名字空间。
简单来说类的属性改变,如果实例没有显式改变属性,则实例属性也改变。实例属性改变,但类的属性不发生改变。

class c:
    foo=100


if __name__ == '__main__':
    c1=c()
    c2=c()
    c.foo=200
    print c1.foo #200
    c1.foo=400
    print c.foo	#200
    print c1.foo	#400

绑定(binding)

类的绑定与方法的调用相关联。方法只有在有所属的类时,才能被调用,被认为是已经绑定到实例。而没有实例的方法就是未绑定的。

self参数:相当于C++this指针。用于在类实例方法中引用方法所绑定的实例。self在每一个方法声明中都是作为第一个参数出现的。

静态方法和类方法

与C++中的静态方法一样,它们仅是类中的函数,不需要通过实例也可以直接调用。
使用函数修饰符@加上staticmethod或classmethod就可以指定方法为静态或类方法。

class c:
    foo=100
    @staticmethod
    def func():
        print 'static func'

组合与派生

一个类被定义之后,目标就是把它当做一个模块来使用,并把这些对象嵌入到代码中,同其他数据类型一起使用。有两种方法可以在代码中利用类:组合和派生。

组合:例如对于地址簿类中有name、address、phone等不同的类,在将这些类的实例都放在地址簿类中时,就产生了一种has-a的关系,即为地址簿中有name、address等实例。

派生:当设计一个相同的类但有一些不同的功能时,派生就是更加好的选择。面向对象编程允许子类继承自父类,甚至多代之间继承。例如在我们需要同时创建客户地址簿和员工地址簿,它们之间会有大量重复的功能,所以可以是它们同时继承自地址簿类。

class parent()::
	'parent class'

class child(parent):
	'child is inherit from parent'

类继承就是描述基类的属性如何‘遗传’给派生类。一个子类可以继承它的基类的任何属性,不管是属性还是方法(_doc_文档字符串并不继承)。
如果父类没有属性,那么继承于父类的子类也没有属性。

如果子类重写了父类中的方法,那么子类将会重写这个方法。
如果想要继续调用父类的方法,则需要在子类重写的方法里显式的调用基类的方法,或者通过super()函数。
_init_方法被重写之后,子类只会调用子类的init函数。

类、实例的内建函数

  • issubclass():判断一个类是否为另一个类的子类或子孙类。
  • isinstance():一个对象是否是另一个给定类的实例对象
  • hasattr():决定一个对象是否有一个特定的属性
  • getattr():获取obj的attr属性。
  • setattr():设置obj的attr属性值为val,替换任何已存在的属性值。
  • delattr():从obj中删除属性attr,类似于del obj.attr。
  • super(type[, obj]):方便找出相应的父类,然后调用相关的属性,比如super(MyClass, self)。
  • vars():返回一个字典,包含对象存储于_dict_中的键值。
  • dir():列举一个模块或对象的所有属性信息。

私有化

默认情况下,属性在python中都是public的,类所在模块和导入了类所在模块的其他模块的代码都可以访问到。这部分会在下一章进行讨论。

super()函数

在使用子类的时候,通常需要重写构造函数(有时候也需要保留父类的构造函数),在需要先使用父类构造函数的情况下,一般有两种解决方法:

# 1 直接调用父类的构造函数
class child:
	def _init_(self):
		parent._init_(self)
		print 'child's init'

# 2 使用super
class child:
	def _init_(self):
		super(child,self)._init_()
		print 'child's init'

下一章将是python基础学习的最后一章,模块的相关学习。

你可能感兴趣的:(Python)