面向对象编程
OOP,是一种程序设计思想。OOP把对象作为程序的基本单元,
一个对象包含了数据和操作数据的函数。
面向过程:把程序当做一组命令集合顺序执行。
为了简化流程,面向过程一般把函数切分为子函数。来降低系统复杂度。
面向对象:把程序当做一组对象集合。
每个对象都可以互相接收发送处理指令消息,
程序的执行也就是一系列消息在对象之间传递、
python中万物皆对象。可以自定义对象,自定义对象数据类型对应了类的概念。
实例:
处理学生成绩,面向过程程序可以用如下方式:
#定义两个学生字典
>>> std1={'name':'Amy','score':98}
>>> std2={'name':'Ellen','score':89}
#打印信息函数
>>> def print_score(std):
... print('%s:%s'%(std['name'],std['score']))
...
>>> print_score(std1)
Amy:98
>>> print_score(std2)
Ellen:89
面向对象:首先思考的不是执行流程,而是学生这种类型可以定义一个对象
它包含了name,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))
...
>>> std1=Student('amy',98)
>>> std2=Student('ellen',89)
>>> std1.print_score()
amy:98
>>> std2.print_score()
ellen:89
类和实例
类是抽象的模板,实例是根据类创建出来的一个个具体对象。
每个对象都有自己的属性和方法。
定义类
class 类名(object):
语句。。
类名:通常大写开头单词
object:表示该类是从哪个类继承下来的。如果没有,默认用object即可。
创建实例
实例名=类名+()
>>> std1=Student('amy',98)
>>> std1
<__main__.Student object at 0x0000000002AE02E8>
>>> Student
<class '__main__.Student'>
绑定属性
std1.name= xxx
__init__方法:创建实例的时候,将属性强制写入进去
... def __init__(self,name,score):
... self.name=name
... self.score=score
注意:__init__方法的第一个参数永远是self,表示创建的实例本身。可以将属性绑定到self,self指向实例。
传参的时候不用将self传入,默认会将实例变量传入。
和普通的函数相比,唯一的区别就是,第一个参数永远是self,调用时也不用传参数。
面向对象的三大特征:封装,继承,多态
数据封装
在类内部定义访问数据的函数。外部程序无需关心如何实现,直接调用即可。
这些函数也可以称为数据的方法。
方法和函数关系:定义在类中的函数称为方法,外边的叫做函数。
>>> std3=Student('P',100)
>>> std3.print_score()
P:100
代码:
class Student(object):
def __init__(self, name, score):
self.name = name
self.score = score
def get_grade(self):
if self.score >= 90:
return 'A'
elif self.score >= 60:
return 'B'
else:
return 'C'
lisa = Student('Lisa', 99) bart = Student('Bart', 59) print(lisa.name, lisa.get_grade()) print(bart.name, bart.get_grade())
私有变量
如果想要内部属性不被外部访问,可以把属性的名称前加上两个下划线。
变为私有变量,只有内部可以访问,外部不能访问。
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))
std1=Student('Amy',98)
std2=Student('Ellen',89)
print(std2.name)
print(std2.__score)
#std1.print_score()
#std2.print_score()
执行结果:
Ellen
Traceback (most recent call last):
File "C:\Users\pangli-os\Desktop\practice.py", line 15, in <module>
print(std2.score)
AttributeError: 'Student' object has no attribute 'score'
作用:确保了外部代码不能随意修改对象内部的状态
问题来了,如果外部想要读取和修改怎么办呢?
增加一个方法get_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))
def get_score(self):
return self.__score
std1=Student('Amy',98)
std2=Student('Ellen',89)
print(std2.name)
print(std2.get_score())
修改
增加一个方法set_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))
def get_score(self):
return self.__score
def set_score(self,score_new):
self.__score=score_new
#std1=Student('Amy',98)
std2=Student('Ellen',89)
print(std2.name)
print(std2.get_score())
std2.set_score(100)
练习:将上述代码,进行传参校验。只有传入的score值在0~100之间,才允许设置,否者报错
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_score(self):
return self.__score
def set_score(self,score_new):
if 0<=score_new<=100:
self.__score=score_new
else:
raise ValueError('参数错误')
#std1=Student('Amy',98)
std2=Student('Ellen',89)
print(std2.name)
print(std2.get_score())
std2.set_score(100)
print(std2.get_score())
std2.set_score(123)
#std1.print_score()
#std2.print_score()
继承和多态
定义一个类如果从现有的class继承,新的class叫做子类
被继承的class称为基类,或者父类
class Animal(object):
def fun(self):
print('Animal is running....')
class Dog(Animal):
pass
class Cat(Animal):
pass
对于dog和cat来说,animal就是它的父类
继承的好处?
子类获得了父类的全部功能。Animal有run的功能,cat和dog也有run的 功能,不用重复定义。
class Animal(object):
def run(self):
print('Animal is running....')
class Dog(Animal):
pass
class Cat(Animal):
pass
dog=Dog()
dog.run()
也可以对子类增加一些方法
class Animal(object):
def run(self):
print('Animal is running....')
class Dog(Animal):
def run(self):
#子类中重写的方法,会覆盖父类的方法。
print('Dog is running....')
def eat(self):
print('Dog is eating....')
class Cat(Animal):
pass
dog=Dog()
dog.run()
dog.eat()
引申到另外一个概念,多态
定义类的时候,实际上就定义了一种数据类型
这种数据类型跟自带的没有区别,str,list,tuple
print(isinstance(dog,Dog))
print(isinstance(dog,Animal))
print(isinstance(dog,Cat))
总结:
1、 继承关系中,如果一个实例的数据类型是某个子类,
那么它的数据类型也可以当做一个父类。反之不行。
a=Animal()
dog=Dog()
dog.run()
dog.eat()
print(isinstance(dog,Dog))
print(isinstance(dog,Animal))
print(isinstance(a,Cat))
实例属性和类属性
实例属性:
class Student(object):
def __init__(self,name):
self.name=name
s=Student('Amy')
print(s.name)
类属性:
class Student(object):
age=20
def __init__(self,name):
self.name=name
class Student(object):
age=20
def __init__(self,name):
self.name=name
s=Student('Amy')
print(s.name) #打印实例属性
print(Student.name) #错误写法
print(s.age) #打印实例属性
print(Student.age) #打印类属性
实例属性优先级要高于类属性,重写会打印重写的值
class Student(object):
name='root'
s=Student()
s.name='Amy'
print(s.name)