两大编程思想
面向过程
功能上的封装,典型代表:C语言
面次对象
属性和行为上的封装:典型代表Java和Pathon
步骤确定:面向过程
类和对象
类:由N多个对象抽取出‘像’的属性和行为从而归纳总结出来的一种类别
在Pathon中一切皆对象
点击查看代码
示例9-1查看对象的数据类型
a=10
b=9.8
s='hello'
print(type(a))
print(type(b))
print(type(s))
1、自定义数据类型的语法结构为
calss 类名():
pass
#类名首字母大写
2、创建对象的语法格式为:
对象名=类名()
点击查看代码
示例9-2自定义数据类型
#编写一个Person
class Person:
pass
#编写一个Cat类
class Cat:
pass
#编写一个Dog类
class Dog:
pass
#编写一个Student类
class Student():
pass
示例9-3创建自定义类型的对象
#编写一个Person
class Person:
pass
#编写一个Cat类
class Cat:
pass
#编写一个Dog类
class Dog:
pass
#编写一个Student类
class Student():
pass
#创建类的对象
#对象名=类名()
#创建一个Person类型的对象
per=Person()#per就是Person类型的对象
c=Cat()#c就是Cat类型的对象
d=Dog()#d就是Dog类型的对象
stu=Student()#stu就是Student类型的对象
print(type(per))
print(type(c))
print(type(d))
print(type(stu))
点击查看代码
示例9-4类属性和实例属性的定义
class Student():
#类属性,定义在类中,方法外的变量
school='北京XXX教育'
#初始化方法
def __init__(self,xm,age):#xm,age是方法的参数,是局部变量,xm,age的作用域在__int__方法
self.name=xm #=左侧是实例属性,xm是局部变量,将局部变量的值xm赋值给实例属性self.name
self.age=age #实例对象和局部变量的名称可以相同
示例9-5类的组成
class Student():
#类属性,定义在类中,方法外的变量
school='北京XXX教育'
#初始化方法
def __init__(self,xm,age):#xm,age是方法的参数,是局部变量,xm,age的作用域在__int__方法
self.name=xm #=左侧是实例属性,xm是局部变量,将局部变量的值xm赋值给实例属性self.name
self.age=age #实例对象和局部变量的名称可以相同
#定义在类中的函数称为方法,自带参数self
def show(self):
print(f'我叫:{self.name},今年:{self.age}岁了')
#静态方法
@staticmethod
def sm():
#print(self.name)
#self.show()
print('这是一个静态方法,不能调用实例属性,也不能调用实例方法')
#类方法
@classmethod
def cm(cls):#cls--->class的简写
# print(self.name)
# self.show()
print('这是一个类方法,不能调用实例属性,也不能调用实例方法')
#创建类的对象
stu=Student('ysj',18)#为什么传了两个参数,因为__int__方法中,有两个形参.self,是自带的参数,无需手动传入
#实例属性,是使用对象名打点调用的
print(stu.name,stu.age)
#类属性,直接使用类名打点调用
print(Student.school)
#实例方法,使用对象名进行打点调用
stu.show()
#类方法,@classmethon进行修饰的方法,直接使用类名打点调用
Student.cm()
#静态方法,@staticmethon进行修饰的方法,直接使用类名打点调用
Student.sm()
示例9-6编写学生类并创建4个学生对象
class Student():
#类属性,定义在类中,方法外的变量
school='北京XXX教育'
#初始化方法
def __init__(self,xm,age):#xm,age是方法的参数,是局部变量,xm,age的作用域在__int__方法
self.name=xm #=左侧是实例属性,xm是局部变量,将局部变量的值xm赋值给实例属性self.name
self.age=age #实例对象和局部变量的名称可以相同
# 定义在类中的函数称为方法,自带参数self
def show(self):
print(f'我叫:{self.name},今年:{self.age}岁了')
#根据’图纸‘可以创建出N多个对象
stu=Student('ysj','18')
stu2=Student('陈玫玫','20')
stu3=Student('玛丽',21)
stu4=Student('Marry',23)#等号右侧都是Student()
print(type(stu))
print(type(stu2))
print(type(stu3))
print(type(stu4))
Student.school=('派森教育') #给类的类属性赋值
#将学生对象存储到列表中
lst=[stu,stu2,stu3,stu4]#列表中的元素是Student类型的对象
for item in lst:#item的hi列表中的元素,是Student类型的对象
item.show() #对象名打点调用实例方法
动态绑定属性和方法
每个对象的属性名称相同,但属性值不同
可以为某个对象绑定独有属性和方法
点击查看代码
示例9-7动态绑定属性和方法
class Student():
#类属性,定义在类中,方法外的变量
school='北京XXX教育'
#初始化方法
def __init__(self,xm,age):#xm,age是方法的参数,是局部变量,xm,age的作用域在__int__方法
self.name=xm #=左侧是实例属性,xm是局部变量,将局部变量的值xm赋值给实例属性self.name
self.age=age #实例对象和局部变量的名称可以相同
# 定义在类中的函数称为方法,自带参数self
def show(self):
print(f'我叫:{self.name},今年:{self.age}岁了')
#创建两个Student类别的对象
stu=Student('ysj',18)
stu2=Student('陈玫玫',20)
print(stu.name,stu.age)
print(stu2.name,stu2.age)
#为stu2动态绑定一个实例属性
stu2.gender='男'
print(stu2.name,stu2.age,stu2.gender)
#print(stu.gender)#AttributeError: 'Student' object has no attribute 'gender'
#动态绑定方法
def introduce():
print('我是一个普通的函数,我被动态绑定成了stu2对象的方法')
stu2.fun=introduce #函数的赋值
#fun 是stu2 对象的方法
#调用
stu2.fun()
面向对象的三大特征
1、封装
点击查看代码
示例9-8权限控制
class Student():
#首尾双下划线
def __init__(self,name,age,gender):
self._name=name #self.name受保护,只能本类和子类访问
self.__age=age # self.__age表示私有的,只能类本身去访问
self.gender=gender #普通的实例属性,类的内部,外部及子类都可以访问
def _fun1(self): #受保护的
print('子类及本身可以访问')
def __fun2(self): #私有的
print('只有定义的类可以访问')
def show(self): #普通的实例方法
self._fun1() #类本身访问受保护的方法
self.__fun2() #类本身访问私有的方法
print(self._name) #受保护的实例属性
print(self.__age) #私有的实例属性
#创建一个学生类的对象
stu=Student('陈玫玫',20,'女')
#类的外部
print(stu._name)
#print(stu.__age)#AttributeError: 'Student' object has no attribute '__age'. Did you mean: '_name'?
#调用受保护的实例方法
stu._fun1()#子类及本身可以访问
#私有方法
#stu.__fun2()#AttributeError: 'Student' object has no attribute '__fun2'. Did you mean: '_fun1'?
print(stu._Student__age) #为什么可以这样访问?
stu._Student__fun2()
print(dir(stu))
示例9-9属性的设置
class Student:
def __init__(self, name,gender):
self.name = name
self.__gender = gender # self.__gender私有的实例属性
#使用@property修饰方法,将方法转成属性使用
@property
def gender(self):
return self.__gender
#将gender这个属性设置为可写属性
@gender.setter
def gender(self,value):
if value != '男' and value!='女':
print('性别有误,已将性别默认设置为男')
self.__gender = '男'
else:
self.__gender = value
stu=Student('陈玫玫','女')
print(stu.name,'的性别是',stu.gender)#stu.gender就会去执行stu.gender()
#尝试修改属性值
#stu.gender='男'#AttributeError: property 'gender' of 'Student' object has no setter
stu.gender='其他'
print(stu.name,'的性别是',stu.gender)
思考:在类外,私有实例属性要通过类进行调用,不可以直接调用,如果要直接调用应使用@property修饰方法,将方法转成属性使用,注意属性不能直接修改,要在类中通过setter更改(私有不可见)
2、继承
class 类名(父类1,父类2......,父类N)
pass
点击查看代码
示例9-10继承
class Person: #默认继承了object
def __init__(self, name,age):
self.name = name
self.age = age
def show(self):
print(f'大家好,我叫:{self.name},我今年:{self.age}岁')
#Student继承Person
class Student(Person):
#初始化方法
def __init__(self,name,age,stuno):
super().__init__(name,age)#调用父类初始化方法为name和age赋值
self.stuno = stuno
#Doctor继承Person类
class Doctor(Person):
def __init__(self,name,age,department):
super().__init__(name,age)
self.department = department
#创建第一个子类
stu=Student('陈玫玫',20,'1001')
stu.show()
doctor=Doctor('张一一',32,'外科')
doctor.show()
示例9-11多继承
class FatherA():
def __init__(self,name):
self.name = name
def showA(self):
print('父类A中的方法')
class FatherB():
def __init__(self,age):
self.age = age
def showB(self):
print('父类B中的方法')
class Son(FatherA,FatherB):
def __init__(self,name,age,gender):
#需要调用两个父类的初始化方法
FatherA.__init__(self,name)
FatherB.__init__(self,age)
self.gender = gender
son=Son('陈玫玫',20,'女')#调用Son类的__init__执行
son.showA()
son.showB()
点击查看代码
示例9-12方法重写
class Person: #默认继承了object
def __init__(self, name,age):
self.name = name
self.age = age
def show(self):
print(f'大家好,我叫:{self.name},我今年:{self.age}岁')
#Student继承Person
class Student(Person):
#初始化方法
def __init__(self,name,age,stuno):
super().__init__(name,age)#调用父类初始化方法为name和age赋值
self.stuno = stuno
def show(self):
#调用父类show的方法
super().show()
print(f'我来自XXX大学,我的学号是{self.stuno}')
#Doctor继承Person类
class Doctor(Person):
def __init__(self,name,age,department):
super().__init__(name,age)
self.department = department
def show(self):
#super().show()#调用父类show的方法
print(f'大家好,我叫:{self.name},我今年{self.age}岁,我的工作科室是:{self.department}')
#创建第一个子类
stu=Student('陈玫玫',20,'1001')
stu.show()#调用子类自己的show方法
doctor=Doctor('张一一',32,'外科')
doctor.show()#调用子类自己的show方法
3、多态
点击查看代码
示例9-13多态
class Person():
def eat(self):
print('人,吃五谷杂粮')
class Cat():
def eat(self):
print('猫,喜欢吃鱼')
class Dog():
def eat(self):
print('狗,喜欢啃骨头')
#这三个类都有一个同名方法
#编写函数
def fun(obj):#obj是函数的形式参数,在定义处知道这个形参的数据类型吗?
obj.eat()#通过变量obj()调用eat方法
#创建三个类的对象
per=Person()
cat=Cat()
dog=Dog()
#调用fun函数
fun(per) #Python中的多态,不关心对象的数据类型,只关心对象是否具有同名方法
fun(cat)
fun(dog)
object类
点击查看代码
示例9-14查看指定类的属性
class Person(object):
def __init__(self, name,age):
self.name = name
self.age = age
def show(self):
print(f'大家好,我叫{self.name},我今年{self.age}岁')
#创建Person类的对象
per=Person('陈玫玫',20)#创建对象是会自动调用__init__方法
print(dir(per))
print(per)#自动调用了__str__方法
示例9-15__str__方法重写之前
class Person(object):
def __init__(self, name,age):
self.name = name
self.age = age
#创建Person的对象
per=Person('陈玫玫',20)
print(per)
示例9-16__str__方法重写之后
class Person(object):
def __init__(self, name,age):
self.name = name
self.age = age
def __str__(self):
return '这是一个人类,具有name和age两个实例属性' #返回值是一个字符串
#创建Person的对象
per=Person('陈玫玫',20)
print(per) #还是内存地址吗?不是,__str__方法中的内容 直接输出对象名,实际上是调用__str__方法
print(per.__str__()) #手动调用
点击查看代码
示例9-17特殊方法
a=10
b=20
print(dir(a))#Python中一切皆对象
print(a+b)#执行加法操作
print(a.__add__(b))
print(a.__sub__(b))#执行减法运算
print(f'{a}<{b}吗',a.__lt__(b))
print(f'{a}<={b}吗',a.__le__(b))
print(f'{a}={b}吗',a.__eq__(b))
print('-'*40)
print(f'{a}>{b}吗',a.__gt__(b))
print(f'{a}>={b}吗',a.__ge__(b))
print(f'{a}!={b}吗',a.__ne__(b))
print('-'*40)
print(a.__mul__(b)) #乘法
print(a.__truediv__(b))#除法
print(a.__mod__(b)) #取余
print(a.__floordiv__(b))#整除
print(a.__pow__(2))#幂运算
特殊属性
点击查看代码
示例9-18特殊属性
class A:
pass
class B:
pass
class C(A,B):
def __init__(self,name,age):
self.name = name
self.age = age
#创建类的对象
a=A()
b=B()
#创建C类的对象
c=C('陈玫玫',20)
print('对象a的属性字典:',a.__dict__) #对象的属性字典
print('对象b的属性字典:',b.__dict__)
print('对象c的属性字典:',c.__dict__)
print('对象a所属的类:',a.__class__)
print('对象b所属的类:',b.__class__)
print('对象c所属的类:',c.__class__)
print('A类的父类元组',A.__bases__)
print('B类的父类元组',B.__bases__)
print('C类的父类元组',C.__bases__)
print('A类的父类',A.__base__)
print('B类的父类',B.__base__)
print('C类的父类',C.__base__) #A类,如果继承了N个父类,结果只显示第一个父类
print('A类的层次结构',A.__mro__)
print('B类的层次结构',B.__mro__)
print('C类的层次结构',C.__mro__) #C类继承了A类,B类,间接继承了object
#子类列表
print('A类的子类列表',A.__subclasses__())#A的子类是C类
print('B类的子类列表',B.__subclasses__())
print('C类的子类列表',C.__subclasses__()) #[]
类的深拷贝与浅拷贝‘
点击查看代码
示例9-19类的深拷贝与浅拷贝
import copy
class CPU():
pass
class Disk():
pass
class Computer():
#计算机使用cpu和硬盘组成
def __init__(self, cpu, disk):
self.cpu = cpu
self.disk = disk
cpu=CPU()#创建了一个CPU对象
disk=Disk()#创建了一个硬盘对象
#创建一个计算机对象
com=Computer(cpu,disk)
#变量(对象)的赋值
com1=com
print(com,'子对象的内存地址:',com.cpu,com.disk)
print(com1,'子对象的内存地址:',com1.cpu,com1.disk)
#类的浅拷贝
print('-'*40)
com2=copy.copy(com)#com2是新产生的对象,com2的子对象cpu和disk不变
print(com,'子对象的内存地址:',com.cpu,com.disk)
print(com2,'子对象的内存地址:',com2.cpu,com2.disk)
#类的深拷贝
print('-'*40)
com3=copy.deepcopy(com)#com3是新产生的对象,com3的子对象cpu和disk也会重新创建
print(com,'子对象的内存地址:',com.cpu,com.disk)
print(com3,'子对象的内存地址:',com3.cpu,com3.disk)
点击查看代码
实战一
#我的思路
class Circle():
def __init__(self, r):
self.r = r
def get_area(self):
area =3.14 * self.r ** 2
print('圆的面积为',area)
def get_perimeter(self):
perimeter = 2 *3.14*self.r
print('圆的周长为', perimeter)
r= int(input('请输入圆的半径:'))
cir=Circle(r)
cir.get_area()
cir.get_perimeter()
print('-'*50)
#老师思路
class Circle():
def __init__(self, r):
self.r = r
#计算面积的方法
def get_area(self):
#return 3.14*self.r**2
return 3.14*pow(self.r,2)
#计算圆的周长
def get_perimeter(self):
return 2*3.14*self.r
#创建对象
r=eval(input('请输入圆的半径:'))
c=Circle(r)
#调用方法
area=c.get_area()
perimeter=c.get_perimeter()
print('圆的面积为:',area)
print('圆的周长为:',perimeter)
点击查看代码
#我的思路
class Student():
def __init__(self, name, age,gender, score):
self.name = name
self.age = age
self.gender = gender
self.score = score
def info(self):
print(f'姓名为:{self.name}, 年龄为:{self.age}, 性别为:{self.gender},得分为: {self.score}')
print('请输入5位学生信息:(姓名#年龄#性别#成绩)')
lst=[]
new_lst=[]
for i in range(5):
stu=input(f'请输入第{i+1}位学生信息:')
lst.append(stu)
s= lst[i].split('#')
new_lst.append(s)
for i in range(0,len(new_lst)):
stu1=Student(new_lst[i][0],new_lst[i][1],new_lst[i][2],new_lst[i][3])
stu1.info()
print('-'*50)
#老师思路
class Student():
def __init__(self, name, age,gender, score):
self.name = name
self.age = age
self.gender = gender
self.score = score
def info(self):
print(self.name,self.age,self.gender,self.score)
print('请输入5位学生信息:(姓名#年龄#性别#成绩)')
lst=[]#用于存储5个学生对象
for i in range(1,6):
s=input(f'请输入第{i}位学生信息:')
s_lst=s.split('#') #索引为0是姓名,索引为1是年龄,索引为2是性别,索引为3是成绩
#创建学生对象
stu=Student(s_lst[0],s_lst[1],s_lst[2],s_lst[3])
#将学生对象添加到列表中
lst.append(stu)
#遍历列表,调用学生对象的info方法
for item in lst: #item的数据类型是Student类型
item.info() #对象名.方法名()
点击查看代码
实战三
class Instrument():
def make_sound(self):
pass
class Erhu(Instrument):
def make_sound(self):
print('二胡在演奏')
class Piano(Instrument):
def make_sound(self):
print('钢琴在演奏')
class Violin(Instrument):
def make_sound(self):
print('小提琴在演奏')
#编写一个函数
def play(obj):
obj.make_sound()
#测试
er=Erhu()
piano=Piano()
vio=Violin()
#调用方法
play(piano)
play(vio)
play(er)
点击查看代码
实战四
#我的思路
class Car():
def __init__(self,car_model,license_plate):
self.car_model=car_model
self.license_plate=license_plate
def start(self):
pass
def stop(self):
pass
class Taix(Car):
def __init__(self,car_model,license_plate,company):
self.company=company
super().__init__(car_model, license_plate)
def start(self):
print('乘客您好!')
print(f'我是{self.company}出租车公司的,我的车牌号是{self.license_plate},您要去哪里?')
def stop(self):
print('目的地到了,请您付款下车,欢迎下次乘坐')
class PrivateCar(Car):
def __init__(self,car_model,license_plate,carname):
self.carname=carname
super().__init__(car_model, license_plate)
def start(self):
print(f'我是{self.carname},我的汽车我做主')
def stop(self):
print('目的地到了,我们去玩吧')
ta=Taix('计程车','京A88888','长城')
ta.start()
ta.stop()
print('-'*50)
pri=PrivateCar('面包车','云A4564','武大郎')
pri.start()
pri.stop()
#老师的思路
class Car():
def __init__(self,type,no,):
self.type = type
self.no = no
def start(self):
print('我是车,我能启动')
def stop(self):
print('我是车,我能停止')
#出租车
class Taxi(Car):
def __init__(self,type,no,company):
super().__init__(type,no)
self.company = company
#重写父类的启动与停止
def start(self):
print('乘客您好!')
print(f'我是{self.company}出租车公司的,我的车牌号是{self.no},您要去哪里?')
def stop(self):
print('目的地到了,请您付款下车,欢迎下次乘坐')
class Family(Car):
def __init__(self,type,no,name):
super().__init__(type,no)
self.name = name
def start(self):
print(f'我是{self.name},我的汽车我做主')
def stop(self):
print('目的地到了,我们去玩吧')
#测试
taix=Taxi('上海大众','京A88888','长城')
taix.start()
taix.stop()
print('-'*50)
family_car=Family('广汽丰田','京B66666','武大郎')
family_car.start()
family_car.stop()