day14笔记 封装 (私有化) 继承 多台

本文深入讲解面向对象编程的核心概念,包括封装、继承、多态,以及它们在代码设计中的应用。通过具体示例,展示了如何利用这些特性简化代码、提高可维护性和扩展性。

作业讲解

"""
2.设计两个类:

	- 一个点Pointer类,属性包括x,y坐标。

	- 一个Rectangle类(矩形),属性有左上角坐标,宽,高

				方法:1. 计算矩形的面积;2. 判断点是否在矩形内

 实例化一个点对象,一个正方形对象,输出矩形的面积,输出点是否在矩形内
"""
class Pointer():
    def __init__(self,x,y):
        self.x = x
        self.y = y

class Rectangle():
    def __init__(self,left_top_point,width,height):
        """
        :param left_top_point: 左上角坐标,其实是一个点的对象
        :param width:
        :param height:
        """
        self.left_top_point = left_top_point
        self.width = width
        self.height = height

    #1. 计算矩形的面积;
    def area(self):
        return self.width * self.height

    #2. 判断点是否在矩形内
    def judge(self,other):
        """
        :param other: 其他任意一个点的对象
        :return:
        """
        """
        分析:
            横向【x】: left_top_point的x坐标  <  other的x坐标  < left_top_point的x坐标 + width
            纵向【y】: left_top_point的y坐标 - height  < other的y坐标  <  left_top_point的y坐标
        """
        r0 = self.left_top_point.x <= other.x <= self.left_top_point.x + self.width
        r1 = self.left_top_point.y - self.height <= other.y <= self.left_top_point.y

        return r0 and r1

#创建对象
p1 = Pointer(4,6)  #左上角点
rect = Rectangle(p1,10,10)
print("面积是:%s" % (rect.area()))

p2 = Pointer(7,10)  #其他点
result = rect.judge(p2)
if result:
    print("在矩形内")
else:
    print("不在")
"""
3.家具类(HouseItem) 有 名字 和 占地面积属性,其中

- 席梦思(bed) 占地 4 平米
- 衣柜(chest) 占地 2 平米
- 餐桌(table) 占地 1.5 平米

房子类(House) 有 户型、总面积 、剩余面积 和 家具名称列表 属性

- 新房子没有任何的家具
- 将 家具的名称 追加到 家具名称列表 中
- 判断 家具的面积 是否 超过剩余面积,如果超过,提示不能添加这件家具

a.将以上三件 家具对象 添加 到 房子对象 中

b.打印房子时,要求输出:户型、总面积、剩余面积、家具名称列表
"""
class HouseItem():
    def __init__(self,name,space):
        self.name = name
        self.space = space

class House():
    def __init__(self,type,total_area,free_area,itemlist=None):
        self.type = type
        self.total_area = total_area
        self.free_area = free_area

        if itemlist is None:
            itemlist = []
        self.itemlist = itemlist

    def add_item(self,item):
        """
        :param item: 需要被添加到房子对象中的家具
        :return:
        """
        if item.space <= self.free_area:
            self.itemlist.append(item.name)

            #计算房子的剩余面积
            self.free_area -= item.space

            print("家具%s添加成功,户型为%s的房子总面积为:%s,此时剩余面积为:%s,"
                  "家具列表:%s" % (item.name,self.type,self.total_area,self.free_area,self.itemlist))
        else:
            print("剩余面积不足,无法添加家具")

#创建家具的对象
bed = HouseItem("席梦思",4)
chest = HouseItem("衣柜",2)
table = HouseItem("桌子",1.5)

#创建房子的对象
house= House("三室一厅",100,90)

#让房子执行自己的行为
house.add_item(bed)
house.add_item(bed)
house.add_item(bed)
house.add_item(chest)

一、封装

1.私有属性说明
#1.
class Animal():
 def __init__(self,type):
     self.__type = type

 def show(self):
     print(self.__type)

 #注意:一个私有化属性----》一对函数
 @property
 def type(self):
     return self.__type

 @type.setter
 def type(self, type):
     # if type == "小狗":
     #     type = "二哈"
     self.__type = type

a = Animal("小狗")
# print(a.type)
# a.type = "小猫"

#2.问题:@property和@xxx.setter必须成对出现吗?---->不是,可以单独使用
#@property能不能单独使用?

#结论:
# 1.@property可以单独使用,但是@xxx.setter不能单独使用,xxx来自于被@property修饰的函数
# 2.@property修饰函数,作用是将函数当做属性使用,实际上获取函数的返回值

