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

被折叠的 条评论
为什么被折叠?



