一、面向对象编程
面向对象编程--Object Oriented Programming ,简称为OOP,是一种程序设计思想。OOP把对象作为程序的基本单元,一个对象包含了数据和操作数据的函数。
在Python中,所有数据类型都可以视为对象,当然也可以自定义对象,自定义的对象数据类型就是面向对象中的类的概念。
数据封装、继承、和多态是面向对象的三大特点,我们下面来介绍类的定义。
二、类和类的实例
面向对象最重要的概念就是类( Class ) 和实例( Instance ),我们必须牢记类是抽象的模板。
class 类名(父类): pass如上面的代码结构就是一个类的定义。我们定义一个继承余Object类的Student类
class Student(object): def __init__(self, name, age, score): self.name = name self.age = age self.score = score def get_level(self): if 90<self.score<=100: return "%s,%s,A" %(self.name,self.age) elif 80<self.score<=90: return "%s,%s,B" %(self.name,self.age) else: return "%s,%s,C" %(self.name,self.age)
由于类可以起到模板的作用,因此可以在类的实例化的过程时,把一些我们认为必须绑定的属性强制填写进去,通过定义一个特殊的__init__方法,在创建时就可以将我们的name,age等等参数传入。
我们可以看到在一个类里面有例如name,age,score等变量的定义,也有相类似函数get_level()的定义,因此在面向对象编程时,我们将类里面的变量称为类的属性,将类里面的函数称为类的方法。
对象是类的实例化过程,对象拥有类的非私有属性与方法。
st1 = Student('XIAOMI',18,90) #传入name,age,score三个参数
上面代码就是类的实例化过程,st1就是一个对象,我们的st1可以是调用get_level方法
print(st1.get_level())
输出:
XIAOMI,18,B
___init__方法,也被我们称作类的构造函数,在类定义时自动被执行,因此我们通常在创建实例时,会将我们的参数传入。注意到,__init__方法的第一个参数永远是self,表示创建的实例本身,因此在__init__方法内部,就可以把各种属性绑定到self,因为self就指向创建的实例本身,self不需要我们传入,Python解释器自己会把实例变量传进去。
三、数据的封装
面向对象编程的一个重要特点就是数据的封装。在上面的Student类中,每个实例就拥有各自的name和age等数据,们可以通过函数来访问这些数据,但是既然 Student 实例本身就拥有这些数据,要访问这些数据,就没有必要从外面的函数去访问,可以直接在 Student 类的内部定义访问数据的函数,这样,就把“数据”给封装起
来了。这些封装数据的函数是和 Student 类本身是关联起来的,我们称之为类的方法
四、类的访问限制
在类的内部,可以有属性和方法,二外部代码可以通过直接调用实例变量的方法去操作数据,这样就隐藏了内部的复杂逻辑,但是从类的外面来看,外部代码还是可以修改一个实例的name,age,scoer属性,这样会使的我们的一些关键性数据变得非常不安全。例如Stuent的对象可以随意的修改自己的成绩。
st1 = Student('XIAOMI',18,90) print(st1.get_level()) st1.score=10 print(st1.get_level())
输出:
XIAOMI,18,B XIAOMI,18,C
当我们想要让对象st1 可以获取自己的成绩但是没有权限区修改自己的成绩,这时就需要将socer变为一个私有变量。私有变量和私有方法,只可以在类的内部进行访问,在类的外面任何对象对不能访问。
定义一个私有变量或私有方法,需要把属性或方法的函数名称前加上两个__,在python中,实例的变量名如果以__开头,就是一个私有的属性,因此我们对Student类做下面修改
class Student(object): def __init__(self, name, age, score): self.name = name self.age = age self.__score = score def get_socre(self): return self.__score def get_level(self): if 90 < self.__score <= 100: return "%s,%s,A" % (self.name, self.age) elif 80 < self.__score <= 90: return "%s,%s,B" % (self.name, self.age) else: return "%s,%s,C" % (self.name, self.age)这样我们的对形象就不可以对socer进行修改,只能使用get_socre()方法去获得对应学生的分数。甚至当我们必须要对象可以去修改socre时 我们可以使用内部的方法去修改,这样我们都可以对传入的参数进行检查。
四、练习
第一题:
使用了的封装实现一个队列的数据结构。
队列的方法:
入队(enqueue), 出队(dequeue), 队头元素(head), 队尾元素(tail),
队列的长度(lenght), 判断队列是否为空(isempty)
显示队列元素(view)
import random class Queue(object): def __init__(self): self.queue = [] def enqueue(self, item): self.queue.append(item) def dequeue(self): if not self.isEmpty(): self.queue.pop(0) def head(self): if not self.isEmpty(): return self.queue[0] def tail(self): if not self.isEmpty(): return self.queue[-1] def length(self): return len(self.queue) def isEmpty(self): # return self.queue == [] return len(self.queue) == 0 def view(self): if not self.isEmpty(): for i in self.queue: print(i, end=",") q1 = Queue() for i in range(5): q1.enqueue(random.randint(1,10)) q1.view()第一题:
栈的方法:
入栈(push), 出栈(pop), 栈顶元素(top),
栈的长度(lenght), 判断栈是否为空(isempty)
显示栈元素(view)
class Stack(object): def __init__(self): self.stack =[] def isEmpty(self): return self.stack == [] def push(self,num): self.stack.append(num) def pop(self): if not self.isEmpty(): self.stack.pop() else: print('Error! statck is empty') def gettop(self): if not self.isEmpty(): return self.stack[-1] def length(self): return len(self.stack) def get_statck(self): return self.stack def view(self): if not self.isEmpty(): for num in self.stack: print(num,end=' ') print('\n') stack = Stack() stack.push(2) stack.view()