"""
面试题:阅读下面的代码,是否正确,如果正确,结果是什么?
class Person():
 @property
 def show(self):
     print("showing")
     
p = Person()
p.show()
"""
class Person():
 @property
 def show(self):
     print("showing")
     return "hello"

p = Person()
#p.show()
print(p.show)
2.私有函数
#1.基本使用
class Person():
 def func1(self):
     print("11111")

 def func2(self):
     print("22222")
     #注意1:私有化函数在类内部可以随意调用
     #注意2:类中的函数之间相互调用,格式:self.函数名(参数列表)
     self.__show()
     self.func1()

 def __show(self):
     print("showing")

p = Person()
p.func1()
p.func2()
#私有化的函数在类外面无法直接调用
#p.__show()

#2.练习
"""
有一个银行账户类 Account, 包括名字 , 余额等属性,方法有存钱、取钱、查询余额的操作。要求:
		1.在存钱时,注意存款数据的格式

		2.取钱时,要判断余额是否充足,余额不够的时候要提示余额不足
"""
class Account():
 def __init__(self,name,balance):
     self.name = name
     self.__balance = balance

 #私有化函数:校验工作,不希望在外界被访问,只是内部的行为
 def __iscorrect(self,num):
     if isinstance(num,int) and num > 0:
         return True
     return False

 def save_money(self,num):
     if self.__iscorrect(num):
         self.__balance += num
         print("存入成功,目前余额为:%s" % (self.__balance))

 def get_money(self,num):
     if self.__iscorrect(num):
         if num <= self.__balance:
             self.__balance -= num
             print("取钱成功,目前余额为:%s" % (self.__balance))
         else:
             print("余额不足,无法实现取款")

 def search(self):
     print("当前余额为:%s" % (self.__balance))

 @property
 def balance(self):
     return self.__balance
 @balance.setter
 def balance(self,balance):
     self.__balance = balance

a = Account("jack",1000000000000)
a.get_money(1000)
a.save_money(500)
a.search()


#3.练习
"""
1.定义一个Time类,对象属性包括:时、分、秒;通过init初始化属性。
	对象方法有:
		    add_hour(self,num)   把小时加num
 		    add_minute(self,num) 把分钟加num
                 add_second(self,num) 把秒数加num
                定义show方法,打印格式化的时间字符串:"04:16:09"
 注意:要考虑分秒的上限  小时不限上限
"""
class Time():
 def __init__(self,hour,minutes,seconds):
     self.hour = hour
     self.minutes = minutes
     self.seconds = seconds
     #校验初始值
     self.__isminutes()
     self.__isseconds()

 #定义一个函数,用于校验分秒的数据的正确性,不希望在外界被访问,只是内部的行为
 def __isminutes(self):
     if self.minutes >= 60:
         hour = self.minutes // 60
         self.minutes %= 60
         self.add_hour(hour)

 def __isseconds(self):
     if self.seconds >= 60:
         minutes = self.seconds // 60
         self.seconds %= 60
         self.add_minute(minutes)

 #添加
 def add_hour(self,num):
     self.hour += num

 def add_minute(self,num):
     self.minutes += num
     self.__isminutes()

 def add_second(self,num):
     self.seconds += num
     self.__isseconds()

 def show(self):
     print("%.2d:%.2d:%.2d" % (self.hour,self.minutes,self.seconds))

time = Time(30,1,100)
time.add_hour(10)
time.show()

二、继承

1.概念

如果两个或者两个以上的类具有相同的属性和方法,我们可以抽取一个类出来,在抽取出来的类中声明各个类公共的部分

​ 被抽取出来的类——父类 超类 基类

​ 两个或两个以上的类——子类 派生类

​ 他们之间的关系——子类 继承自 父类 或者 父类 派生了 子类

2.单继承
2.1基本使用

简单来说,一个子类只能有一个父类,被称为单继承

语法:

class 子类类名(父类类名):

​ 类体

注意:object是Python中所有类的根类

#1.
"""
class Student():
 def __init__(self,name,subject):
     self.name = name
     self.subject = subject

 def eat(self):
     print("eating")
 def study(self):
     print("studying")

class Doctor():
 def __init__(self, name):
     self.name = name
 def eat(self):
     print("eating")

class Worker():
 def __init__(self, name, kind):
     self.name = name
     self.kind = kind

 def eat(self):
     print("eating")
 def work(self):
     print("working")

class Teacher():
 def eat(self):
     print("eating")
 def teach(self):
     print("teaching")
"""

