day18面向对象续

面向对象

继承

  1. 什么是继承

    • 子类直接拥有父类的属性和方法的过程就是继承
    • 子类:继承者
    • 父类:被继承着,父类又叫超类
  2. 怎么继承

    class 子类(父类):
    pass

    注意:

    • 如果定义类的时候没有添加父类,默认继承Python的基类object

            -  同一个子类可以同时继承多个父类: class 子类(父类1, 父类2, 父类3,...)
      

    Python子类可以继承父类所有的属性和方法

    class Person(object):
        num = 61
    
        def __init__(self):
            self.name = '小红'
            self.age = 18
            self.gender = '女'
    
        def eat(self, food):
            print(f'{self.name}正在吃{food}')
    
        @classmethod
        def show_num(cls):
            print('人数:', cls.num)
    
        @staticmethod
        def info():
            print('人类保护环境!')
    
    
    class Student(Person):
        pass
    
    
    stu1 = Student()
    print(stu1.name, stu1.age, stu1.gender)
    
    print(stu1.num)
    stu1.eat('面')
    stu1.info()
    

重写

  1. 在子类中添加属性和方法

    1. 添加类属性:直接在子类中定义新的类属性
    2. 添加方法:直接在子类中定义新的方法
      在子类中添加方法的时候可以对父类方法进行重写
      在子类中可以通过 super().方法的形式来调用父类中的方法。(注意:不能在静态方法中使用super()调用父类的方法)

    总结:super的用法
    可以通过super在子类中调用父类的方法
    super().方法() - 直接调用当前类的父类的指定方法
    super(类, 对象).方法() - 调用指定类的父类的指定方法(要求对象必须是前面的类的对象)

    1. 添加对象属性方法
      在子类的_ _ init _ _方法中通过super()去调用父类的 _ _ init _ _
class A:
    x = 100

    @staticmethod
    def fun1():
        print('A')

    @classmethod
    def funa(cls):
        print('A1')


class B(A):
    y = 20

    @classmethod
    def fun2(cls):
        print('B')

    @staticmethod
    def fun1():
        print('BB')

    @classmethod
    def funa(cls):
        super().funa()
        # cls.__base__.funa()
        print('B2')

    @staticmethod
    def fun3():
        # super().fun1()  # 报错
        # super(B, B()).fun1()
        print('B的静态方法')


class C(B):
    pass


print(A.x)  # 100
print(B.x)  # 100
print(C.x)  # 100

# print(A.y)  # 报错
print(B.y)  # 20
print(C.y)  # 20

B.fun1()    # BB
A.fun1()    # A

B.funa()    # A1 B2


class Animal:
    def __init__(self, age=18, sex='雌'):
        self.age = age
        self.sex = sex


class Cat(Animal):
    def __init__(self, color='白', price=2000):
        super().__init__(20, '雄')
        self.color = color
        self.price = price


c1 = Cat()
print(c1.color, c1.age, c1.sex)  # 白 20 雄

对象属性的添加

class A:
    def __init__(self, a, b=10):
        self.a = a
        self.b = b
        self.c = 0


class B(A):
    def __init__(self, d, a):
        # d = 100, a = 10
        # super().__init__(100)
        super().__init__(a)  # A:__init__(200)
        self.d = d


bb = B(100, 200)    # B:__init__(100,200)
print(bb.a, bb.b, bb.c, bb.d)  # 200 10 0 100

练习:
创建一个人类有属性:姓名、年龄、性别,要求创建人的对象的时候姓名和年龄必须赋值,性别可以赋值也可以不赋(默认是男)
创建学生类有属性:姓名、年龄、性别、学号、学分和电话,要求创建学生对象的时候,姓名和电话必须赋值。
年龄和性别可以赋值也可以不赋(默认是18和年),学分和学号创建的时候不能赋值,默认值分别是’000’和0

class Person:
    def __init__(self, name, age, sex='男'):
        self.name = name
        self.age = age
        self.sex = sex


class Student(Person):
    def __init__(self, name, tel, age=18, sex='男'):
        super().__init__(name, age, sex)
        self.credit = '000'
        self.num = 0
        self.tel = tel


stu1 = Student('小明', '110')
print(f'<{str(stu1.__dict__)[1:-1]}>')

多继承

多继承的时候子类可以继承所有父类的类属性和方法,但是只能继承第一个父亲的对象属性。

