类与对象(下)

1、类与对象

1.1、类与对象的关系
【类】是【对象】的模板。
在这里插入图片描述
在这里插入图片描述
1.2、实例对象的概念
【类】就像工厂的模具,以它为模板,造出来的成千上万的产品,才是被我们消费、购买、使用,真正融入我们生活的东西。这些产品,在Python中就叫【实例对象】。
在这里插入图片描述

2、类的实例化

2.1、实例化的基本格式
直接使用类:
在这里插入图片描述
实例化后再使用:
在这里插入图片描述
提示:实例名可以任取一个变量名,可以和类名相同!

例题-成绩单
直接使用类:

class 成绩单():
  @classmethod
  def 录入成绩单(cls):
    cls.学生姓名 = input('请输入学生姓名:')
    cls.语文_成绩 = int(input('请输入语文成绩:'))
    cls.数学_成绩 = int(input('请输入数学成绩:'))
  @classmethod
  def 打印成绩单(cls):
    print(cls.学生姓名 + '的成绩单如下:')
    print('语文成绩:'+ str(cls.语文_成绩))
    print('数学成绩:'+ str(cls.数学_成绩))

成绩单.录入成绩单()
成绩单.打印成绩单()

实例化:

class 成绩单():
  def 录入成绩单(self):
    self.学生姓名 = input('请输入学生姓名:')
    self.语文_成绩 = int(input('请输入语文成绩:'))
    self.数学_成绩 = int(input('请输入数学成绩:'))
  
  def 打印成绩单(self):
    print(self.学生姓名 + '的成绩单如下:')
    print('语文成绩:'+ str(self.语文_成绩))
    print('数学成绩:'+ str(self.数学_成绩))

成绩单1=成绩单() # 实例化,得到实例对象“成绩单1”
成绩单1.录入成绩单() #实例化后再调用
成绩单1.打印成绩单()
>>>
请输入学生姓名:doudou
请输入语文成绩:87
请输入数学成绩:98
doudou的成绩单如下:
语文成绩:87
数学成绩:98

注意:实例化后,如果按直接使用类方法调用,则会报错
在这里插入图片描述
2.2、实例属性和类属性
当一个类实例化为多个实例后,实例将原封不动的获得类属性,也就是实例属性和类属性完全相等。
在这里插入图片描述

class():
  变量=100

实例1 =() # 实例化
实例2 =() # 实例化

print(.变量)

print(实例1.变量)  
print(实例2.变量)
>>>
100
100
100

我们可以修改类属性,这会导致所有实例属性变化(因为类是模板)。
在这里插入图片描述

class():
  变量 = 100

实例1 =() # 实例化
实例2 =() # 实例化

print(实例1.变量)
print(实例2.变量).变量 = 'abc'   # 修改类属性
print(实例1.变量)   # 实例属性同步变化
print(实例2.变量)   # 实例属性同步变化
>>>
100
100
abc
abc

对比:

class():
  变量 = 100

实例1 =() # 实例化
实例2 =() # 实例化

print(实例1.变量)
print(实例2.变量)

实例1.变量=10.变量 = 'abc'   # 修改类属性
print(实例1.变量)   # 类.变量=‘abc’不影响它
print(实例2.变量)   # 实例属性同步变化
>>>
100
100
10
abc

我们也可以修改实例属性,但这不会影响到其他实例,也不会影响到类。因为每个实例都是独立的个体。
在这里插入图片描述

class():
  变量 = 100

实例1 =() # 实例化
实例2 =() # 实例化

print('原先的类属性:')
print(.变量)

print('原先的实例1属性:')
print(实例1.变量)

print('原先的实例2属性:')
print(实例2.变量)

实例1.变量 = 'abc'

print('修改后的实例1的属性:'+实例1.变量) 
print(实例2.变量)
print(.变量)
>>>
原先的类属性:
100
原先的实例1属性:
100
原先的实例2属性:
100
修改后的实例1的属性:abc
100
100

新增也是一样的道理,在类中新增属性会影响到实例,但在实例中新增属性只影响这个实例自己。
(1)新增类属性

class():
  变量1 = 100.变量2 = 'abc' # 新增类属性

实例 =() # 实例化

print(实例.变量1)
print(实例.变量2)
>>>
100
abc

(2)新增实例属性

class():
  变量1 = 100

实例 =() # 实例化

实例.变量2 = 'abc' # 新增实例属性

