# ================================
# -*- coding:utf-8 -*-
# @Author:henry
# @Time:2020/6/8 17:09
# Email:yinpingwei@gmail.com
# @File: 2020-06-08python类的继承,多态和动态属性设置.py
# =================================
"""
实例方法 必须掌握
类方法 单元测试用的多
静态方法 基本不用
"""
# 1.静态方法(了解即可,用不到)
'''
静态方法(了解即可,用不到)
1)在类内部定义:使用装饰器@staticmethod。参数随意,参数没有“self”和"cls"参数
2)与类没有任何关联,就是一个普通函数,只不过放在类中,方便管理
3)调用:实例对象和类对象都可以调用。
4)应用场景:存放逻辑代码,内部不需要引用类属性和实例属性。
'''
def hello():
print("hello")
class Dog:
def bark(self):
print("叫")
@classmethod # 类方法
def set_kind(cls):
cls.kind = "狗"
@staticmethod # 静态方法 装饰器@staticmethod
def hello(flag=True):
print("hello,dog!!")
Dog.hello() # 类调用静态方法
d = Dog() # 实例化
d.hello() # 对象调用实例方法
# 2.类的继承
"""
单继承:
1.继承语法 :class 子类(父类)
2.私有化:父类不想让子类继承部分属性和方法(了解即可)有2种:
第一种是深度的:
父类当中以双下划线__开头的属性/方法,仅定义父类内部可用.
父类对象和子类/子类对象都不可以用。
第二种是浅度的:
类定义时,以单下划线_开头的属性/方法,父类内部/子类内部都可以用。
父/子对象不建议使用。
潜规则 - 告诉你这是私有化的,全靠对象自觉。硬要用也是可以的,不会报错。
3.继承后,在子类中面临的问题是-子类和父类有同名方法的时候的处理:
第一种是:完全重写父类的某个同名方法
重写
第二种是:继承使用父类的同名方法。但是在父类的基础上,再拓展内容。
语法:super().同名方法()--调用父类的同名方法
1个父类 可以有 N个子类
# 多继承(了解一下)
1.多继承:任何一个类,可以有N个父类
语法:class 类名(父类1,父类2,父类3....父类N)
问题:菱形继承??(自行查资料)
继承来讲:自己有用自己的,自己没有用,一层层往上找。
祖先类(默认继承):object
"""
# 父类
class Base:
def __init__(self, name):
print("初始化对象:{}!".format(self))
self.name = name
def eat(self):
print("吃")
def sleep(self): # 父类的实例方法
print("睡")
def hawl(self):
print("嚎")
class Cat(Base): # 继承 class 子类(父类)
def __init__(self, name, sex): # 子类的实例属性
super().__init__(name) # 使用super().调用父类的实例属性
self.sex = sex # 添加子类需要的实例属性
def climb(self):
print("Cat会爬树!!")
self.eat() #
def sleep(self): # 子类的实例方法,父类也有,同名了
# 1.完全覆盖。一点都不用父类的。
# print("cat呼呼大睡!!!")
# 2.继承使用父类的同名方法。但是在父类的基础上,再拓展内容。
super().sleep() # 使用super().调用父类实例方法
print("我使用爸爸睡觉的姿势,顺便再加了一个姿势!!")
c = Cat("英短", "母")
c.sleep()
# class Dog(Base):
# def catch_mouse(self):
# print("Dog会抓老鼠!")
#
# c = Cat()
# d = Dog()
# d.catch_mouse()
# 3.类的多态
"""
1、python有多态吗? 父类类型代表任意子类对象
父类Father:run()
子类1:run()
子类2:run()
鸟类:run()
人类/猪类 run()
函数:can_run(对象): 函数传参不限定参数类型。
对象.run()
"""
# 4.动态属性设置(反射机制)
'''
1.类定义之后,动态的给类/对象添加/删除属性
2.不确定类的属性名和属性值是什么
3.从其他地方获取hor,动态的类添加属性和值
hasattr:判断属性
getattr:获取属性
setattr:设置属性
delattr:删除属性
'''
class People: # 定义一个类
def __init__(self, name): # 初始化
self.name = name # 实例属性
p = People("xj") # 实例化
print(p.name) # 打印出来 xj
p.name = "黄花菜" # name 改成 黄花菜
print(p.name) # 打印出来 黄花菜
p.sex = "女" # 实例化之后允许这样来添加
print(p.sex) # 打印出来 女
res = hasattr(People, "name") # hasattr是判断People(类)里面是否有name这个类属性
print(res) # 返回布尔值(False)
res = hasattr(p, "name") # hasattr是判断p(对象)里面是否有name这个实例属性
print(res) # 返回布尔值(True)
# getattr:获取属性
ser = getattr(p, "name") # 获取这个属性在不在返回属性值
print(ser)
# setattr:设置属性,如果属性存在,修改属性,如果属性不存在,则增加属性
setattr(People,'king','方天画戟') # 类里不存在这个属性,添加类属性
print(People.king) # 通过类名来访问
setattr(p,'king','画戟') # 实例属性里不存在这个属性,添加实例属性
print(p.king) # 通过对象来访问
# delattr:删除属性
delattr(People,'king') # 删除了属性值,所以会报错
print(People.king) # 打印所以会报错
# 课后作业
# 1.详细总结类和对象知识点,包括:
# 类的定义
print('''****************类的定义**********************
类的定义:
定义类/实现类的格式:
class 类名(大驼峰命名方式):
属性
方法(功能(函数))
''')
# 对象的初始化
print('''****************对象的初始化**********************
对象的初始化:
1.使用初始化:魔法函数 __init__,在你创建对象的同时,会自动调用。
2.在类当中可有可无,取决于你的需求
3.实例化的同时,调用__init__ 有几个参数,在实例化的时候就要给几个参数
4.self : 是对象本身
''')
# 类属性
print('''****************类属性**********************
类属性:
1.是直接在类当中定义的,不在任何的实例方法中
2.格式为:属性名=值
3.若类属性和实例属性同名,在实例对象当中,对象名.属性名调用的是 对象自己的属性。
自己有,用自己的。
自己没有,用类的。
''')
# 实例属性
print('''****************实例属性**********************
实例属性:
1.在类的方法当中格式为:self.属性名=值
2.如果想在创建对象的同时,个性化定制对象的属性,使用实例属性,创建对象的同时,会自动调用
3.若类属性和实例属性同名,在实例对象当中,对象名.属性名调用的是 对象自己的属性。
自己有,用自己的。
自己没有,用类的。
''')
# 实例方法
print('''****************实例方法**********************
实例方法:
1.self代表对象本身,第一个参数是self
2.在实例化的对象是谁,self就是谁。
3.只能由实例对象去调用
''')
# 类方法
print('''****************类方法**********************
类方法:
1.定义:使用装饰器@classmethod。第一参数必须是当前类对象,该参数名一般约定为“cls”,
通过它来传递的属性和方法(不能传实例的属性和方法)。
2.调用:实例对象和类对象都可以调用。
3.应用场景:需要站在类的角度执行某个行为时,那么就应该定义为类方法。
''')
# 静态方法
print('''****************静态方法**********************
静态方法:
1.在类内部定义:使用装饰器@staticmethod。参数随意,参数没有“self”和"cls"参数
2.与类没有任何关联,就是一个普通函数,只不过放在类中,方便管理
3.调用:实例对象和类对象都可以调用
4.应用场景:存放逻辑代码,内部不需要引用类属性和实例属性
''')
# 继承
print('''****************继承**********************
继承:
1.继承是一种子类继承父类的一种方式,主要是继承可以减少代码的量
2.继承是类与类之间的关系,子类会继承父类的属性和方法
''')
# 重写
print('''****************重写**********************
重写:
1.是在继承后,在子类中面临父类有同名方法需要进场重写
2.完全重写父类的某个同名方法,完全覆盖。一点都不用父类的
''')
# super 函数
print('''****************super 函数**********************
super 函数:
1.继承使用父类的同名方法。但是在父类的基础上,再拓展内容。
2.语法:super().同名方法()--调用父类的同名方法
''')
# 2, 定义一个类 Dog, 包含 2 个属性:名字和年龄。
# 定义一个方法 eat 吃东西。
# 定义一个类 TeddyDog, 继承 Dog 类, Teddy 在吃东西的时候还会望着你, 定义方法 watch_you.
# 定义一个类 BabyTeddyDog, 继承 TeddyDog, BabyTeddy 吃东西不仅会望着你,还会四处转悠, 定义方法 go_around
print('***************************************第二题***************************************')
# 父类
class Dog: # 定义一个类
def __init__(self,name,age): # 初始化属性
self.name = name # 实例属性(名字)
self.age = age # 实例属性(年龄)
def eat(self): # 定义一个实例方法
print('我家{},{}岁了,在吃甜食呢'.format(self.name,self.age))
# 子类1
class TeddyDog(Dog): # 继承 class 子类(父类)
def __init__(self,name,age,watch):
super().__init__(name,age) # 使用super().调用父类的实例属性
self.watch = watch # 添加子类的实例属性(看)
def watch_you(self): # 定义一个子类的实例方法
print('我家{},{}岁了,我一动他就会两眼巴巴的望着我'.format(self.name,self.age))
def eat(self): # 定义一个实例方法同父类方法一样
super().eat() # 使用super().调用父类实例方法
print('我家{},{}岁了,在吃甜食的时候还会{},'.format(self.name,self.age,self.watch))
# 子类2
class BabyTeddyDog(TeddyDog): # 继承 class 子类(父类)
def __init__(self,name,age,watch,around):
super().__init__(name,age,watch) # 使用super().调用父类的实例属性
self.around = around # 添加子类的实例属性(走)
def go_around(self): # 定义一个子类的实例方法
print('我家{},{}岁了,喜欢{}'.format(self.name,self.age,self.around))
def eat(self): # 定义一个实例方法同父类方法一样
super().eat() # 使用super().调用父类实例方法
print('我家{},{}岁了,在吃甜食的时候还会{},还会{}'.format(self.name, self.age, self.watch,self.around))
cat = BabyTeddyDog('BabyTeddy','2','两眼巴巴的望着你','四处转悠')
cat.watch_you()
cat.go_around()
cat.eat()
# 二、选作题(不需要提交)
# 1.编写如下程序
# 编写一个工具箱类和工具类
# 工具类:需要有工具具的名称、功能描述、价格。
# 工具箱类:能够添加工具、删除工具、查看工具,并且能获取工具箱中工具的总数。
# 实例化几个工具。并在工具箱对象当中做添加/删除/查看工具操作,获取工具箱对象中有几个工具。
# 工具比如锤子、斧头、螺丝刀等工具。
print('********************************************第三题*******************************************************')
# 第一种方法
class Tools: # 定义一个工具类
def __init__(self,name,Features,price): # 初始化
self.name = name # 实例属性-名称
self.Features = Features # 实例属性-功能
self.price = price # 实例属性-价格
def __str__(self): # 返回_str__的信息
return '工具:{} ,功能:{} ,价格:{}'.format(self.name, self.Features, self.price) # 返回如下信息
hammer = Tools('锤子','敲打','50') # 锤子信息
print(hammer)
ax = Tools('斧头','砍菜','21.2') # 斧头信息
print(ax)
screwdriver = Tools('螺丝刀','拧紧','54.84') # 螺丝刀信息
print(screwdriver)
scissors = Tools('剪刀','剪短东西','64') # 剪刀信息
print(scissors)
class Toolbox: # 定义一个工具箱类
def __init__(self):
self.tools_list = [] # 空列表
def add(self,item): # 定义增加工具的方法
print('工具箱中添加工具:{}'.format(item.name))
self.tools_list.append(item.name)
def delete_tool(self,item): # 定义删除工具的方法
try:
if len(self.tools_list) > 0: # 如果工具列表的长度大于0
print('删除工具:{}'.format(item.name))
self.tools_list.remove(item.name)
else:
print('工具箱中没有这个工具')
except:
print('删除错误,没有这个工具')
return
def total_tool(self):
print('查看工具箱:',self.tools_list)
print('查看工具箱的总数:',len(self.tools_list))
my_boxs = Toolbox() #
my_boxs.delete_tool(hammer) # 查看工具箱中是否有工具
my_boxs.add(hammer) # 增加工具到工具箱
my_boxs.add(ax) # 增加工具到工具箱
my_boxs.add(screwdriver) # 增加工具到工具箱
my_boxs.delete_tool(screwdriver) # 删除工具箱中的 screwdriver
my_boxs.add(scissors) # 增加工具到工具箱
my_boxs.total_tool() # 查看工具箱和总数
print('=============================================================================================================')
# 第二种方法
class Tool:
"""
定义工具类
"""
def __init__(self, name, desc, price):
"""
构造方法
:param name: 工具名称
:param desc: 工具描述
:param price: 工具价格
:return: 无
"""
self.name, self.desc, self.price = name, desc, price
def describe_tool(self):
"""
获取工具描述信息
:return:
"""
print("\n{:*^100}".format("开始描述"))
print("名称:{0.name}\n功能:{0.desc}\n价格:{0.price}".format(self))
print("{:*^100}\n".format("结束描述"))
# print("描述工具\n名称:{}\n功能:{}\n价格:{}".format(self.name, self.desc, self.price))
def __str__(self):
return "<{}>".format(self.name)
class ToolPackage:
"""
定义工具箱类
"""
# tools 不作为参数传入,也可以作为参数传入
def __init__(self, name):
self.name = name
self.all_tools = [] # 存放工具的列表
def add(self, one_tool):
"""
添加工具到工具箱中
:param one_tool: Tool工具对象
:return:
"""
if isinstance(one_tool, Tool):
self.all_tools.append(one_tool)
print("成功添加【{}】到【{}】中!".format(one_tool.name, self.name))
else:
print("{}不是工具对象,无法添加!".format(one_tool))
def has_tool(self, one_tool):
"""
判断工具是否在工具箱中
:param one_tool: Tool工具对象或者工具名
:return: True or False
"""
if isinstance(one_tool, Tool): # 如果one_tool是工具对象
return one_tool in self.all_tools # 判断是否在工具箱中
elif isinstance(one_tool, str): # 如果是工具名,字符串
for tool_obj in self.all_tools:
if one_tool == tool_obj.name:
return True
return False
def remove(self, one_tool):
"""
删除工具
:param one_tool: Tool工具对象或者工具名称
:return:
"""
if self.has_tool(one_tool): # 如果要删除的工具存在
if isinstance(one_tool, Tool): # 如果one_tool为Tool工具对象
self.all_tools.remove(one_tool)
else: # 为工具名称字符串
for index, item in enumerate(self.all_tools):
if one_tool == item.name: # 当前遍历的工具名为one_tool
self.all_tools.pop(index)
break # 删除之后,退出循环
else:
print("工具不存在,无法删除!")
def search(self, one_tool):
"""
根据工具对象或者工具名称查找工具
:param one_tool: Tool工具对象或者工具名称
:return:
"""
if self.has_tool(one_tool):
if isinstance(one_tool, Tool): # 如果one_tool为Tool工具对象
one_tool.describe_tool()
else: # 为工具名称字符串
for index, item in enumerate(self.all_tools):
if one_tool == item.name: # 当前遍历的工具名为one_tool
self.all_tools[index].describe_tool()
break # 找到工具之后,退出循环
else:
print("工具不存在!")
def get_tools_num(self):
print("{}里的工具总数为:{}".format(self.name, len(self.all_tools)))
# return len(self.all_tools)
hammer = Tool("锤子", "由金属或木头等材料做成的头和与之垂直的柄构成的敲击工具。", 25.2)
screwdriver = Tool("螺丝刀", "是一种用来拧转螺丝以使其就位的工具,通常有一个薄楔形头,可插入螺丝钉头的槽缝或凹口内。", 5)
saw = Tool("锯子", "用来把木料或者其他需要加工的物品锯断或锯割开的工具。", 12)
electric_drill = Tool("电钻", "利用电做动力的钻孔机具。", 278)
family_tool_package = ToolPackage("家用工具箱")
# 将工具添加到工具箱中
family_tool_package.add(hammer)
family_tool_package.add(screwdriver)
family_tool_package.add(saw)
family_tool_package.add(electric_drill)
family_tool_package.remove('锤子')
family_tool_package.get_tools_num()
2020年6月8日---python类的继承,多态和动态属性设置
最新推荐文章于 2023-07-02 09:49:28 发布