内容简介:什么是面向对象?哈哈,其实此对象非彼对象,程序中的面向对象可不是这样,假设我们要处理学生的成绩表,为了表示一个学生的成绩,面向过程的程序可以用一个dict表示:
什么是面向对象?
哈哈,其实此对象非彼对象,程序中的面向对象可不是这样,假设我们要处理学生的成绩表,为了表示一个学生的成绩,面向过程的程序可以用一个dict表示:
std1 = { 'name': 'Michael', 'score': 98 } std2 = { 'name': 'Bob', 'score': 81 }
而处理学生成绩可以通过函数实现,比如打印学生的成绩:
def print_score(std): print('%s: %s' % (std['name'], std['score']))
如果采用面向对象的程序设计思想,我们首选思考的不是程序的执行流程,而是Student这种数据类型应该被视为一个对象,这个对象拥有name和score这两个属性(Property)。如果要打印一个学生的成绩,首先必须创建出这个学生对应的对象,然后,给对象发一个print_score消息,让对象自己把自己的数据打印出来。
class Student(object): def __init__(self,name,score): self.name = name self.score = score def print_score(self): print('%s: %s' %(self.name,self.score))
给对象发消息实际上就是调用对象对应的关联函数,我们称之为对象的方法(Method)。面向对象的程序写出来就像这样:
bart = Student('Bart Simpson',59) bart.print_score()
面向对象的设计思想是从自然界中来的,因为在自然界中,类(Class)和实例(Instance)的概念是很自然的。Class是一种抽象概念,比如我们定义的Class——Student,是指学生这个概念,而实例(Instance)则是一个个具体的Student,比如,Bart Simpson和Lisa Simpson是两个具体的Student。
类和实例
在 Python 中,定义类是通过 class 关键字:
class Student(object): pass
class后面紧接着是类名,即Student,类名通常是大写开头的单词,紧接着是(object),表示该类是从哪个类继承下来的,通常,如果没有合适的继承类,就使用object类,这是所有类最终都会继承的类。
class Student(object): def __init__(self, name, score): self.name = name self.score = score
init方法的第一个参数永远是self,表示创建的实例本身,因此,在 init 方法内部,就可以把各种属性绑定到self,因为self就指向创建的实例本身。
有了 init 方法,在创建实例的时候,就不能传入空的参数了,必须传入与 init 方法匹配的参数,但self不需要传,Python解释器自己会把实例变量传进去:
和普通的函数相比,在类中定义的函数只有一点不同,就是第一个参数永远是实例变量self,并且,调用时,不用传递该参数。除此之外,类的方法和普通函数没有什么区别,所以,你仍然可以用默认参数、可变参数、关键字参数和命名关键字参数。
数据封装
面向对象的数据封装是指我们只需要调用其类的方法,而不需要知道其具体的内部实现。
class Student(object): def __init__(self,name,score): self.name = name self.score = score def print_score(self): print('%s: %s' %(self.name,self.score)) def get_grade(self): if self.score >= 90: return 'A' elif self.score >=60: return 'B' else: return 'C' bart = Student('Bart Simpson',59) print(bart.get_grade())
访问限制
如果要让内部属性不被外部访问,可以把属性的名称前加上两个下划线 ,在Python中,实例的变量名如果以 开头,就变成了一个私有变量(private),只有内部可以访问,外部不能访问,所以,我们把Student类改一改:
def __init__(self,name,score): self.__name = name self.__score = score def print_score(self): print('%s: %s' %(self.name,self.score))
改完后,对于外部代码来说,没什么变动,但是已经无法从外部访问实例变量. name和实例变量. score了,如果需要访问需要增加2个方法
class Student(object): def __init__(self,name,score): self.__name = name self.__score = score def get_name(self): return self.__name def get_score(self): return self.__score def print_score(self): print('%s: %s' %(self.name,self.score)) def get_grade(self): if self.score >= 90: return 'A' elif self.score >=60: return 'B' else: return 'C' bart = Student('Bart Simpson',59) print(bart.get_name())
如果要允许修改 score 呢
class Student(object): def __init__(self,name,score): self.__name = name self.__score = score def get_name(self): return self.__name def get_score(self): return self.__score def print_score(self): print('%s: %s' %(self.name,self.score)) def set_score(self,score): self.__score = score def get_grade(self): if self.score >= 90: return 'A' elif self.score >=60: return 'B' else: return 'C' bart = Student('Bart Simpson',59) print(bart.get_name()) bart.set_score(60) print(bart.get_score())
则输出
你也许会问,原先那种直接通过bart.score = 99也可以修改啊,为什么要定义一个方法大费周折?因为在方法中,可以对参数做检查,避免传入无效的参数:
class Student(object): …… def set_score(self,score): if 0<=score<=100: self.__score = score else: raise ValueError('bad score') bart = Student('Bart Simpson',59) print(bart.get_name()) bart.set_score(101) print(bart.get_score())
需要注意的是,在Python中,变量名类似 xxx 的,也就是以双下划线开头,并且以双下划线结尾的,是特殊变量,特殊变量是可以直接访问的,不是private变量,所以,不能用 name 、 score 这样的变量名。
有些时候,你会看到以一个下划线开头的实例变量名,比如_name,这样的实例变量外部是可以访问的,但是,按照约定俗成的规定,当你看到这样的变量时,意思就是,“虽然我可以被访问,但是,请把我视为私有变量,不要随意访问”。
双下划线开头的实例变量是不是一定不能从外部访问呢?其实也不是。不能直接访问 name是因为Python解释器对外把 name变量改成了_Student__name,所以,仍然可以通过_Student__name来访问__name变量:
>>> bart._Student__name 'Bart Simpson'
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- 面向Python,面向对象(基础)
- 面向Python,面向对象(基础3)
- <<深入PHP面向对象、模式与实践>>读书笔记:面向对象设计和过程式编程
- 《JavaScript面向对象精要》之六:对象模式
- 《JavaScript面向对象精要》之三:理解对象
- 面向对象的程序设计之理解对象
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Effective Ruby:改善Ruby程序的48条建议
Peter J. Jones / 杨政权、秦五一、孟樊超 / 机械工业出版社 / 2016-1 / 49
如果你是经验丰富的Rub程序员,本书能帮助你发挥Ruby的全部力量来编写更稳健、高效、可维护和易执行的代码。Peter J.Jones凭借其近十年的Ruby开发经验,总结出48条Ruby的最佳实践、专家建议和捷径,并辅以可执行的代码实例。 Jones在Ruby开发的每个主要领域都给出了实用的建议,从模块、内存到元编程。他对鲜为人知的Ruby方言、怪癖、误区和强力影响代码行为与性能的复杂性的揭......一起来看看 《Effective Ruby:改善Ruby程序的48条建议》 这本书的介绍吧!