第一章 1.16 类和对象(进阶)
一. 类的继承
继承是让子类直接拥有父类的属性和方法
1. 用法
class 类名(父类1,父类2,...)
类的内容
class Person:
num = 70
def __init__(self):
self.name = '小明'
self.age = 18
@staticmethod
def func1():
print('静态方法')
class Student(Person):
pass
# 子类直接使用父类的属性和方法
stu1 = Student.num
print(stu1)
stu2 = Student()
print(stu2.name, stu2.age)
2. 子类中添加属性和方法
1). 添加方法和字段
在子类中直接声明新的字段和方法,若字段和方法与父类的重名,则父类的会被覆盖(重写)
2). 添加对象属性
用__initial__方法添加新的属性,并且通过 super().__init__ 方法继承父类的对象属性
- 可以在类的任何一个对象方法或者类方法中去通过super()调用父类的的对象方法或者类方法
- super(类1,类1的对象).方法() -> 调用类1的父类中的方法
super().方法() <==> super(当前类,当前类的对象) - super(type, obj) -> 要求obj必须是type的对象或者是type的子类对象
class Animal:
num = 100
def __init__(self):
self.age = 10
self.gender = '雌'
def func1(self):
print('动物类中的对象方法')
@classmethod
def func2(cls):
print('动物类中的类方法')
@staticmethod
def func3():
print('动物类中的静态方法')
class Cat(Animal):
voice = '喵~'
def __init__(self):
super().__init__() # 调用当前类的父类的__init__方法
self.color = '白'
self.breed = '加菲猫'
def func4(self):
super().func1() # 用super实现 子类Cat中的函数(方法)内调用父类Animal的方法
print('猫类中的对象方法')
@classmethod
def func5(cls):
super().func2() # 用super实现 子类Cat中的函数(方法)内调用父类Animal的方法
print('猫类中的类方法')
@staticmethod
def func6():
print('猫类中的静态方法')
# 子类Cat继承父类Animal的属性和方法
# (父类的类方法和静态方法只能用子类的类调用,对象方法只能用对象调用)
cat1 = Cat()
print(cat1.color, cat1.breed, cat1.age, cat1.gender)
cat1.func1()
Cat.func2()
Cat.func3()
# 用super实现 子类Cat中的函数(方法)内调用父类Animal的方法
cat1.func4()
Cat.func5()
Cat.func6()
以上代码的执行结果:
白 加菲猫 10 雌
动物类中的对象方法
动物类中的类方法
动物类中的静态方法
动物类中的对象方法
猫类中的对象方法
动物类中的类方法
猫类中的类方法
猫类中的静态方法
3. 多继承
子类在继承多个父类时,对象属性只能继承第一个父类的对象属性
class Animal:
num = 100
def __init__(self, age=0, gender='雄'):
self.age = age
self.gender = gender
def a_func1(self):
print('动物的对象方法')
def massage(self):
print('this is Animal')
class Fly:
flag = '飞行'
def __init__(self, height=1000, time=3):
self.height = height
self.time = time
@classmethod
def f_func1(cls):
print('飞行的类方法')
class Bird(Animal, Fly):
pass
b1 = Bird()
print(Bird.num, Bird.flag)
b1.a_func1()
Bird.f_func1()
print(b1.age, b1.gender)
print(b1.height, b1.time) # 第二个父类的属性不能继承,本行代码会报错
4. 多继承的执行顺序
例:
class A:
def massage(self):
print('this is A')
class B(A):
def massage(self):
super().massage()
print('this is B')
class C(A):
def massage(self):
super().massage()
print('this is C')
class D(B, C):
def massage(self):
super().massage()
print('this is D')
D().massage()
代码执行结果:
this is A
this is C
this is B
this is D
说明:我也说不清,别喷我😭
二. 私有化
1. 访问权限
公开的(public):类的里面,外面都能用,也可以被继承
保护的(protect):类的里面可以用,也可以被继承
私有的(private):类的里面可以用,不能被继承
2. python中的权限
python类中的内容只有公开的,私有化是假的私有化
3.python私有化
在方法名前或属性名前加两个下划线__
只是在 __方法名 前加了下划线类名(_类名),在外部加_类名可以调用
class Person:
num = 61
__num2 = 100
def __init__(self, name, age=18):
self.name = name
self.age = age
self.gender = '男'
self.__gender = '男'
def func1(self):
print('%s今年%d岁' % (self.name, self.age), self.__gender)
self.__func11()
def __func11(self):
print('私有的对象方法')
@staticmethod
def func2():
print('我是静态方法1')
@staticmethod
def __func22():
print('我是静态方法1')
@classmethod
def func3(cls):
print(cls.num)
print(cls.__num2)
3. getter和setter
1. 什么时候用
如果希望在对象属性赋值前做点儿别的什么事情就给这个属性添加setter
如果希望在获取属性值之前做点儿别的什么事情就给这个属性添加getter
2. 怎么用
getter:
a. 将需要添加getter的属性名前加 _
b. 声明函数:声明前加@property;
函数名不带_的属性名;
函数需要一个返回值,返回值就是获取这个属性能够得到的值
c.在外面使用属性的时候不带下划线
setter:
注意: 如果想要给属性添加setter必须先添加getter
a. 声明函数: 声明前加@getter名.setter;
函数名不带_的属性名;
函数不需要返回值,但是需要一个参数,这个参数就是给属性赋的值
b.在外面给属性赋值的时候不带下划线
class Circle:
pi = 3.1415926
def __init__(self, r):
self.r = r
self._area = 0
@property
def area(self):
return Circle.pi * self.r * self.r
@area.setter
def area(self, value):
print('给area属性赋值:', value)
raise ValueError
c1 = Circle(1)
print(c1.area) # 本质是在调用area函数: c1.area()
c1.r = 10
print(c1.area) # 本质是在调用area函数: c1.area()
c1.r = 3
print(c1.area) # 本质是在调用getter的area函数: c1.area()