#2.
#a.将多个类中公共的属性和方法提取出来【注意:不要为了继承而继承,要结合实际情况】,形成一个父类
#父类
#b.如果一个类的父类不明确,则继承自object
class Person(object):
 def __init__(self,name):
     print("父类Person中的init被调用")
     self.name = name

 def eat(self):
     print("eating")

#子类
#c.要实现继承,则必须要指明父类,语法:class 子类类名(父类类名)
class Doctor(Person):
 pass

class Teacher(Person):
 def teach(self):
     print("teaching")

class Student(Person):
 def __init__(self, age, subject):
     print("子类Student的init被调用了")
     self.age = age
     self.subject = subject
 def study(self):
     print("studying")

class Worker(Person):
 def __init__(self, name, kind):
     self.kind = kind
     # 注意4:如果子类对象需要访问父类中的属性,则需要在子类的构造函数中调用父类的构造函数
     # 方式一:super(当前类,self).__init__(属性列表)
     # super(Worker,self).__init__(name)

     # 方式二:父类名.__init__(self,属性列表)   ******
     # Person.__init__(self,name)

     # 方式三:super().__init__(属性列表)
     super().__init__(name)

 def work(self):
     print("working")

#3.子类对象和父类之间的关系
#3.1 子类中未定义任何内容:Doctor
#注意1:如果子类中未定义构造函数,则创建对象的时候默认调用的是父类的构造函数【继承了父类的构造函数】
d = Doctor("张医生")
#注意2:子类对象可以直接调用父类中未被私有化的函数【当前类的对象都无法访问私有化函数】
d.eat()
print(d.name)

print("=" * 30)

#3.2 子类中未定义构造函数,但是定义了成员函数
t = Teacher("王老师")
t.eat()
t.teach()
print(t.name)

print("=" * 30)

#3.3 子类中定义构造函数,但是不需要使用父类中的成员变量
#注意3:如果子类中出现了和父类重名的函数,则子类对象优先调用子类中的函数【重写/覆盖:override】
s = Student(10,"语文")
s.study()
s.eat()
print(s.age,s.subject)

print("=" * 30)

#3.4 子类中定义构造函数,但是需要使用父类中的成员变量
w = Worker("张三","环卫工人")
w.eat()
w.work()

print(w.kind)
print(w.name) #AttributeError: 'Worker' object has no attribute 'name'
2.2继承的好处
class Animal(object):
 def __init__(self,name,age,color,kind):
     self.name = name
     self.age = age
     self.color = color
     self.kind = kind

class Cat(Animal):
 def __init__(self,height,name,age,color,kind):
     self.height = height
     Animal.__init__(self,name,age,color,kind)

class Dog(Animal):
 pass

"""
继承的特点:
 a.子类对象可以直接访问父类中未被私有化的属性
 b.子类对象可以直接调用父类中未被私有化的函数
 c.父类对象不能访问子类中特有的属性和方法
 
优点:
 a.可以简化代码,减少冗余
 b.提高代码的可维护性
 c.提高代码的扩展性
 d.提高代码的复用性
 e.继承是多态的前提
 
缺点:
 a.在继承关系中,耦合性相对较高【如果修改父类,子类也会随着发生改变】
"""
2.3继承中的__slots__
#__slots__:通过__slots__限制的属性只能对当前类实例起作用,对继承的子类不起作用

class Student(object):
 __slots__ = ("name","age")


class SmallStudent(Student):
 __slots__ = ("name", "age")

s = SmallStudent()
s.score = 66
print(s.score)
3.多继承

顾名思义,多继承就是一个子类可以有多个父类,比如:一个孩子有一个父亲,一个母亲

语法:

class 子类(父类1, 父类2, 父类3):
类体

#父类
class Father(object):
 def __init__(self,money):
     self.money = money
 def play(self):
     print("play")

 def func(self):
     print("Father~~~~~func")

class Mother(object):
 def __init__(self, facevalue):
     self.facevalue = facevalue
 def eat(self):
     print("eat")

 def func(self):
     print("Mother~~~~~func")

#子类
#语法:class 子类类名(父类1,父类2,,,,)
class Child(Father,Mother):
 def __init__(self,money,facevalue,hobby):
     self.hobby = hobby
     #调用父类的构造函数,注意:父类类名.__init__(self,属性列表)
     Mother.__init__(self,facevalue)
     Father.__init__(self,money)

 def func(self):
     print("子类~~~~~func")

     #注意:在子类中出现了和父类重名的函数,如果想要使用父类中的功能,则调用的方式和调用init的方式相同
     Mother.func(self)
     Father.func(self)

