当前位置: 首页 > article >正文

Day21笔记-封装继承

复习面向对象基础语法

# 定义类
class Person():
    # 类属性
    num = 10
    # 限制对象属性的动态绑定
    __slots__ = ('name','age','hobby')
    # 定义实例属性
    def __init__(self,name,age,hobby):
        self.name = name
        self.age = age
        self.hobby = hobby
    # 类中的函数
    # 实例函数
    def func1(self,a,b):
        print('1111',a,b)
    # 类函数
    @classmethod
    def func2(cls,a):
        print('22222',a)
    # 静态函数
    @staticmethod
    def func3(num1,num2):
        print('333333',num1,num2)
​
# 创建对象/实例化对象/类的实例化
p = Person('aaa',10,'dance')
# 访问属性
print(Person.num)
print(p.num)
print(p.name,p.age,p.hobby)
# 调用函数
p.func1(5,8)
​
Person.func2(34)
p.func2(34)
​
Person.func3(45,7)
p.func3(45,8)

Day20作业

'''
1.设计两个类:
    a. 一个点Pointer类,属性包括x,y坐标。
    b. 一个Rectangle类(矩形),属性有左上角坐标,宽,高
        方法:1. 计算矩形的面积;2. 判断点是否在矩形内
    c.实例化一个点对象,一个正方形对象,输出矩形的面积,输出点是否在矩形
'''
class Pointer():
    __slots__ = ('x','y')
    def __init__(self,x,y):
        self.x = x
        self.y = y
class Rectangle():
    __slots__ =  ('left_top_point','width','height')
    # left_top_point:表示一个点Pointer的对象
    def __init__(self,left_top_point,width,height):
        self.left_top_point = left_top_point
        self.width = width
        self.height = height
    def area(self):
        return self.width * self.height
    def judge(self,point):
        # self:矩形对象  point:点的对象
        # x轴
        r0 = self.left_top_point.x < point.x < self.left_top_point.x + self.width
        # y轴
        r1 = self.left_top_point.y - self.height < point.y < self.left_top_point.y
        return r0 and r1
​
# 创建表示左上角点的对象
left_top_point = Pointer(2,19)
# 创建矩形对象
rect = Rectangle(left_top_point,10,10)
print(f'矩形的面积为:{rect.area()}')
​
# 创建一个某点的对象
point = Pointer(54,10)
print(rect.judge(point))

一、面向对象三大特征

1.封装

面向对象的三大特征:封装,继承和多态

广义的封装:函数的定义和类的定义

狭义的封装:一个类中的某些属性,如果不希望被外界直接访问,则可以将该属性私有化,该属性只能在当前类中被直接访问,如果在类的外面需要访问【获取或修改】,则可以通过暴露给外界的函数间接访问

封装的本质:将类中的属性进行私有化

【面试题】解释下面不同形式的变量出现在类中的意义
a:普通属性,也被称为公开属性,在类的外面可以直接访问             ****
_a:在类的外面可以直接访问,但是不建议使用,容易和私有属性混淆
__a:私有属性,只能在类的内部被直接访问。类的外面可以通过暴露给外界的函数访问    *****
__a__:在类的外面可以直接访问,但是不建议使用,因为系统属性和魔术方法都是这种形式的命名,
    如:__slots__  __init__  __new__  __del__,__name__,__add__,__sub__,__mul__等
# 封装的本质:将类中的属性进行私有化
'''
公开属性:可以在当前类之外的任何地方直接访问的属性
私有属性:只能在当前类中被直接访问的属性
'''
​
# 1.属性未被私有化
class Animal1():
    __slots__ = ('name','age')
    def __init__(self,name,age):
        self.name = name
        self.age = age
    def show(self):
        print(self.name,self.age)
