210225课 类的继承

210225课 类的继承

继承

1,继承的定义

让子类直接拥有父类的属性和方法的过程
**子类;**继承者
**父类:**被继承者,又称 超类

2,继承方法

class 子类(父类)
pass
**注意:**如果没有添加括号,默认继承基类object
一个子类可以同时拥有多个父类 class 子类(父类1,父类2,…)
Python中子类可以继承父类所有的属性和方法

class Person:
    num = 61

    def __init__(self):
        self.name = '小红'
        self.age = 18
        self.sex = '女'

    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.age, stu1.name, stu1.sex)
# 18 小红 女
print(Student.num)
# 61
stu1.eat('包子')
# 小红在吃包子
Student.show_num()
# 人类的数量: 61
Student.info()
# 人类破坏环境!

子类重写

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

1)添加类属性

直接在子类中定义新的类属性即可

2)重写: 在子类中可以添加跟父类相同的方法

调用:各用各的重写部分时直接调用
既用重写又用父类方法时,通过 super().方法 来调用 (静态方法除外)
总结:super的用法
super().方法() 直接调用当前父类的制定方法
super(类,对象).方法()
调用指定类的父类的制定方法(要求对象必须是前面类的对象

3)添加对象属性

在子类的 _ _ init _ _ 方法中通过super()去调用父类的 _ _ init _ _

class A:
    x = 100

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

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

    def func4(self):
        print('A的对象方法1')

    def func5(self):
        print('A的对象方法2')


class B(A):
    y = 20

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

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

    @classmethod
    def funca(cls):
        super().funca()
        """cls.__base__.funca()"""
        print('B2')

    def func4(self):
        super().func4()
        super().func5()
        print('B的对象方法')

    @staticmethod
    def func3():
        # super().func1()  # 报错
        super(B, B()).func1()
        print('B的静态')


class C(B):
    pass


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

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

B.func1()   # BB
A.func1()   # A

B.funca()  # A1 B2

b = B()
b.func4()  # A的对象方法1  A的对象方法2  B的对象方法

B.func3()  # A  B的静态


class X:
    def fx(self):
        print('x')


class Y(X):
    def fy(self):
        super().fx()
        """super(Y, self).fx()"""
        print('y')

    def f(self):
        super().fx()
        super(N, N()).fm()


class M:
    def fm(self):
        print('m')


class N(M):
    def fn(self):
        print('n')


x = X()
y = Y()
y.fy()  # x y
y.f()   # x m


print('================================================')


class Animal:
    def __init__(self):
        self.age = 0
        self.gender = '雌'


class Cat(Animal):
    def __init__(self):
        super().__init__()
        self.color = '白色'
        self.price = 2000
        self.breed = '野猫'
    pass


cat = Cat()
print(cat.age, cat.gender)  # 0 雌
print(cat.color)  # 白色

对象属性的添加问题

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


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


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, gender='男'):
        self.name = name
        self.age = age
        self.gender = gender


class Students(Person):
    def __init__(self, name, tel, age=18, gender='男'):
        super(Students, self).__init__(name, age, gender)
        self.study_id = '007'
        self.score = 0
        self.tel = tel


p = Person('小明', 18)
stu = Students('小红', '1110', 20, '女')
print(stu)  # <__main__.Students object at 0x000000000255B160>

多继承

多继承时子类可以继承所有父类的类属性和方法,
但是只能继承第一个父类的对象属性
_ _ mro _ _ 模型 适用于多继承(了解)


class Animal:
    num = 61

    def __init__(self):
        self.age = 0
        self.gender = '雄'

    @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(Fly, Animal):
    pass


print(Bird.num, Bird.name)

Bird.show()
Bird.message()

b = Bird()
# print(b.age, b.gender)
print(b.height, b.time)

私有化

访问权限:

1)公开的:在类的内部和外部都可以使用和被继承

(Python中所有的属性都是公开的)

2)保护的:在类的内部可以使用和被继承
3)私有的:在类的内部使用,不能被继承

在Python的类里面的属性名或方法名命名前加2个下划线__
即可使属性或方法私有化
Python的私有化是个伪概念,加2个下划线相当于更换了一个存储位置
相当于在2个下划线开头加’_类名’,
如果想被继承,在前面加 _类名 即可. 本质还是公开的


class A:
    num = 100
    __x = 200    # __x是私有的

    def __init__(self):
        self.name = '小明'
        self.__age = 18   # __age是私有的

    def info(self):
        print('信息:', self.__age)
        self.__f1()

    @classmethod
    def show(cls):
        print(cls.num, cls.__x)

    def __f1(self):
        print('对象方法')


print(A.num)
A.show()

# print(A.__x)

a = A()
print(a.name)
# print(a.__age)

a.info()

# a.__f1()

print(a.__dict__)   # {'name': '小明', '_A__age': 18}
print(a._A__age)    # 18

拷贝

浅拷贝和深拷贝

**相同点:**都会复制被拷贝的对象,产生新的对象,然后用新的对象来赋值
**不同点:**如果被拷贝的对象有子类,浅拷贝只复制父类,深拷贝都拷贝

# 导入copy模块
from copy import copy, deepcopy
class Dog:
    def __init__(self):
        self.name = '旺财'
        self.gender = '公狗'

    def __repr__(self):
        return f'<{str(self.__dict__)[1:-1]},id:{id(self)}>'


class Person:
    def __init__(self, name, age=18, gender='女'):
        self.name = name
        self.age = age
        self.gender = gender
        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.gender = '母狗'
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=[10, 20, 30, ['abc', '123'], 100]
A[3].pop()  # A=[10, 20, 30, ['abc'], 100]

print(B)  # [10, 20, 30, ['abc'], 100]
print(C)  # [10, 20, 30, ['abc']]
print(D)  # [10, 20, 30, ['abc', '123']]

内存管理

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

1,内存的开辟 使用数据时在堆里面申请内存,值与栈里的名字相对应

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

2,内存的释放 垃圾回收机制

Python中内存的某个数据是否释放,看这个数据在程序中的引用个数
大于0,不会被销毁,反之会被销毁

print(type(10))

a = 100
age = 100
list1 = [100, 200]
print(id(a), id(age), id(list1[0]))

a = [10, 20]
b = [10, 20]
c = [100, [10, 20]]
print(id(a), id(b), id(c[-1]))

A = 100
del A
# B = A   # NameError: name 'A' is not defined
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值