c = Child(100,80,"手游")
print(c.hobby)
print(c.facevalue)
print(c.money)

c.play()
c.eat()

#注意:当多个父类中出现重名的函数的时候,子类对象调用函数的时候,取决于父类列表中谁出现在最前面
c.func()
4.重写
#重写:在继承关系中,如果父类中的函数实现的功能满足不了子类的使用,则可以在子类中实现重写

class Animal(object):
 def show(self):
     print("父类")

class Cat(Animal):
 pass

class Dog(Animal):
 pass

class Tiger(Animal):
 pass

class Bird(Animal):
 #注意:实际情况下,只要子类中出现和父类重名的函数则可以认为是重写
 #但是,一般情况下,子类中函数的声明部分和父类中保持一致
 def show(self,num):
     print("子类")

b = Bird()
b.show(10)

三、多态

一种事物的多种体现形式,举例:动物有很多种

定义时的类型和运行时的类型不一样,也就是定义时并不确定要调用的是哪个方法,只有运行的时候才能确定调用的是哪个

注意:继承是多态的前提

"""
【面试题】面向对象的三大特征的含义
封装:这是定义类的准则,根据多个对象的特点,将相同的属性和行为抽出出来形成一个类,
  还可以进行属性或者函数的私有化
继承:这是设计类的技巧,父类和子类,主要体现在代码的重用,不需要大量的编写重复代码
多态:不同的子类调用相同的父类方法,产生不同的执行结果,可以增加代码的外部灵活度,多态的前提是继承
 这是一种调用方法的技巧,不会影响到类的内部设计
"""
#1.基本使用
"""
class Thing(object):
 pass
class Animal(Thing):
 pass
class Dog(Animal):
 pass

d = Dog()
print(isinstance(d,Dog))
print(isinstance(d,Animal))
print(isinstance(d,Thing))
"""

#2.多态的应用
"""
调用灵活,有了多态,更容易编写出通用的代码,以适应需求的不断变化,可维护性和可扩展性都会提高
"""
#需求:人饲养动物
class Person(object):
 # def feedcat(self,cat):
 #     cat.eat()
 # def feeddog(self,dog):
 #     dog.eat()

 def feedanimal(self,ani):
     print("动物类型:",type(ani))
     ani.eat()


class Animal(object):
 def __init__(self,name):
     self.name = name

 def eat(self):
     print(self.name + "eating")

class Dog(Animal):
 def __init__(self,name):
     super().__init__(name)

class Cat(Animal):
 def __init__(self,name):
     super().__init__(name)

class Tiger(Animal):
 def __init__(self,name):
     super().__init__(name)

class Elephant(Animal):
 def __init__(self,name):
     super().__init__(name)

class Pig(Animal):
 def __init__(self,name):
     super().__init__(name)

class Lion(Animal):
 def __init__(self,name):
     super().__init__(name)


p = Person()

c = Cat("小白")
p.feedanimal(c)

d = Dog("旺财")
p.feedanimal(d)

l = Lion("狮王")
p.feedanimal(l)

四、其他

1.内置属性
#1.__slots__:显示对象属性的动态绑定

#2.__doc__:表示类的描述信息【获取类中的文档注释,文档注释指的是多行注释】
class Foo(object):
 """
 hellohello
 """
 def func(self):
     pass

print(Foo.__doc__)     #hellohello
f = Foo()
print(f.__doc__)   #hellohello


#3.__dict__
class Person(object):
 #类属性
 num = 10

 def __init__(self,name):
     #实例属性【对象属性】
     self.name = name

 def func(self):
     pass

#类名.__dict__ :获取类中的内容,包括类属性和方法
print(Person.__dict__)

#对象.__dict :获取对象的内容,包括对象的属性
p = Person("aaa")
print(p.__dict__)  #{'name': 'aaa'}


#4.__module__:获取当前操作的对象在哪个模块
#注意1:如果被操作的对象在当前模块,则获取的结果为 __main__
print(p.__module__)  #__main__

#注意2:如果被操作的对象在其他模块,则获取的结果为  模块名称
from testmodule import  p1
print(p1.__module__)

#5.__class__获取当前对象的类型【获取当前操作的对象的类是什么】
print(p.__class__)  #<class '__main__.Person'>
print(type(p))   #<class '__main__.Person'>
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值