第四周 Day4 —— Python继承
一、继承
1. 什么是继承
让子类直接拥有父类属性和方法的过程就是继承。
子类:继承者
父类:被继承者,父类又叫超类
2. 怎么继承
Python中子类可以继承父类所有的属性和方法。
class 子类(父类):
pass
若要创建子类,必须有父类。
class Person:
def __init__(self, name='小花', age=18, gender='女'):
self.name = name
self.age = age
self.gender = gender
class Student(Person):
pass
stu1 = Student()
print(stu1.name, stu1.age, stu1.gender) # 小花 18 女
注意:
- 如果定义类的时候没有添加父类,默认继承
python
的基类object
- 同一个子类可以同时继承多个父类:
class 子类(父类1, 父类2, 父类3,...)
二、重写
1. 在子类中添加属性和方法
-
添加类属性:直接在子类中定义新的类属性。
-
添加方法:直接在子类中添家新的方法。
-
在子类中添家方法的时候可以对父类的方法重写。
-
在子类中可以通过
super().方法
的形式来调用父类中的方法。(注意:不能在静态方法中使用super()
调用父类的方法)
-
class A:
x = 100
@staticmethod
def func1():
print('A')
@classmethod
def funca(cls):
print('A1')
class B(A):
y = 20
@staticmethod
def func2():
print('B')
@staticmethod
def func1():
"""重写func1"""
print('BB')
@classmethod
def funca(cls):
super().funca()
print('B2')
@staticmethod
def func3():
super(B, B()).func1()
print('B的静态')
print(A.x) # 100
print(B.x) # 100
print(B.y) # 20
# print(A.y) # 报错
B.func1() # BB
B.func2() # B
A.func1() # A
B.funca() # A1 B2
B.func3() # A B的静态
总结:
super
的用法可以通过
super
在子类中调用父类中的方法。
suoer().方法()
- 直接调用当前类的父类的指定方法super(类, 对象).方法()
- 调用指定类的父类的指定方法(要求对象必须是前面的类的对象)
-
添加对象属性
在子类的
__init__
方法中通过super()
去调用父类的__init__
。
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 = '野猫'
cat = Cat()
print(cat.age, cat.gender) # 0 雌
print(cat.color, cat.price, cat.breed) # 白色 2000 野猫
三、对象属性的添加问题
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):
super().__init__(a)
self.d = d
bb = B(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 Student(Person):
def __init__(self, name, tel, age=18, gender='男'):
super().__init__(name, age, gender)
self.tel = tel
self.stu_id = '000'
self.credits = 0
stu1 = Student('小明', '123456789', age=20, gender='女')
print(stu1.name, stu1.age, stu1.gender, stu1.tel, stu1.stu_id, stu1.credits)
# 小明 20 女 123456789 000 0
四、多继承
多继承的是子类可以继承所有父类的类属性和方法,但是只能继承第一个父类的对象属性。
class Animal:
num = 61
def __init__(self):
self.age = 0
self.gender = '雄'
@classmethod
def show(cls):
print(f'数量:{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) # 61 飞行器
Bird.show() # 数量:61
Bird.message() # 飞行器
bird1 = Bird()
print(bird1.age, bird1.gender)
# print(bird1.height, bird1.time) # AttributeError: 'Bird' object has no attribute 'height'
五、私有化(补充)
-
公开的:在类的内部可以使用、类的外部也可以使用还可以被继承。(Python中所有的属性和方法都可以公开)
-
保护的:在类的内部可以使用、可以被继承。
-
私有的:只能在类的内部可以使用。
1.私有化的方法:
在属性名或者方法名前面加__
就可以让属性或者方法变成私有的。
2.私有化的原理:
假的私有化;在__
开头的名字前面加_类名
class A:
__x = 100
print(A.__x) # 报错
print(A._A__x) # 100
六、拷贝
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, gender):
self.name = name
self.age = age
self.gender = gender
self.dog = Dog()
def __repr__(self):
return f'<{str(self.__dict__)[1:-1]}>'
p1 = Person('小明', 20, '男')
p2 = p1 # 直接赋值,将p1中的地址赋给p2
p3 = copy(p1) # 浅拷贝,复制p1产生一个新的对象,用新对象给p3赋值
p4 = deepcopy(p1) # 深拷贝,复制p1产生一个新的对象,用新对象给p4赋值
p1.name = '小花'
print('原数据:', p1)
print('直接赋值:', p2)
print('浅拷贝:', p3)
print('深拷贝:', p4)
# 原数据: <'name': '小花', 'age': 20, 'gender': '男', 'dog': <'name': '馒头', 'gender': '公狗', id:2968125319600>, id:2968122732616>
# 直接赋值: <'name': '小花', 'age': 20, 'gender': '男', 'dog': <'name': '馒头', 'gender': '公狗', id:2968125319600>, id:2968122732616>
# 浅拷贝: <'name': '小明', 'age': 20, 'gender': '男', 'dog': <'name': '馒头', 'gender': '公狗', id:2968125319600>, id:2968125319768>
# 深拷贝: <'name': '小明', 'age': 20, 'gender': '男', 'dog': <'name': '馒头', 'gender': '公狗', id:2968125342496>, id:2968125320440>
1. 浅拷贝和深拷贝
共同点:不管是浅拷贝还是深拷贝都是复制被拷贝的对象产生一个新的对象,然后用新的对象来复制。
区别:如果背靠背的对象中有子对象,浅拷贝不复制子对象用原来的,深拷贝会复制子对象产生新的子对象。
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) # B = [10, 20, 30, ['abc', '123'], 100]
print(C) # C = [10, 20, 30, ['abc']]
print(D) # D = [10, 20, 30, ['abc', '123']]
七、内存管理
内存管理分为内存的开辟和释放:
1. 内存的开辟
python
中所有的类型都是类,所有的数据都是对象,对象都保存在堆里面。
在保存护具的时候相同的不可变数据内存中只保存一份,相同的可变数据在内存中一定会保存多份。
使用数据的时候就申请内存保存数据
2. 内存的释放——垃圾回收机制
python
中内存的某个数据是否销毁(对应的内存是否释放),看这个数据在程序中的引用个数,当引用个数大于0
的时候数据不会被销毁,当数据的引用个数为0
的时候数据就会被自动销毁。