print(实例.变量2)
#输出abc
print(.变量2)
#报错

2.3、实例方法和类方法
和类属性一样,我们可以重写类方法,这会导致所有实例方法自动被重写。
在这里插入图片描述
“重写类方法”分成两个步骤:
(1)在类的外部写一个函数;
(2)把这个新函数的名字赋值给类.原始函数。
在这里插入图片描述
注意: 这里的赋值是在替换方法,并不是调用函数,所以【不要加上括号】—— 写成类.原始函数() = 新函数()是错误的。

 class():
  def 原始函数(self):
    print('我是原始函数!')

def 新函数(self):
  print('我是重写后的新函数!')

a =()  # 实例化
a.原始函数()

# 用新函数代替原始函数,也就是【重写类方法】.原始函数 = 新函数

# 现在原始函数已经被替换了
a.原始函数() 
 #第二次调用a.原始函数()的效果是新函数效果
>>>
我是原始函数!
我是重写后的新函数!

我们可以通过重写类方法,让实例方法发生变化,但我们不能重写实例方法,模板给的技能不是说换就能换的。
在这里插入图片描述
实例的属性和方法总结:
在这里插入图片描述
2.4、初始化函数

class():
  def __init__(self):#函数名是固定格式
    print('实例化成功!')

实例 =()
>>>
实例化成功!

创建一个实例的时候,这个函数就会被调用。上面的代码在执行实例 = 类()的语句时,就 自动调用 了__init__(self)函数,不用类. init()这一步!

初始化函数的写法是固定的格式:
中间是“init”,然后前后都要有【 两个下划线 】,然后__init__()的括号中, 第一个参数一定要写上self, 不然会报错。

class 成绩单():
  def __init__(self,学生姓名,语文_成绩,数学_成绩):
    self.学生姓名 = 学生姓名
    self.语文_成绩 = 语文_成绩
    self.数学_成绩 = 数学_成绩

  def 打印成绩单(self):
    print(self.学生姓名 + '的成绩单如下:')
    print('语文成绩:'+ str(self.语文_成绩))
    print('数学成绩:'+ str(self.数学_成绩))


成绩单1 = 成绩单('张三',99,88)
成绩单2 = 成绩单('李四',64,73)
成绩单3 = 成绩单('王五',33,22)

成绩单1.打印成绩单()
成绩单2.打印成绩单()
成绩单3.打印成绩单()
>>>
张三的成绩单如下:
语文成绩:99
数学成绩:88
李四的成绩单如下:
语文成绩:64
数学成绩:73
王五的成绩单如下:
语文成绩:33
数学成绩:22

在我们实例化的过程,可以通过初始化函数__init__给类传递不同的参数

3、类的继承

3.1 单继承
定义:子类从【一个父类】继承类方法
格式:class 新类(旧类)
在这里插入图片描述
例子:子类原封不动地继承了父类

class 父类():
  def __init__(self,参数):
    self.变量 = 参数
  def 打印属性(self):
    print('变量的值是:')
    print(self.变量)

class 子类(父类):
  pass  # pass语句代表“什么都不做”

子类实例 = 子类(2)
子类实例.打印属性()
>>>
变量的值是:
2

在这里插入图片描述
子类可以定制新的类方法
下面我们来做一个练习。这里有一段残缺的代码:
在这里插入图片描述
代码运行的效果如下:
在这里插入图片描述
程序:

class 基础机器人():
  def __init__(self,参数):
    self.姓名 = 参数

  def 自报姓名(self):
    print('我是' + self.姓名 + '!')     

  def 卖萌(self):
    print('主人,求抱抱!')

class 高级机器人(基础机器人):
  def 高级卖萌(self):
  #子类定义的新的类方法
    print('主人,每次想到怎么欺负你的时候,就感觉自己全身biubiubiu散发着智慧的光芒!')

安迪 = 高级机器人('麦克')

安迪.自报姓名()
安迪.卖萌()
安迪.高级卖萌()
>>>
我是安迪!
主人,求抱抱!
主人,每次想到怎么欺负你的时候,就感觉自己全身biubiubiu散发着智慧的光芒!

子类还能直接覆盖父类的方法,只要使用相同的类方法名称即可

class 基础机器人():
  def __init__(self,参数):
    self.姓名 = 参数

  def 自报姓名(self):
    print('我是' + self.姓名 + '!')     

  def 卖萌(self):
    print('主人,求抱抱!')

