一、面向对象编程
面向对象编程--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()