class Animal:
    num = 25

    def __init__(self):
        self.age = 0
        self.sex = '雌'

    @classmethod
    def show(cls):
        print('数量:', cls.num)


class Fly:
    name = '飞行器'

    def __init__(self):
        self.height = 100
        self.time = 3

    @staticmethod
    def message():
        print('飞行器')


class Bird(Animal, Fly):
    pass


print(Bird.num, Bird.name)  # 25 飞行器

Bird.show()     # 数量: 25
Bird.message()  # 飞行器

b = Bird()
print(b.age, b.sex)         # 0 雌
# print(b.height, b.time)     # 报错

私有化

访问权限(编程常识):

  • 公开的(public):在类的内部可以使用、类的外部也可以使用还可以被继承(Python中所有的属性和方法都是公开)

  • 保护的(protect):在类的内部可以使用、可以被继承

  • 私有的(private):在类的内部可以使用

    Python的私有化
    方法:在属性名或者方法名前加_ _ 就可以让属性或者方法变成私有的
    原理:假的私有化;在_ _ 开头的名字前加’_类名’

    class A:
        num = 100
        __x = 200  # __x是私有的
    
        def __init__(self):
            self.name = '小明'
            self.__age = 18     # __age是私有的
    
        def info(self):
            print(self.__age)
    
        @classmethod
        def show(cls):
            print(cls.num, cls.__x)
    
    
    print(A.num)    # 100
    A.show()        # 100 200
    
    # print(A.__x)  # 无法使用
    
    a = A()
    print(a.name)   # 小明
    # print(a.__age)  # 无法使用
    a.info()        # 18
    

拷贝

  • 浅拷贝和深拷贝的区别:

    1)不管是浅拷贝还是深拷贝都是赋值被拷贝的对象产生一个新的对象,然后用新对象来赋值
    2)如果被拷贝的对象中有子对象,浅拷贝直接赋值被拷贝对象的子对象,深拷贝会拷贝被拷贝对象的子对象

    class Dog:
        def __init__(self):
            self.name = '旺财'
            self.sex = '公'
    
        def __repr__(self):
            return f'<{str(self.__dict__)[1:-1]}, id:{id(self)}>'
    
    
    class Person:
        def __init__(self, name, age=18, sex='男'):
            self.name = name
            self.age = age
            self.sex = sex
            self.dog = Dog()
    
        def __repr__(self):
            return f'<{str(self.__dict__)[1:-1]}, id:{id(self)}>'
    
    
    p1 = Person('小明', 20, '男')
    p2 = p1             # 直接赋值,将p1中的地址赋值给p2
    p3 = copy(p1)       # 浅拷贝,复制p1产生一个新的对象,用新对象给p3赋值
    p4 = deepcopy(p1)   # 深拷贝,复制p1产生一个新的对象,用新对象给p4赋值
    print('原数据:', p1)
    print('直接赋值:', p2)
    print('浅拷贝:', p3)
    print('深拷贝:', p4)
    
    print('===============')
    
    p1.name = '小花'
    p1.dog.sex = '母'
    print('原数据:', p1)
    print('直接赋值:', p2)
    print('浅拷贝:', p3)
    print('深拷贝:', p4)
    
    # 练习:
    A = [10, 20, 30, ['abc', '123']]
    B = A
    C = copy(A)
    D = deepcopy(A)
    
    A.append(100)
    A[3].pop()
    
    print(B)  # [10, 20, 30, ['abc'], 100]
    print(C)  # [10, 20, 30, ['abc']]
    print(D)  # [10, 20, 30, ['abc', '123']]
    

内存管理

内存管理分为内存的开辟和释放

  1. 内存的开辟

    Python中所有的类型都是类,所有的数据都是对象,对象都保存在堆里面。
    在保存数据的时候相同的不可变数据内存中只保存一份,相同的可变数据在内存中一定会保存多份

    list1 = [100, 200]
    list2 = [100, 200]
    
    tuple1 = (100, 200)
    tuple2 = (100, 200)
    
    print(id(list1), id(list2))     # 2177081172552 2177081172616
    print(id(tuple1), id(tuple2))   # 2177081784584 2177081784584
    
  2. 内存的释放 - 垃圾回收机制

    Python中内存的某个数据是否销毁(对应的内存是否释放),看这个数据在程序中的引用个数,当引用个数大于0的时候数据不会被销毁
    当数据的引用个数为0的时候数据会被自动销毁。

上一篇:day18 redis stream


下一篇:java实训学习:(day18)