class 高级机器人(基础机器人):
  def 卖萌(self):  
  # 这里使用了相同的类方法名称“卖萌”,这样可以让子类方法覆盖父类方法
    print('主人,每次想到怎么欺负你的时候,就感觉自己全身biubiubiu散发着智慧的光芒!')

鲁宾=高级机器人('鲁宾')
鲁宾.自报姓名()
鲁宾.卖萌()
>>>
我是鲁宾!
主人,每次想到怎么欺负你的时候,就感觉自己全身biubiubiu散发着智慧的光芒!

我们可以在子类中重写覆盖任意父类方法,哪怕是初始化函数__init__。

class 基础机器人():
  def __init__(self,参数):
    self.姓名 = 参数

  def 自报姓名(self):
    print('我是' + self.姓名 + '!')     

  def 卖萌(self):
    print('主人,求抱抱!')

class 高级机器人(基础机器人):
  def __init__(self,参数,数字):
    self.姓名=参数
    self.智商=数字  
    #覆盖父类中的初始化函数  
    
  def 自报姓名(self):
    print('我是高级机器人'+self.姓名+'! '+'智商高达'+str(self.智商)+'!')       

  def 卖萌(self):
    print('主人,每次想到怎么欺负你的时候,就感觉自己全身biubiubiu散发着智慧的光芒!')

安迪 = 高级机器人('安迪',150)
安迪.自报姓名()
安迪.卖萌()
>>>
我是高级机器人安迪! 智商高达150!
主人,每次想到怎么欺负你的时候,就感觉自己全身biubiubiu散发着智慧的光芒!

3.2 多继承
定义:一个子类从【多个父类】中继承类方法
格式:class 子类(父类1,父类2,……)
注意:多重继承要求父类是平等的关系
在这里插入图片描述

class 基础机器人():
  def 卖萌(self):
    print('主人,求抱抱!')
 # 注:因为多重继承要求父类是平等的关系,所以这里的“高级机器人”没有继承“基础机器人”

class 高级机器人(): 
  def 高级卖萌(self): 
    print('主人,每次想到怎么欺负你的时候,就感觉自己全身biubiubiu散发着智慧的光芒!')

class 超级机器人(基础机器人,高级机器人):
  #继承两个父类
  def 超级卖萌(self): 
    print('pika, qiu!')


安迪=超级机器人()

安迪.卖萌()
安迪.高级卖萌()    
安迪.超级卖萌()  
>>>
主人,求抱抱!
主人,每次想到怎么欺负你的时候,就感觉自己全身biubiubiu散发着智慧的光芒!
pika, qiu!

4、实际操作

练习1—问卷搜集器

1、问卷答案的存储

#不用运行,读懂即可
class Survey():

  # 收集调查问卷的答案
  def __init__(self, question):
    self.question = question
    #定义问卷问题答案的列表
    self.response = []

  # 显示调查问卷的题目
  def show_question(self):
    print(self.question)

  # 存储问卷搜集的答案
  def store_response(self,new_response):
    self.response.append(new_response)

2、搜集问题—最喜欢的美食

class Survey():

  # 收集调查问卷的答案
  def __init__(self, question):
    self.question = question
    #定义问卷问题答案的列表
    self.response = []

  # 显示调查问卷的题目
  def show_question(self):
    print(self.question)

  # 存储问卷搜集的答案
  def store_response(self,new_response):
    self.response.append(new_response)

#实例化Survey,并显示问卷问题
food_survey=Survey('你最喜欢的美食是什么?')
food_survey.show_question()

#存储问卷调查的美食名称
while True:
  response = input('请回答问卷问题,按q键退出:')
  if response == 'q':
    break
  else:
    food_survey.store_response(response) #调用实例方法,进行问卷答案的收集

#输出测试
for food in food_survey.response:
  print('美食:'+food)
 print(food_survey.response)
  >>>
  你最喜欢的美食是什么?
请回答问卷问题,按q键退出:三汁焖锅
请回答问卷问题,按q键退出:海鲜大咖
请回答问卷问题,按q键退出:牛排
请回答问卷问题,按q键退出:q
美食:三汁焖锅
美食:海鲜大咖
美食:牛排
['三汁焖锅','海鲜大咖','牛排']

3、实名问卷—搜集名字和籍贯地

