一.封装
封装是指将对象的属性和方法包装在一起,对外隐藏实现细节,只提供必要的接口给外部访问。
在Python中,通过 init 方法初始化属性,并通过方法来操作这些属性。
以 __ 开头的属性或方法是私有的,在子类和类外部无法直接使用
可使用私有属性和公有方法控制外部访问。
二.继承/派生
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| class Ganyuan: def __init__(self, name, atk): self.name = name self.atk = atk def ATK(self): print('%s的攻击力是%d'%(self.name, self.atk)) class jinwei(Ganyuan): def __init__(self, name, atk,fy): super().__init__(name, atk) self.fy = fy def FY(self): print('%s的防御力是%d'%(self.name, self.fy)) Ace = jinwei('Ace', 100, 200)
Ace.ATK() Ace.FY()
|
输出:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| class Ganyuan: def __init__(self, name, atk): self.name = name self.atk = atk def ATK(self): print('%s的攻击力是%d'%(self.name,self.atk)) class man: def __init__(self, age): self.age = age def AGE(self): print('年龄是%d'%(self.age)) class jinwei(Ganyuan,man): def FY(self): print('%s的防御力是%d'%(self.name, self.fy)) def __init__(self,name,atk,age,fy): Ganyuan.__init__(self,name,atk) man.__init__(self,age) self.fy = fy Ace = jinwei('Ace',100,200,10) Ace.ATK() Ace.FY() Ace.AGE()
|
输出:
1 2 3
| Ace的攻击力是100 Ace的防御力是10 年龄是200
|
三.覆盖 – 重写
在子类中实现与基类同名的方法,我们叫覆盖。
实现和父类同名,但功能不同的方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| class father: def __init__(self,name,age): self.name = name self.age = age def show(self): print('我是%s,今年%d岁'%(self.name, self.age))
class son(father): def __init__(self,name,age,atk): super().__init__(name,age) self.atk = atk a = son('Ace', 18, 100) a.show()
|
输出:
四.多态
多态是指同一个方法在不同对象上具有不同的行为
多态的实现通常通过继承和方法重写来实现
子类创建的对象既属于子类也属于父类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| class Animal: def speak(self): print('Animal speak') class Dog(Animal): def speak(self): print('Dog speak') class Cat(Animal): def speak(self): print('Cat speak')
class bird(Animal): def fly(self): print('bird fly') def animal_speak(animal): if isinstance(animal, Animal): animal.speak() else: print('animal is not Animal') dog = Dog() cat = Cat() Bird = bird() animal_speak(dog) animal_speak(cat)
animal_speak(Bird)
|
输出:
1 2 3
| Dog speak Cat speak Animal speak
|
五.对象对成员的操作
1 2 3 4 5 6 7 8 9 10
| class arknights: x = 10 atk = 100 Ace = arknights()
print(Ace.x)
print(Ace.fy)
|
输出:
1 2 3 4 5 6 7 8 9 10
| 10
--------------------------------------------------------------------------- AttributeError Traceback (most recent call last) Cell In[6], line 10 7 print(Ace.x) 9 # 访问没有的属性 ---> 10 print(Ace.fy)
AttributeError: 'arknights' object has no attribute 'fy'
|
可以看到一个对象访问其中没有的属性是会报错的,但对象可以直接添加一个属性,这样不会报错。
1 2 3 4 5 6 7 8 9
| class arknights: x = 10 atk = 100 Ace = arknights()
Ace.fy = 200 print(Ace.fy) print(arknights.fy)
|
输出:
1 2 3 4 5 6 7 8 9 10
| 200
--------------------------------------------------------------------------- AttributeError Traceback (most recent call last) Cell In[9], line 9 7 Ace.fy = 200 8 print(Ace.fy) ----> 9 print(arknights.fy)
AttributeError: type object 'arknights' has no attribute 'fy'
|
事实证明一个对象确实可以拥有自己的属性,原类中没有且不能访问。
六.私有属性
用 __x 来表示私有属性,私有属性是跟对象有关的,也是类属性的一种。
1 2 3 4 5
| class A: __x = 1 a = A() print(a.__x)
|
输出:
1 2 3 4 5 6 7 8
| --------------------------------------------------------------------------- AttributeError Traceback (most recent call last) Cell In[13], line 5 2 __x = 1 4 a = A() ----> 5 print(a.__x)
AttributeError: 'A' object has no attribute '__x'
|
这个类创建的对象是不能直接访问类的私有属性的,那该怎么访问呢?可以在父类中定义一个方法,这个方法在类中是可以访问私有属性的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| class A: __x = 1 def fun(self): self.__x = 2 def fun1(self): print(self.__x) a = A() b = A()
a.fun() a.fun1()
b.fun1()
A.fun1(A)
|
输出:
这也就反映了为什么说私有属性是类属性的一种,因为私有属性像类属性一样会继承给对象,而对象更改私有属性也只会更改自己的私有属性,而不会影响其他对象。
七.重载
实际上就是把原有的魔术方法更改了,这里不提前面写过的方法,提一些其他的方法:
**mul(self, rhs) **计算乘法
**truediv(self, rhs) **计算除法
**floordiv(self, rhs) **计算整除
**mod(self, rhs) **计算取余
pow(self, rhs) 计算幂
八.super函数
来一个很好的比喻,父类A中的fun()方法有10万行代码,管理者觉得非常好。继承A的B类中的fun()方法只有1万行代码,管理者觉得也很好。现在希望把这11万行代码一起运行,那么,A和B的fun()方法应该如何组合呢?难道要把那10万行代码又重新写一遍再加上1万行?那么我们现在就来看看。
1 2 3 4 5 6 7 8 9 10 11 12 13
| class A: def fun(self): print('A') class B(A): def fun(self): super().fun() print('B') b = B() b.fun()
|
输出:
注意,super()不一定非得写在类的函数里面,也可以直接在外部直接使用
1 2 3 4 5 6 7 8 9 10 11 12
| class A: def fun(self): print('A') class B(A): def fun(self): print('B') b = B()
super(B,b).fun()
|
输出:
关于这个使用方法,可以出一道思考题:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| class A: x = 1 def fun(self): print('A') print(self.x) class B(A): x = 2 def fun(self): print('B') print(self.x) b = B() b.x = 3
super(B,b).fun()
|
输出:
结果显而易见,调用了父类A的fun()方法,但其传进去的参数却是子类B创建的b对象,因此打印了A中的语句,以及b对象的属性。