Python不仅支持面向过程编程,同时也支持面向对象编程。面向过程就是分析解决问题所需的步骤,然后用函数把这些步骤逐一实现,使用的时候再一个个调用函数就可以。面向对象则是把解决的问题按照一定规则划分为多个独立的对象,然后通过调用对象的方法来解决问题。在编写小程序(少于500行代码)时,使用面向过程编程基本上不会有任何问题。但对于中等和大型项目来说,面向对象将给代码的编写和维护带来很多优势。本文主要介绍Python中面向对象的基本概念。
面向对象基本概念
面向对象的特点主要可以概括为封装性、继承性、多态性。
(1)封装性
封装是面向对象的核心思想,将对象的属性和行为封装起来,不需要让外界知道具体实现细节,这就是封装的思想。比如,用户使用电脑,只需要会敲键盘就可以,无须知道电脑内部是如何工作的。
(2)继承性
继承性主要描述的是类与类之间的关系,通过继承,可以在无须重新编写原有类的情况下,对原有类的功能进行扩展。
(3)多态性
多态性指的是在程序中允许重名现象,它指在一个类中定义的属性和方法被其他类继承后,它们可以具有不同的数据类型或表现出不同的行为,这使得同一个属性和方法在不同的类中具有不同的语义。
面向对象的思想需要通过大量的实践去学习和理解,才能将面向对象真正理解清楚。后面会通过一些例子介绍其使用方法。
类和对象基本概念
面向对象的思想中提出了两个概念,即类和对象。类是对某一类事物的抽象描述,是一种抽象的数据类型,一种模板。而对象用于表示现实中该类事物的个体,也就是具体化了类的描述。它们的关系是,对象是类的具体实例,类是对象的模板。对象根据类创建,一个类可以创建多个对象。比如我定义了一个学生类,那么通过类创建出来的小明、小王就叫对象。
类的定义
在Python中使用class关键字定义一个类,类的主体由属性(变量)和方法(函数)组成。通过定义一个学生类来学习下Python类的定义方法,如下:
#-*- coding:utf-8 -*-
#类的创建
class Student(object):
count = 0 #类属性
def __init__(self, name, age): #__init__为类的构造函数
self.name = name #实例属性
self.age = age #实例属性
def output(self): #实例方法
print self.name
print self.age
上述例子中Student是类名,__init__()函数是构造函数,count、name、age是类中定义的属性,output(self)是类中定义的方法。
对象的创建和使用
定义完Student类之后,就可以创建对象。当一个对象被创建后,包含3个方面的特性:对象的句柄、属性和方法。对象的句柄用于区分不同的对象,当对象被创建后,该对象会获取一块存储空间,存储空间的地址即为对象的标识。Python创建对象的方法是通过类名加圆括号的方式。实例化上述定义的Student类,格式如下:
#-*- coding:utf-8 -*-
#类的创建
class Student(object):
count = 0 #类属性
def __init__(self, name, age): #__init__为类的构造函数
self.name = name #实例属性
self.age = age #实例属性
def output(self): #实例方法
print self.name
print self.age
if __name__ == '__main__':
stu1 = Student('Zhangsan',18) #使用Student类对象stu1
print "stu1.name = %s" % (stu1.name,) # 利用对象stu1获取对象属性name。输出stu1.name = Zhangsan
print "stu1.age = %d" % (stu1.age,) # 利用对象stu1获取对象属性age。输出stu1.age = 18
stu1.output() # 利用对象stu1调用output方法。
实例化对象之后,就可以通过对象直接调用对象的属性和方法。但是注意的是对象调用方法时,不需要给参数self赋值,self参数用于表示指向实例对象本身。
到这里,已经学会了类的定义和对象创建方法和使用了。上述的例子中仅介绍了类的基本实例属性和实例方法的定义,实际上实例变量还区分私有属性和公有属性,还有类变量等概念。同时类中的方法还包括静态方法、类方法。
类属性和实例属性
类的属性是对数据的封装,类中定义的属性包括实例属性、类属性两种。上述例子中count变量属于类属性,name、age属于实例属性。类变量可以在该类的所有实例中被共享。二者在定义和使用上区别主要如下:
(1)类属性定义在类中但是在方法外的变量,实例属性通常定义在构造函数__init__内。如下
class Student(object):
count = 0 #类属性
def __init__(self, name, age): #__init__为类的构造函数
self.name = name #实例属性
self.age = age #实例属性
(2)类属性属于类本身,可以通过类名进行访问/修改。
#-*- coding:utf-8 -*-
#类的创建
class Student(object):
count = 0 #类属性
if __name__ == '__main__':
Student.count = 100
print "Student.count = %d" % (Student.count,) #输出Student.count = 100
(3)类属性也可以被类的所有实例访问/修改。
#-*- coding:utf-8 -*-
#类的创建
class Student(object):
count = 0 #类属性
def __init__(self, name, age): #__init__为类的构造函数
self.name = name #实例属性
self.age = age #实例属性
if __name__ == '__main__':
stu1 = Student('Zhangsan',18) #使用Student类对象stu1
stu1.count = 100
print "stu1.count = %s" % (stu1.count,) # 利用对象stu1获取类属性count值。输出stu1.count = 100
(4)实例属性只能通过实例访问。
#-*- coding:utf-8 -*-
#类的创建
class Student(object):
count = 0 #类属性
def __init__(self, name, age): #__init__为类的构造函数
self.name = name #实例属性
self.age = age #实例属性
if __name__ == '__main__':
stu1 = Student('Zhangsan',18) #使用Student类对象stu1
print "stu1.age = %d" % (stu1.age,) # 利用对象stu1获取实例属性age值。输出stu1.age = 18
#print "Student.age = %d" % (Student.age,) # 报错,不能通过类直接访问实例属性
(5)当类属性与实例属性名称相同时,一个实例访问这个属性时实例属性会覆盖类属性,但类访问时不会。
#-*- coding:utf-8 -*-
#类的创建
class Student(object):
name = "Xiaoming" #类属性
def __init__(self, name, age): #__init__为类的构造函数
self.name = name #实例属性
self.age = age #实例属性
if __name__ == '__main__':
stu1 = Student('Zhangsan',18) #使用Student类对象stu1
print "stu1.name = %s" % (stu1.name,) # 输出Zhangsan
print "Student.name = %s" % (Student.name,) # 输出Xiaoming
实例方法、类方法和静态方法
自定义的一个类中,可能出现三种方法,实例方法、静态方法和类方法,下面来看下三种方法的定义和使用区别。
(1)实例方法
实例方法的第一个参数必须是"self",实例方法只能通过对象调用。
#-*- coding:utf-8 -*-
#类的创建
class Student(object):
count = 0 #类属性
def __init__(self, name, age): #__init__为类的构造函数
self.name = name #实例属性
self.age = age #实例属性
def output(self): #实例方法
print self.name, self.age
if __name__ == '__main__':
stu1 = Student('Zhangsan',18) #使用Student类对象stu1
stu1.output() # 利用对象stu1调用output方法。
其中output()方法即为实例方法,必须带一个参数self,调用时不必给该参数赋值。
(2)类方法
类方法是将类本身作为操作对象的方法。类方法可以使用函数classmethod()或@classmethod修饰器定义。与实例方法不同的是,把类作为第一个参数(cls)传递。类方法可以通过类名调用,也可以通过对象调用。代码如下:
#-*- coding:utf-8 -*-
#类的创建
class Student(object):
count = 0 #类属性
def __init__(self, name, age): #__init__为类的构造函数
self.name = name #实例属性
self.age = age #实例属性
@classmethod #方法一,定义类方法,调用类变量,getPrice中不带self参数
def getCount(cls):
print cls.count
def getCount2(cls):
print cls.count
tran_getCount2 = classmethod(getCount2) ##方法二,定义类方法,调用类变量
if __name__ == '__main__':
Student.getCount() #使用类名直接调用类方法
stu1 = Student('Zhangsan',18) #使用Student类对象stu1
stu1.getCount() # 利用对象stu1调用类方法。
可见,类方法的使用和静态方法十分相似。如果某个方法需要被其他实例共享,同时又需要使用当前实例的属性,则定义为类方法。
(3)静态方法
静态方法使用函数classmethod()或@classmethod修饰器定义。定义和使用方式如下:
#-*- coding:utf-8 -*-
#类的创建
class Student(object):
count = 0 #类属性
def __init__(self, name, age): #__init__为类的构造函数
self.name = name #实例属性
self.age = age #实例属性
@staticmethod #方法一,定义类方法,调用类变量,getPrice中不带self参数
def getCount():
print Student.count
def getCount2():
print Student.count
tran_getCount2 = staticmethod(getCount2) ##方法二,定义类方法,调用类变量
if __name__ == '__main__':
Student.getCount() #使用类名直接调用静态方法
stu1 = Student('Zhangsan',18) #使用Student类对象stu1
stu1.getCount() # 利用对象stu1调用静态方法。
这三种方法的主要区别在于参数,实例方法被绑定到一个实例,只能通过实例进行调用;但是对于静态方法和类方法,可以通过类名和对象两种方式进行调用。
小结
本文介绍了Python面向对象基本概念、类的定义、对象的创建和使用、类的属性和方法。了解这些基本概念,有助于后续的实际开发。