class Survey():

  # 收集调查问卷的答案
  def __init__(self, question):
    self.question = question
    #定义问卷问题答案的列表
    self.response = []

  # 显示调查问卷的题目
  def show_question(self):
    print(self.question)

  # 存储问卷搜集的答案
  def store_response(self,new_response):
    self.response.append(new_response)

# 定义实名调查问卷的新类RealNameSurvey,继承子Survey类    
class RealNameSurvey(Survey):
  def __init__(self, question):
    Survey.__init__(self,question) 
    #这里直接调用旧类中的初始化函数。用幅值语句:self.question=question也可以  
    self.response = {}  # 由于籍贯地和名字挂钩,所以用构成为“键值对”的字典来存放。
    
  # 存储问卷搜集的答案(覆盖父类的类方法)
  def store_response(self, name, new_response):  # 除了self,还需要两个参数。
    self.response[name] = new_response  # 键值对的新增

survey = RealNameSurvey('你的籍贯地是哪?')
survey.show_question()

#存储问卷调查的姓名和籍贯
while True:
  response = input('请回答问卷问题,按q键退出:')
  if response == 'q':
    break
  else:
    name=input('请输入回答者姓名:')
    survey.store_response(name,response) #调用新类中的类方法,将两次input的字符串存入字典

#输出测试
for name,response in survey.response.items():  #字典的遍历
  print(name+':'+response)
  >>>
  你的籍贯地是哪?
请回答问卷问题,按q键退出:广东深圳
请输入回答者姓名:小红
请回答问卷问题,按q键退出:江西九江
请输入回答者姓名:小华
请回答问卷问题,按q键退出:西藏拉萨
请输入回答者姓名:小高
请回答问卷问题,按q键退出:q
小红:广东深圳
小华:江西九江
小高:西藏拉萨

练习2—那个男人来了
分析比较3中方法的异同!

方法1:新类中没有定义初始化函数,而是在对Man类实例化时,传入参数,仍然使用旧类的初始化函数!

class Person:
  def __init__(self, name):
    self.name = name
    print('大家注意了!')

  def show(self):
    print('一个叫“%s”的人来了。' % self.name)

class Man(Person):

  def show(self):
    print('一个叫“%s”的男人来了。' % self.name)
    #子类直接覆盖父类的方法,只要使用相同的类方法名称即可

  def leave(self):  # 子类定制新方法
    print('那个叫“%s”的男人留下了他的背影。' % self.name)

author1 = Person('吉多')
author1.show()

author2 = Man('范罗苏姆')
author2.show()

author3 = Man('范罗苏姆')
author3.leave()
>>>
大家注意了!
一个叫“吉多”的人来了。
大家注意了!
一个叫“范罗苏姆”的男人来了。
大家注意了!
那个叫“范罗苏姆”的男人留下了他的背影。

方法2:在新类中调用旧类的初始化函数,具体操作内容见程序,这是一种常见的方法!

class Person:
  def __init__(self, name):
    self.name = name
    print('大家注意了!')
    
  def show(self):
    print('一个叫“%s”的人来了。' % self.name)

class Man(Person):
  def __init__(self):
    Person.__init__(self, name='范罗苏姆')  # 直接调用旧类的初始化函数,并且传入参数
    # 上面的括号里也可以写成(self,'范罗苏姆'),但加上参数后清晰一些,代码看起来更清晰

  def show(self):
    print('一个叫“%s”的男人来了。' % self.name)

  def leave(self):  # 子类定制新方法
    print('那个叫“%s”的男人留下了他的背影。' % self.name)

author1 = Person('吉多')
author1.show()

author2 = Man()
author2.show()

author3 = Man()
author3.leave()
>>>
大家注意了!
一个叫“吉多”的人来了。
大家注意了!
一个叫“范罗苏姆”的男人来了。
大家注意了!
那个叫“范罗苏姆”的男人留下了他的背影。

方法3:

class Person:
  def __init__(self, name):
    self.name = name
    print('大家注意了!')
    
  def show(self):
    print('一个叫“%s”的人来了。' % self.name)

class Man(Person):
  def __init__(self,name):#方法2的这里,只有一个参数
    Person.__init__(self,name)  #这里name不赋值

  def show(self):
    print('一个叫“%s”的男人来了。' % self.name)

  def leave(self):  # 子类定制新方法
    print('那个叫“%s”的男人留下了他的背影。' % self.name)

author1=Person('吉多')
author1.show()

author2=Man('范罗苏姆')
author2.show()

author3=Man('范罗苏姆')
author3.leave()  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值