​
a1 = Animal1('大黄',3)
print(a1.name,a1.age)
a1.show()
​
a1.name = '小白'
​
print('*' * 30)
​
# 2.属性私有化     ******
# 作用:为了数据的安全性,不希望当前类以外的其他地方访问该属性
class Animal2():
    __slots__ = ('__name','__age')
    def __init__(self,name,age):
        # 当给对象动态绑定属性的时候,如果在属性名的前面添加两个下划线,则表示该属性被私有化了
        self.__name = name
        self.__age = age
    def show(self):
        print(self.__name,self.__age)
​
a2 = Animal2('大黄',3)
a2.show()
# print(a2.__name,a2.__age)  # AttributeError: 'Animal2' object has no attribute '__name'
​
print('*' * 30)
​
# 3.暴露给外界访问的函数
# a.
class Animal3():
    __slots__ = ('__name','__age')
    def __init__(self,name,age):
        self.__name = name
        self.__age = age
    def show(self):
        print(self.__name,self.__age)
​
    # 获取值
    def func1(self):
        return self.__name
    # 修改值
    def func2(self,a):
        self.__name = a
​
    def func3(self):
        return self.__age
    def func4(self,b):
        if b < 0:
            b = -b
        self.__age = b
​
a3 = Animal3('大黄',3)
a3.show()
print(a3.func1())
a3.func2('旺财')
print(a3.func1())
​
print(a3.func3())
a3.func4(-45)
print(a3.func3())
​
print('*' * 30)
​
# b.装饰器实现
class Animal3():
    __slots__ = ('__name','__age')
    def __init__(self,name,age):
        self.__name = name
        self.__age = age
    def show(self):
        print(self.__name,self.__age)
​
    # 获取值
    '''
    @property用来装饰获取私有化属性的函数,将该函数处理成属性使用
    '''
    @property
    def name(self):
        return self.__name
    # 修改值
    '''
     @xxx.setter用来装饰修改私有化属性的函数,将该函数处理成属性使用
     xxx:一定得是被@property装饰的函数名
     
     一般情况下,func1和func2这两处的函数名不会随意命名,建议命名为被私有化的属性的属性名
    '''
    @name.setter
    def name(self,name):
        self.__name = name
​
    @property
    def age(self):
        return self.__age
    @age.setter
    def age(self,age):
        if age < 0:
            age = -age
        self.age  = age
​
a3 = Animal3('大黄',3)
a3.show()
print(a3.name)  # 大黄,调用的是被@property装饰的函数,a3.func1获取的是原func1函数的返回值
# print(a3.func1())   # TypeError: 'str' object is not callable
​
# print(a3.func2)
a3.name = '旺财'   # 调用的是被@xxx.setter装饰的函数
# a3.func2('旺财')     # TypeError: 'str' object is not callable
print(a3.name)
2.继承

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

​ 被抽取出来的类——父类【father class】 超类【super class】 基类【base class】

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

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

简单来说,

一个子类只有一个父类,被称为单继承

一个子类有多个父类,被称为多继承

语法:
class 子类类名(父类类名):
    类体
class 子类类名(父类类名1,父类类名2.......):
    类体

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

​
# 1.单继承
# 在Python中,object是所有类的根类
# 父类
class Person():  # 在此处的()中什么都不写,默认的父类仍然是object
    def __init__(self,name,age):
        self.name = name
        self.age = age
    def show(self):
        print('showing')
​
# 子类
class Worker(Person):
    pass
# a.当子类中未定义__init__,则创建子类对象,默认会调用父类中的构造函数,所以要注意和父类中的__init__的参数匹配【子类继承了父类中的__init__】
# w = Worker()  # TypeError: __init__() missing 2 required positional arguments: 'name' and 'age'
w = Worker('小王',20)
print(w.name,w.age)
w.show()
​
class Student(Person):
    def study(self):
        print('study~~~~')
stu = Student('小明',19)
print(stu.name,stu.age)
stu.show()
stu.study()
​
# b.如果子类中定义了__init__函数,则创建子类对象,优先会调用子类中的__init__
class Doctor(Person):
    def __init__(self,name,age,kind):
        # 在子类的__init__中调用父类的__init__
        # 方式一:super(当前类,self).__init__(参数列表)
        # super(Doctor,self).__init__(name,age)
        # 方式二:super().__init__(参数列表)
        # super().__init__(name,age)
        # 方式三:父类类名.__init__(self,参数列表)
        Person.__init__(self,name,age)
