第六章 类与对象
基本概念
面向对象的特征:封装性、继承性、多态性
封装性:把客观事物封装成抽象的类,隐藏了属性和方法实现细节,仅对外提供公共的访问方式。
继承性:两种事物之间存在着一定的所属关系,那么继承的类可以从被继承的类中获得属性和方法,在无须重写原来类的情况下对这些功能进行扩展,提高代码的复用性和可扩展性
多态性:一个抽象类有多个子类,多态的概念依赖于继承;不同对象在接收同一条消息时会产生不同的行为,即每个对象可以用自己的方式去响应共同的消息,执行不同的函数,提高程序扩展性。
类
提供组合数据和功能的方法,用来描述具有相同属性和方法的类型的类型集合。
class 类名:
"""
类文档字符串
"""
类体
类名通常首字母大写以区分函数名。
类文档字符串是一段简要描述类相关信息的字符串,可以通过类名.__doc__方法来访问。
类体是包含描述状态的数据(属性)和描述操作的成员函数(方法),如果要创建一个空类,可以指定类体为pass
对象
定义了新类意味着定义了一个新的对象类型,从而允许创建该类型的新实例。
实例名 = 类名.方法名([形参列表]),其中形参列表与__init__函数保持一致
调用实例的格式如下:
实例名.方法名([形参列表])
实例名.属性
>>> class Person:
name='小明'
def hello(self):
print('hello world')
>>> if __name__=='__main__':
p1=Person()#创建对象实例
p1.hello()
print(p1.name)
hello world
小明
当python文件直接被运行,则if __name__=='__main__':运行if下面的代码;
如果python文件是作为模块在其他函数中被调用,则不能运行。
属性
1、实例属性
通过__init__函数中的参数分别对实例属性进行赋值,得到实例化对象。
__init__函数中第一个参数必须是self。
>>> class Person:
def __init__(self,name,gender):
#在类中通过self.属性的方式使用实例属性
self.name=name
self.gender=gender
>>> if __name__=='__main__':
P1=Person('小明','男')
>>> print('{}的性别是{}'.format(P1.name,P1.gender))
小明的性别是男
注意:通过实例.属性的方式使用实例属性,不可以通过使用类对象访问实例属性,如:
print('身高是{}'.format(Person.height)) #错误
2、类属性
类属性又称静态属性,为所有类对象的实例对象(方法)所共有,内存中只有一个副本,多个实例对象之间共享。
class Person:
count=0
def __init__(self,name,gender,age,height,weight):
self.name=name
self.gender=gender
self.age=age
self.height=height
self.weight=weight
Person.count+=1
print('初始化{}完成,当前Person类共有实例{}个'.format(name,Person.count))
if __name__=='__main__':
p1=Person('小明','男',20,170,70)
print('当前总人数为:{}'.format(Person.count))#通过类名
p2=Person('小红','女',30,160,60)
print('当前总人数为:{}'.format(p2.count))#通过实例
在上述例子中,count是类属性,其他是实例属性
——常见内置类属性——
常见专有属性 | 说明 |
__dict__ | 由类的数据属性组成属性字典 |
__doc__ | 类的文档字符串 |
__name__ | 类名 |
__module | 实例对象所在模块名称 |
__bases__ | 类所有父类构成的元组 |
方法
方法可以分为实例方法、类方法和静态方法。
实例方法
又称对象方法,指用户在类中定义的普通方法。实例方法只有实例对象能使用,类对象不能。
class Person:
def __init__(self,name):
self.name=name
def eat(self,food):
print('{}在吃{}'.format(self.name,food))
if __name__=='__main__':
p1=Person('熊猫')
p1.eat('竹子')
Person.eat('竹子')
运行结果:
第一句话输出熊猫在吃竹子,第二句话报错
类方法
类对象所拥有的方法,声明类方法需要用修饰器@classmethod标识。 类方法要求第一个形参必须是类对象cls。因为传入的参数是类变量而不是实例变量,所以类方法不能访问实例属性而只能访问类属性。
class Person:
count=0
def __init__(self,name):
self.name=name
Person.count+=1
def eat(self,food):
print('{}在吃{}'.format(self.name,food))
@classmethod
def showcount(cls):
print('当前共创建实例对象{}个'.format(cls.count))
if __name__=='__main__':
Person.showcount()
p1=Person('熊猫')
p1.eat('竹子')
Person.showcount()#通过类对象访问类方法
p2=Person('鸽子')
p2.showcount()#通过实例对象访问类方法
运行结果:
当前共创建实例对象0个 熊猫在吃竹子 当前共创建实例对象1个 当前共创建实例对象2个
静态方法
用修饰器@staticmethod来标识。静态方法不需要传入self参数,也不需要传入cls参数,所以不能获得类中定义的实例属性和其他方法。
class Person:
count=0
def __init__(self,name,id):
self.name=name
if Person.checkid(id):
self.id=id
else:
return
Person.count+=1
@classmethod
def showcount(cls):
print("当前共创建实例对象{}个".format(cls.count))
@staticmethod
def checkid(id):
if len(id)!=18:
print('输入身份证号码长度有误')
return False
else:
return True
Person.showcount()
p1=Person('panda','360111199612111211')
Person.showcount()
p2=Person('luo','32022219800911091')#身份证号码长度错误
Person.showcount()
运行结果:
当前共创建实例对象0个
当前共创建实例对象1个
输入身份证号码长度有误
当前共创建实例对象1个
实例属性 | 类属性 | 实例方法 | 类方法 | 静态方法 | |
实例对象 | √ | √ | √ | √ | √ |
类对象 | × | √ | × | √ | √ |
实例方法 | √ | √ | √ | √ | √ |
类方法 | × | √ | × | √ | √ |
静态方法 | × | √ | × | √ | √ |
私有成员和公有成员
class Person:
count=0
def __init__(self,name,id):
self.name=name
if Person.checkid(id):
self.id=id
else:
return
Person.count+=1
@staticmethod
def checkid(id):
if len(id)!=18:
print('输入身份证号码长度有误')
return False
else:
return True
Person.checkid('123456')
运行结果:
输入身份证号码长度有误
若改为私有静态方法__check(id),则程序报错。因为此时只能在定义类体时访问,在外部不能访问。
@staticmethod
def __checkid(id):
if len(id)!=18:
print('输入身份证号码长度有误')
return False
else:
return True
Person.__checkid('123456')
报错
继承机制
子类的定义
类成员的继承和重写
class vehicle():
def __init__(self,speed):
self.speed=speed
def stop(self):
self.speed=0
print("已停止")
def speedup(self,x):
self.speed+=x
def speeddown(self,x):
self.speed-=x
def move(self):
print('交通工具正在以速度{}行驶'.format(self.speed))
class plane(vehicle):
def __init__(self,speed,height):
vehicle.__init__(self,speed)
self.height=height
def up(self,x):
self.height+=x
def down(self,x):
self.height-=x
def move(self):
print('飞机正在以速度{}在高度{}飞行'.format(self.speed,self.height))
c=plane(1000,20000)
c.move()#重写
c.speedup(200)#继承
c.down(5000)
c.move()
运行结果:
飞机正在以速度1000在高度20000飞行
飞机正在以速度1200在高度15000飞行
常用类及其相关内置函数
__getitem__(self,key):获取序列的索引key对应的值,等价于seq[key]
class myList:
def __init__(self,data):
self.data=data
def __getitem__(self,index):
return self.data[index]
#创建自定义列表对象
my_list=myList([1,2,3,4,5])
#使用__getitem__获取元素
print(my_list[2])
程序思考题
1、创建老师类和学生类
#创建老师类
class Teacher:
def __init__(self, teacher_id, name, sex, age, class0, income):
self.teacher_id = teacher_id
self.name = name
self.sex = sex
self.age = age
self.class0 = class0
self.income =income
def eat(self):
print(f"{self.name} is eating.")
def sleep(self):
print(f"{self.name} is sleeping.")
def teach(self):
print(f"{self.name} is teaching.")
def greet(self):
print(f"{self.name} is greeting.")
# 创建一个老师实例
teacher1 = Teacher(1, "yuan", 'male', 27, 2, 1000 )
# 调用方法
teacher1.eat()
#创建学生类
class Student:
def __init__(self, student_id, name, sex, age, grade):
self.student_id = student_id
self.name = name
self.sex = sex
self.age = age
self.grade = grade
def eat(self):
print(f"{self.name} is eating.")
def sleep(self):
print(f"{self.name} is sleeping.")
def study(self):
print(f"{self.name} is studying.")
def greet(self):
print(f"{self.name} is greeting.")
# 创建一个学生实例
student1 = Student(1, "shuo", 'male', 16, 3)
# 调用方法
student1.study()
运行结果:
yuan is eating.
shuo is studying.
将老师类和学生类抽象为父类,减少代码冗余:
class Person:
def __init__(self, person_id, name, sex, age):
self.person_id = person_id
self.name = name
self.sex = sex
self.age = age
def eat(self):
print(f"{self.name} is eating.")
def sleep(self):
print(f"{self.name} is sleeping.")
def greet(self):
print(f"{self.name} is greeting.")
class Teacher(Person):
def __init__(self, teacher_id, name, sex, age, class0, income):
super().__init__(teacher_id, name, sex, age)
self.class0 = class0
self.income = income
def teach(self):
print(f"{self.name} is teaching.")
class Student(Person):
def __init__(self, student_id, name, sex, age, grade):
super().__init__(student_id, name, sex, age)
self.grade = grade
def study(self):
print(f"{self.name} is studying.")
# 创建实例
teacher1 = Teacher(1, "yuan", 'male', 27, 2, 1000)
student1 = Student(1, "shuo", 'male', 16, 3)
# 调用方法
teacher1.eat()
student1.study()
运行结果相同。