目录
@dataclass只能在python3.7版本中使用
from dataclasses import dataclass
@dataclass
class Point:
x: float
y: float
z: float = 0.0
# p = Point(1.5, 2.5)
# print(p) # produces "Point(x=1.5, y=2.5, z=0.0)"
from dataclasses import dataclass
@dataclass
class zhuangbei:
price: int
aggrev: int
life_value: int
bc = zhuangbei(9,100,10)
class duolandun(zhuangbei):
pass
class BlackCleaver(zhuangbei):
pass
# print(bc)
f = BlackCleaver(0,100,10)
print(f)
'''
BlackCleaver(price=0,aggrev=100,life_value=10)
'''
# https://www.cnblogs.com/apocelipes/p/10284346.html
1.继承是一种新建类的方式。新建的类称为子类,被继承的类称为父类
2.继承的特性:子类会继承父类所有的属性
3.继承其本质就是类与类之间的一种关系
class F_c:
attri = '继承'
def __init__(self,name):
self.name = name
def func(self):
print('from 父类')
class S_c(F_c):
pass
son = S_c('son')
print(son.attri) # 继承数据属性(可自行更改)
print(son.name) # 继承父类的属性,即可以使用父类中的自定义属性
son.func() # 继承父类的函数属性,即可以调用父类中的函数
'''
继承
son
from 父类
'''
可以避免重复代码,即减少代码的冗余
1.python中支持一个类同时继承多个父类
class Parent1:
pass
class Parent2:
pass
class Child(Parent1, Parent2):
pass
**2.使用__bases__方法可以获取对象所继承的类**
print(child.__bases__) # (<class '__main__.Parent1'>, <class '__main__.Parent2'>)
# 是一个元组,所以我们可以通过for循环打印
for i in child.__bases__:
print(i)
1.继承描述的是子类与父类之间的关系,要找出它们的关系,必须先抽象再继承。抽象:抽取类似或者说比较像的部分
2.抽象主要的作用是划分类别(可以隔离关注点,降低复杂度)
3.抽象只是分析和设计过程的一个动作,或者说是一种技巧,通过抽象,我们可以得到类
class SchoolPeople:
school = 'XXschool'
def __init__(self,name,age,gender):
self.name = name
self.age = age
self.gender = gender
class Student(SchoolPeople):
def choose_course(self):
print(f'{self.name} is choose course')
class Teacher(SchoolPeople):
def mark(self, stu_obj, score):
print('{self.name} is mark')
stu_obj.grade = score # 对象本质上可以看作是一个字典,所以可以直接添加(对象是可以点出属性的)
stud = Student('king',26,'male')
print(stud.__dict__)
teac = Teacher('teacher',27,'male')
print(teac.__dict__)
stud.choose_course()
teac.mark(stud,100)
print(stud.__dict__)
print(teac.__dict__)
'''
{'name': 'king', 'age': 26, 'gender': 'male'}
{'name': 'teacher', 'age': 27, 'gender': 'male'}
king is choose course
teacher is mark
{'name': 'king', 'age': 26, 'gender': 'male', 'grade': 100}
{'name': 'teacher', 'age': 27, 'gender': 'male'}
'''
对象自己 ----> 对象的类 ----> 父类 ----> 父类(如果存在多个父类).... ----> 爷爷类
class Foo:
def f1(self):
print('f1 of Foo ')
def f2(self):
print('f2 of Foo ')
self.f1() # 这里的self指的是实例化对象(千万不要看作是f2)
class Bar(Foo):
def f1(self):
print('f1 of Bar')
obj = Bar() # 实例化一个对象
obj.f2() # 对象查找属性的路径:对象自己--》对象的类--》父类...
'''
所以 obj.f2() 的结果为:
f2 of Foo
f1 of Bar
'''
派生:子类中定义新的属性的过程叫做派生。子类在使用派生的属性时,始终以自己的派生属性为准
方法一:指名道姓访问某一个类中的函数,与继承无关(子类自己定义属性)
class SchoolPeople:
school = 'XXschool'
def __init__(self,name,age,gender):
self.name = name
self.age = age
self.gender = gender
class Teacher(SchoolPeople):
def __init__(self,name,age,gender,level):
SchoolPeople.__init__(self,name,age,gender)
self.level = level
def mark(self, stu_obj, score):
print('{self.name} is mark')
teac = Teacher('king',26,'male',2)
print(teac.__dict__)
# {'name': 'king', 'age': 26, 'gender': 'male', 'level': 2}
方法二:
1.严格以继承属性来查找关系(可以参考菱形继承问题)
**2.利用super().__init__方法进行派生子类的新属性**
3.super()会得到一个特殊的对象,该对象就是专门用来访问分类中的属性的(按照继承关系来查找属性)
4.python2中的语法:super(自己的类名,self)。python3中的语法:super()
class SchoolPeople:
school = 'XXschool'
def __init__(self,name,age,gender):
self.name = name
self.age = age
self.gender = gender
class Teacher(SchoolPeople):
def __init__(self,name,age,gender,level):
super().__init__(self,name,age,gender)
# python2语法:
# super(Teacher,self).__init__(self,name,age,gender)
self.level = level
def mark(self, stu_obj, score):
print('{self.name} is mark')
teac = Teacher('king',26,'male',2)
print(teac.__dict__) # {'name': 'king', 'age': 26, 'gender': 'male', 'level': 2}
在一个类中以另外一个类的对象作为数据属性
组合可以解决类与类之间代码冗余的问题
class SchoolPeople:
def __init__(self, name, age, gender):
self.name = name
self.age = age
self.gender = gender
def login(self):
print(f'{self.name}登陆')
class Student(SchoolPeople):
def __init__(self, id, name, age, gender):
self.id = id
super(Student, self).__init__(name, age, gender) # python2 语法
def choose(self, course):
print(f'{self.name}选择了{course.name}课程')
king = Student(1, 'king', 26, 'male')
class Teacher(SchoolPeople):
def __init__(self, name, age, gender, level):
super().__init__(name, age, gender) # python3 语法
self.level = level
def scored(self, student, course, score):
print(f'老师{self.name}给学生{student.name}的{course.name}课程打了{score}分')
nick = Teacher('nick',20,'male',1)
class Course:
def __init__(self, name, price):
self.name = name
self.price = price
python = Course('python', 8888)
# 类的组合:将另一个类的对象当作这个类的数据属性
class Admin(SchoolPeople, Course):
# 组合的应用
def creat_course(self, name, price):
res = Course(name, price) # 通过类中的方法调用其他的类(生成一个实例对象)
print(f'{self.name}创建了课程{res.name}')
return res # 返回被调用类运行的结果,这个结果就是一个实例对象
egon = Admin('egon', 20, 'male')
python = egon.creat_course('python', 20000) # 相当于在类内部调用另一个类,同样可以实例化对象
print(python.price)
1.继承了object的类以及该类的子类的类,都是新式类
2.python3中所有的类都是新式类
1.没有继承object的类以及该类的子类,都是经典类
2.只有python2中有经典类
3.1 对于python中定义的每个类,python会计算出一个方法解析顺序列表(MRO),这个MRO列表就是一个简单的所有基类的线性顺序列表
3.2 通过mro()方法,我们可以得到新式类的寻找属性顺序
class A:
pass
class B(A):
pass
class C(A):
pass
class D(A):
pass
class E(D):
pass
class F(C):
pass
class G(B,E,F):
pass
print(G.mro())
'''
[<class '__main__.G'>, <class '__main__.B'>, <class '__main__.E'>, <class '__main__.D'>, <class '__main__.F'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>]
'''
for i in G.mro():
print(i)
'''
<class '__main__.G'>
<class '__main__.B'>
<class '__main__.E'>
<class '__main__.D'>
<class '__main__.F'>
<class '__main__.C'>
<class '__main__.A'>
<class 'object'>
'''
为了实现继承,python会在MRO列表上从左到右开始查找基类,直到找到第一个匹配这个属性的类为止。
而这个MRO列表的构造是通过一个C3线性化算法来实现的。我们不去深究这个算法的数学原理,它实际上就是合并所有父类的MRO列表并遵循如下三条准则:
1.多态:多种状态,只要大家能继承同一种东西A,这些东西就是A的多态
2.水:液态/固态/气态
3.动物:人/狗/猫
import abc
class Animal(metaclass=abc.ABCMeta): # 不推荐使用
def __init__(self, height, weight):
self.height = height
self.weight = weight
@abc.abstractmethod
def sleep(self):
print('我在睡觉')
@abc.abstractmethod
def speak(self):
print(self, '开始叫了')
@abc.abstractmethod
def eat(self):
print(self, '开始吃了')
class People(Animal):
def speak(self):
print('开始叫了')
def eat(self):
print(self, '开始吃了')
class Dog(Animal):
def speak(self):
print('开始叫了')
def eat(self):
print(self, '开始吃了')
class Cow(Animal):
def speak(self):
print('开始叫了')
def eat(self):
print(self, '开始吃了')
class Foo(Animal):
def speak(self):
pass
f = Foo(1,1)
f.sleep()
peo = People(180, 140)
dog = Dog(50, 100)
cow = Cow(100, 200)
# peo.speak()
# dog.speak()
# cow.speak()
# sheep.speak()
# mao.speak()
# peo.eat()
# dog.eat()
4.总结
4.1 鸭子类型:长得像鸭子,叫声也像鸭子,就是鸭子,(只要有speak和eat这两个方法,那他就是动物类)
4.2 对于我们这个例子:==你只要有speak方法/有eat方法,我无论你怎么定义这个类,你就是动物==的一种形态,你这样才能用动物的方法,否则无法使用动物的方法
5.多态性的好处(涉及到接口)
class Cat(Animal): # 属于动物的另外一种形态:猫
def talk(self):
print('say miao')
def func(animal): # 对于使用者来说,自己的代码根本无需改动
animal.talk()
cat1 = Cat() # 实例出一只猫
func(cat1) # 甚至连调用方式也无需改变,就能调用猫的talk功能
Python本身就是多态,根本就不支持多态
class Animal():
def eat(self):
print('eat')
class People(Animal):
def eat(self):
print('人吃')
class Dog(Animal):
def eat(self):
print('??吃')
class Pig(Animal):
def eat(self):
print('??吃')
def sleep(self):
print('??睡')
class F(Animal):
def eat(self):
print('f吃')
f = F()
peo = People()
pig = Pig()
dog = Dog()
# 多态性
peo.eat()
pig.eat()
dog.eat()
f.eat()
class Cat(Animal):
def eat(self):
print('???吃')
cat = Cat()
cat.eat()
# 100种动物
print('*'*50)
# 多态性的使用,提供接口的概念
def func(obj):
obj.eat()
obj.run()
obj.walk()
obj.sleep()
func(cat)
# cat.eat()
# cat.walk()
# cat.run()
# cat.sleep()
func(dog)
# dog.eat()
# dog.walk()
# dog.run()
# dog.sleep()
func(peo)
取钱,插卡-》输入密码-》输入金额-》取到钱了
(插卡-》输入密码-》输入金额-》取到钱了)--》取钱函数
鸭子类型:只要长得像??,叫的像??,游泳也想??,你就是??
参考链接:http://www.cnblogs.com/nickchen121/
原文:https://www.cnblogs.com/itboy-newking/p/11072034.html