2020年6月8日---python类的继承,多态和动态属性设置

# ================================
# -*- 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()

在这里插入图片描述

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值