一、面向过程和面向对象的不同之处
例如:要处理学生的成绩表
面向过程:
std1={'name':'Micheal','score':'98'} std2={'name':'Bob','score':81}
现在打印学生的成绩:
def print_score(std): print('%s,%s'%(std['name'],std['score']))
面向对象:
class Student(): def __init__(self,name,score): self.name=name self.score=score def print_score(self): print('%s,%s'%(self.name,self.score))
二、类和实例
类是一种抽象的模板,比如Student类。实例是根据类创建出来的一个个具体的对象,每个对象都拥有相同的方法,但各自的数据可能不同。
例如:
创建一个类:
class Student(): pass
现在为这个类创建一个具体的对象(实例):
>>> bart=Student()
当创建了这个实例之后,可以给实例变量绑定一个属性:
>>> bart.name='Jim'
因为类本身就起到了模板的作用,所以在创建实例的时候,可以把一些必须的属性填写进去,用__init__方法:
class Student(): def __init__(self,name,score): self.name=name self.score=score
注意:__init__方法的第一个参数永远是self,表示创建的实例本身,因此在__init__方法内部,就可以把各种属性绑定到self,因为self指向创建的实例本身。
有了__init__方法之后,在创建实例的时候,就不能传入空的参数了,必须传入与__init__方法相匹配的参数,self不需要传
>>> bart=Sudent('Jim',59)
与普通的函数相比,在类中定义的函数只有一点不同,就是第一个参数永远是实例变量self,并且在调用时,不用传递该参数,除此之外,类的方法和普通的函数没
任何区别
三、数据封装
面向对象的一个重要特点就是数据封装,在上面创建的Student类中,每个实例都拥有各自的name属性和score属性,可以通过函数来访问这些数据:
def print_score(self): print('%s,%s'%(std.name,std.score)) print_score(bart)
既然Student实例本身就拥有这些数据,要访问这些数据,就没有必要从外面的函数去访问,可以直接在函数的内部定义访问函数,这就是类的封装
class Student(): def __init__(self,name,score): self.name=name self.score=score def print_score(self): print('%s,%s'%(self.name,self.score))
现在调用封装之后的方法:
bart.print_score()
四、访问限制
在类的内部,可以有属性和方法,而外部代码可以直接调用实例变量的方法来操作数据,这样就隐藏了内部的复杂逻辑,但是在上面的类中,外部的代码可以自由的修改一个实例的name、score属性:
>>>bart=Studnt{'Jim',99}
>>>bart.score
99
>>>bart.score=59
>>>bart.score
59
所以,如果要让内部属性不被外部访问,可以在属性的前面加上两个下划线__,将其变为私有变量,只有内部可以访问,外部不能访问
class Student(): def __init__(self,name,score): self.__name=name self.__score=score def print_score(self): print('%s,%s'%(self.name,self.score))
现在从外部访问:
>>>bart=Studnt{'Jim',99}
>>>bart.__name
报错
上面的这种方法就确保了外部代码不能随意修改对象内部的状态,但是如果外部代码想要获取name和score属性,可以给Student类增加get_name和get_score这样的类:
class Student():
def __init__(self,name,score):
self.__name=name
self.__score=score
def print_score(self):
print('%s,%s'%(self.name,self.score))
def get_name(self):
return self._name
def get_score(self):
return self._score
如果又要允许外部代码修改score,可以再给Student类增加set_score类:
class Student():
def __init__(self,name,score):
self.__name=name
self.__score=score
def print_score(self):
print('%s,%s'%(self.name,self.score))
def get_name(self):
return self._name
def get_score(self):
return self._score
def set_score(self,score):
if 0<=score<=100:
self.__score=score
else:
raise ValueError('bad score')
注意:在python,变量名是以双下划线开头,以双下划线结尾的,是特殊变量,特殊变量可以直接访问。若是以一个下划线开头的变量(_name),这样的变量外部是可以访问的,但按照约定俗成的规定,它的意思是:“虽然我可以被直接访问,但是请把我视为私有变量量,不要随意访问”