那些年被我坑过的Python——玄而又玄(第六章 面向对象编程基础)
面向对象编程:
面向对象顾名思义,就是把组织代码的粒度从函数级别抽象到对象级别,对象是通过类来生成的,类可以想象为模板或进本框架而对象是在原有模板或框架的基础上增加详细信息的实体,类,有分类、聚类的含义,也就是说把世间万物进行区分,有相同特点的找到这些相同点构成一个模板,以备今后使用。实例化就是从类生成对象的过程。
类的三大特性:
封装、继承和多态
封装:编程的根本结果是实现了数据的组织、传递、转换与呈现,面向对象编程中,对数据的存放和传递进行了抽象,数据不再以单点存在,而是保存在对象中,传递的媒介就成了对象,这样是把一组相互关联的数据放在一起,并构建起内部的变换关系,在使用过程中,程序员不必过多考虑数据是什么,更多的是考虑对象有什么属性和方法。
继承:除了类别之间的关系,还有类别之内的细分,继承的本意就是把核心的共同点保留下来,不用再重新编写,实现了类级的重用
多态:实现了对类中接口的重用,简单来说就是对外调用的接口不变,但是接口内在的逻辑可以不同。
定义一个类可以采用下面的方式来定义:
class className(object):
foo
bar
注意类名后面有个冒号,在block块里面就可以定义属性和方法了。当一个类定义完之后,就产生了一个类对象。类对象支持两种操作:引用和实例 化。引用操作是通过类对象去调用类中的属性或者方法,而实例化是产生出一个类对象的实例,称作实例对象。比如定义了一个people类:
class people(object):
name = 'jack' #定义了一个属性
#定义了一个方法
def printName(self):
print people.name
people类定义完成之后就产生了一个全局的类对象,可以通过类对象来访问类中的属性和方法了。当通过people.name(至于为什么可 以直接这样访问属性后面再解释,这里只要理解类对象这个概念就行了)来访问时,people.name中的people称为类对象,这点和C++中的有所 不同。当然还可以进行实例化操作,p=people( ),这样就产生了一个people的实例对象,此时也可以通过实例对象p来访问属性或者方法了(p.name).
理解了类、类对象和实例对象的区别之后,我们来了解一下Python中属性、方法和函数的区别。
在上面代码中注释的很清楚了,name是一个属性,printName( )是一个方法,与某个对象进行绑定的函数称作为方法。一般在类里面定义的函数与类对象或者实例对象绑定了,所以称作为方法;而在类外定义的函数一般没有同对象进行绑定,就称为函数。
二.属性
在类中我们可以定义一些属性,比如:
class people():
name = 'jack'
age = 12
p = people()
print p.name,p.age
私有属性
定义了一个people类,里面定义了name和age属性,默认值分别为'jack'和12。在定义了类之后,就可以用来产生实例化对象了, 这句p = people( )实例化了一个对象p,然后就可以通过p来读取属性了。这里的name和age都是公有的,可以直接在类外通过对象名访问,如果想定义成私有的,则需在前 面加2个下划线 ' __'。
class people:
__name = 'jack'
__age = 12
p = people()
print p.__name,p.__age
这段程序运行会报错:
提示找不到该属性,因为私有属性是不能够在类外通过对象名来进行访问的。在Python中没有像C++中public和private这些关键 字来区别公有属性和私有属性,它是以属性命名方式来区分,如果在属性名前面加了2个下划线'__',则表明该属性是私有属性,否则为公有属性(方法也是一 样,方法名前面加了2个下划线的话表示该方法是私有的,否则为公有的)。
三.方法和私有方法
在类中可以根据需要定义一些方法,定义方法采用def关键字,在类中定义的方法至少会有一个参数,,一般以名为'self'的变量作为该参数(用其他名称也可以),而且需要作为第一个参数。下面看个例子:
class people:
__name = 'jack'
__age = 12
def getName(self):
return self.__name
def getAge(self):
return self.__age
p = people()
print p.getName(),p.getAge()
如果对self不好理解的话,可以把它当做C++中类里面的this指针一样理解,就是对象自身的意思,在用某个对象调用该方法时,就将该对象作为第一个参数传递给self。
四.类中内置的方法
在Python中有一些内置的方法,这些方法命名都有比较特殊的地方(其方法名以2个下划线开始然后以2个下划线结束)。类中最常用的就是构造方法和析构方法。
构造方法__init__(self,....)在生成对象时调用,可以用来进行一些初始化操作,不需要显示去调用,系统会默认去执行。构造方法支持重载,如果用户自己没有重新定义构造方法,系统就自动执行默认的构造方法。
析构方法__del__(self)在释放对象时调用,支持重载,可以在里面进行一些释放资源的操作,不需要显示调用。
还有其他的一些内置方法:
比如 __cmp__( ), __len( )__等,具体的用法可以参考这篇博文:
http://www.cnblogs.com/simayixin/archive/2011/05/04/2036295.html
五.类属性、实例属性、类方法
在了解了类基本的东西之后,下面看一下python中这几个概念的区别。
先来谈一下类属性和实例属性
在前面的例子中我们接触到的就是类属性,顾名思义,类属性就是类对象所拥有的属性,它被所有类对象的实例对象所共有,在内存中只存在一个副本,这个和C++中类的静态成员变量有点类似。对于公有的类属性,在类外可以通过类对象和实例对象访问。
class people:
name = 'jack' #公有的类属性
__age = 12 #私有的类属性
p = people()
print p.name #正确
print people.name #正确
print p.__age #错误,不能在类外通过实例对象访问私有的类属性
print people.__age #错误,不能在类外通过类对象访问私有的类属性
实例属性是不需要在类中显示定义的,比如:
class people:
name = 'jack'
p = people()
p.age =12
print p.name #正确
print p.age #正确
print people.name #正确
print people.age #错误
在类外对类对象people进行实例化之后,产生了一个实例对象p,然后p.age = 12这句给p添加了一个实例属性age,赋值为12。这个实例属性是实例对象p所特有的,注意,类对象people并不拥有它(所以不能通过类对象来访问 这个age属性)。当然还可以在实例化对象的时候给age赋值。
class people:
name = 'jack'
#__init__()是内置的构造方法,在实例化对象时自动调用
def __init__(self,age):
self.age = age
p = people(12)
print p.name #正确
print p.age #正确
print people.name #正确
print people.age #错误
如果需要在类外修改类属性,必须通过类对象去引用然后进行修改。如果通过实例对象去引用,会产生一个同名的实例属性,这种方式修改的是实例属 性,不会影响到类属性,并且之后如果通过实例对象去引用该名称的属性,实例属性会强制屏蔽掉类属性,即引用的是实例属性,除非删除了该实例属性。
class people():
country = 'china'
print people.country
p = people()
print p.country
p.country = 'japan'
print p.country #实例属性会屏蔽掉同名的类属性
print people.country
del p.country #删除实例属性
print p.country