​
        self.kind = kind
    def assist(self):
        print('assist~~~~')
​
# d = Doctor() # TypeError: __init__() missing 3 required positional arguments: 'name', 'age', and 'kind'
d = Doctor('王大夫',45,'外科')
print(d.kind)
# 当子类对象需要访问父类中提取出来的属性时,无法访问,解决方案:在子类的__init__中调用父类中的__init__
print(d.name,d.age)  # AttributeError: 'Doctor' object has no attribute 'name'
d.show()
d.assist()
​
# 2.多继承
# a
class Flyable():
    def fly(self):
        print('flying')
class Runable():
    def run(self):
        print('running')
class Bird(Flyable,Runable):
    pass
​
bird = Bird()
bird.fly()
bird.run()
​
# b.
# class FatherClass1():
#     def __init__(self,num):
#         self.num = num
#     def func(self):
#         print('11111')
#
# class FatherClass2():
#     def __init__(self,value):
#         self.value = value
#     def func(self):
#         print('2222')
#
# class SubClass(FatherClass1,FatherClass2):
#     pass
​
# 当一个类有多个父类,且子类中未定义构造函数,则创建子类对象,默认情况下调用的时父类列表中第一个父类中的__init__,多个父类中出现重名的函数也是这种原理
# sc = SubClass(45)
# sc.func()
​
# c
class FatherClass1():
    def __init__(self,num):
        self.num = num
    def func(self):
        print('11111')
​
class FatherClass2():
    def __init__(self,value):
        self.value = value
    def func(self):
        print('2222')
​
class SubClass(FatherClass1,FatherClass2):
    def __init__(self,num,value,a,b):
        # 在多继承中,在子类的__init__中调用父类的__init__,只能使用方式三,可以区分父类
        FatherClass1.__init__(self, num)
        FatherClass2.__init__(self, value)
        self.a = a
        self.b = b
​
sc = SubClass(34,6,7,8)
print(sc.a,sc.b)
print(sc.num,sc.value)


http://www.kler.cn/a/307084.html

相关文章:

  • uni-app表单⑪
  • 【Linux】基础IO及文件描述符相关内容详细梳理
  • [ Linux 命令基础 3 ] Linux 命令详解-文件和目录管理命令
  • 设计模式-七个基本原则之一-单一职责原则 + SpringBoot案例
  • 力扣 LeetCode 977. 有序数组的平方(Day1:数组)
  • crond 任务调度 (Linux相关指令:crontab)
  • MySQL练手题--体育馆的人流量(困难)
  • [数据集][目标检测]疟疾恶性疟原虫物种目标检测数据集VOC+YOLO格式948张1类别
  • 大学生看过来,必备4款写论文AI写作网站先稿后付
  • 《论负载均衡技术在Web系统中的应用》写作框架,软考高级系统架构设计师
  • Python网络爬虫:如何高效获取网络数据
  • vue3 透传 Attributes
  • TDengine 签约前晨汽车,解锁智能出行的无限潜力
  • 【计算机网络】网络通信中的端口号
  • Android SPN/PLMN 显示逻辑简介
  • SpringBoot框架Web开发
  • 第十一章 【后端】商品分类管理微服务(11.1)——创建父工程
  • Python 实现 LM 算法(Levenberg-Marquardt)
  • PCIe进阶之TL:First/Last DW Byte Enables Rules Traffic Class Field
  • Linux命令分享 四 (ubuntu 16.04)(vi操作文件)
  • 第十七节:学习Hutool上传文件(自学Spring boot 3.x的第四天)
  • C++比大小游戏
  • 虚幻引擎Gameplay探索 Actor 之间的高效通信与交互技巧一
  • 鹏哥C语言39---goto语句(关机程序 )
  • UE4_后期处理六—复古电视效果
  • 【HCIA-Datacom】华为VRP系统