Python之面向对象 面向过程的程序设计把计算机程序视为一系列的命令集合,即一组函数的顺序执行。为了简化程序设计,面向过程把函数继续切分为子函数,即把大块函数通过切割成小块函数来降低系统的复杂度。
面向对象编程—Object Oriented Programming,简称OOP,是一种程序设计思想。OOP把对象作为程序的基本单元,一个对象包含了数据和操作数据的函数。
举个例子理解一下:
假设我们要处理学生的成绩表,为了表示一个学生的成绩,面向过程的程序可以用一个dict表示,然后通过定义一个函数去查询。如下:
我们使用std1和std2来分别表示张三和李四的成绩,然后使用print_score函数来打印出这两位同学的成绩。
上面那种思路是典型的面向过程的思路,如果我们使用面向对象的设计思想,我们首先考虑的应该是学生这种数据类型,他包含两种属性,一种是name,一种的score,如果要打印这两个学生的成绩,需要创建两个对象,再利用对象的print_score消息,让对象自己将自己打印出来,类的定义如下:
上面的定义中有以下情况需要注意,
1.class后面紧接着是类名,即Student,类名通常是大写开头的单词,紧接着是(object),表示该类是从哪个类继承下来的,通常,如果没有合适的继承类,就使用object类,这是所有类最终都会继承的类,
2.特别需要叮嘱的是:init前后分别有两个下划线。
3.__init__方法的第一个参数永远是self,表示创建的实例本身,因此,在__init__方法内部,就可以把各种属性绑定到self,因为self就指向创建的实例本身。
4.本例中的Student在定义的时候,需要给函数传递两个参数,一个是name属性,一个是score属性。
5.普通的函数相比,在类中定义的函数只有一点不同,就是第一个参数永远是实例变量self,并且,调用时,不用传递该参数。除此之外,类的方法和普通函数没有什么区别
我们初始化对象的时候,就需要这么做:
这里需要注意:类(Class)是一种抽象概念,比如我们定义的Class——Student,是指学生这个概念,而实例(Instance)则是一个个具体的Student,比如,zhang和li是两个具体的Student。实例是根据类创建出来的一个个具体的“对象”,每个对象都拥有相同的方法,但各自的数据可能不同。
数据的封装性
面向对象编程的一个重要特点就是数据封装。既然Student实例本身就拥有这些数据,要访问这些数据,就没有必要从外面的函数去访问,可以直接在Student类的内部定义访问数据的函数,这样,就把“数据”给封装起来了。这些封装数据的函数是和Student类本身是关联起来的,我们称之为类的方法。
要定义一个方法,除了第一个参数是self外,其他和普通函数一样。要调用一个方法,只需要在实例变量上直接调用,除了self不用传递,其他参数正常传入。
我们从外部看Student类,就只需要知道,创建实例需要给出name和score,而如何打印,都是在Student类的内部定义的,这些数据和逻辑被“封装”起来了,调用很容易,但却不用知道内部实现的细节。
举个例子:
在上面的例子中,我们首先定义了一个Person函数,里面有两个属性,一个是country(已经给了一个默认值china),另外一个是name,此时我们添加一个方法run,我们使用classmethod装饰器将这个方法设置为一个类方法,然后将它放在类的方法run中,最后通过类名去调用这个方法,结果就是‘China 在奔跑’。
对于类的使用者来说,它们甚至看不到为什么会输出china这个字符串,因为类对使用者来讲是完全封闭的,这就是类的封装性。