在我学习python之前一直认为python是脚本型语言,不能用面相对象的方法进行编程,当我学习了python之后我发现我错了,python不但支持面相对象而且使用的人还挺多的。我从接触编程开始就是学习的Java语言,所以面相对象编程的思想在我的脑海里根深蒂固,让我一下从面向对象编程转换到面向过程编程还有一些不适应呢,所以我就来总结一下python面向对象编程的方法和过程。我将按照面向对象的构成要素来分析,依次为类和实例、属性、方法、封装、继承、多态,如果有什么问题还请大家积极指出,我所用的版本为python2.7!
一、类和实例
面向对象是一种编程思想,它将现实生活中的事物映射到程序世界中,所以我们可以使用现实生活中的思想来考虑编程问题,这使我们编程变得更加容易,毕竟我们都已经在现实生活中生活了几十年了嘛。
我们来看一下python中类的基本形式。
class Movie(object):
def __init__(self,name,length):
self.name = name
self.length = length
def print_name(self):
print '电影的名称是:%s' % (self.name,)
class Movie(object): 是固定写法,class表明正在声明的是一个类,Movie是类名,(object)表示继承自那些父类,就行java一样,所有的类都是继承自object类的,所以如果你写的不继承自其他的类就将其写成继承自object,当继承自object,括号连同括号里的object都可以省略写成:class Movie:
第一个方法__init__
是构造方法,构造方法的第一个参数永远是self,表示这个类的对象本身,真正构造对象时,self这个参数不用写,python编译器会自己加上去,构造方法的作用就是对self对象进行赋值,如上面的将电影的名字和长度赋给self。
对于上面的Movie类我们可以用下面的代码来调用它:
import OOP
movie = OOP.Movie('大圣归来',90)
movie.print_name()
输出的结果是:电影的名称是:大圣归来
如果不需要给对象传递什么参数,那么构造方法也是可以省略的,例如:
class Movie(object):
def print_info(self):
print '这是一个电影的类'
这样在构造对象时就不用传递任何的参数例如:
import OOP
movie = OOP.Movie()
movie.print_info()
输出的结果为:这是一个电影的类
二、属性
实例属性是归对象所有,每个对象都有自己的一套属性,不同对象之间的实例属性不会相互干扰。在python中,在__init__
方法中声明的属性就是实例属性。当然,你也可以在类中的任何一个方法中,使用self.var=something 的方式声明实例属性,但是我个人觉得这样会使程序非常混乱,容易出错,下面用这个例子来看一下:
OPP
# -*- coding: utf-8 -*-
class Movie(object):
def __init__(self,name,length):
self.name = name
self.length = length
def print_name(self):
self.aaa = '123'
print '电影的名称是:%s' % (self.name,)
OOPTest
# -*- coding: utf-8 -*-
import OOP
movie1 = OOP.Movie('大圣归来',90)
movie2 = OOP.Movie('美人鱼',120)
print movie1.name
print movie2.name
movie1.print_name()
print movie1.aaa #只有在调用了print_name方法之后,aa才会被定义
movie1.name='风声'
print movie1.name
print movie2.name #movie1的改变并未影响到movie2
输出结果:
大圣归来
美人鱼
电影的名称是:大圣归来
123
风声
美人鱼
类属性是归这个类所有的,所有的实例都共享着一个变量,如果一个实例改变了类属性的值,那么所有的实例都会受到影响。类属性的声明独立于所有方法,声明方法如下:
OOP
# -*- coding: utf-8 -*-
class Movie(object):
count = 1 #类属性
def __init__(self,name,length):
self.name = name
self.length = length
def print_name(self):
self.aaa = '123'
print '电影的名称是:%s' % (self.name,)
上面的count就是一个类属性,类属性就类似于java中static变量,可以使用类名.count的方式进行调用,当然也可以通过实例.count的方式进行调用,类属性一般用于计数对象,或者不同实例之间共享变量,看下面的例子来理解一下类变量。
# -*- coding: utf-8 -*-
import OOP
movie1 = OOP.Movie('大圣归来',90)
movie2 = OOP.Movie('美人鱼',120)
print OOP.Movie.count #1 通过类名.count的方式进行调用
print movie2.count #1 通过实例.count的方式进行调用
movie1.count = 3
print OOP.Movie.count #1
print movie1.count #3
print movie2.count #1
OOP.Movie.count=3
print OOP.Movie.count #3
print movie1.count #3
print movie2.count #3
注释中是输出的结果,我们可以看到如果使用类名.count的方式进行调用,那么所有的实例中的值都将改变,但是如果通过实例.count的方式进行调用,那么只有相应的实例的值发生了改变。
三、方法
Python的方法并不像C#,Java这些编译性语言那样严格的区分静态方法和实例方法。也就是说Python的静态方法,类方法和实例方法只是在调用上有区别,类型和实例都可以调用。
实例方法可以被类实例调用,通过实例.方法的形式进行调用,这个我们都不陌生了,上面例子中的print_name方法就是实例方法,使用实例方法是传入的参数方法声明时的参数少一个,因为第一个参数self是不用提供的。除此之外实例方法还可以被类调用,形式是类名.方法名(self),必须手动添加self变量,也就是类的实例。
类方法可以被类和类实例调用,但是类方法无法访问实例变量,只能方法访问类变量,声明时在方法前面加上@classmethod,并且方法中的第一个参数是cls而不是self,和实例方法一样,使用时第一个参数不用传递,python的编译器会自动的加上。类方法更像java中的static方法。
静态方法可以被类和类实例调用,无法访问实例变量和类变量,只能方法传入进来的参数,声明时在方法前面加上@staticmethod,静态方法没有默认的参数,静态方法有点像函数工具库的作用。
OOP
# -*- coding: utf-8 -*-
class Movie(object):
count = 1
def __init__(self,name,length):
self.name = name
self.length = length
#实例方法
def print_name(self):
self.aaa = '123'
print '电影的名称是:%s' % (self.name,)
#类方法
@classmethod
def print_len(cls):
print '电影的长度是:%d' % (cls.count,)
#静态方法
@staticmethod
def print_info(str):
print '传入的信息是:%s' % (str,)
OOPTest
# -*- coding: utf-8 -*-
import OOP
movie1 = OOP.Movie('大圣归来',90)
movie1.print_name() #通过实例调用实例方法
OOP.Movie.print_name(movie1) #如果通过类调用实例方法,必须手动传入实例
OOP.Movie.print_len() #通过类调用类方法
movie1.print_len() #通过实例调用类方法
OOP.Movie.print_info('哈哈') #通过类调用静态方法
movie1.print_info('哈哈') #通过实例调用静态方法
剩下的还有很多,一次写不完,下一篇在讨论封装、继承和多态,谢谢大家的支持!