昨日回顾
1.面对对象编程
核心是“对象“,对象指的是特征与技能的结合体。
基于改编程思想编写程序,就好比在创造世界,一种上帝式的思维方式。
2.类
类是一系列对象相同的特征和技能的结合体。
定义类时产生的事情:
1.会产生一个空的名称空间
2.会把类内部的所有名字(资源)扔进名称(内存)空间中
3.会执行类内部的代码
调用类时发生的事情:
1.会产生一个空的对象
2.会自动触发__init__
3.会将对象和括号内的参数一并传给__init__
注意:调用类的过程称之为类的实例化,产生的对象称之为类的一个实例。
__init__
:在类内部创建的,会在调用类时触发该方法
3.对象
对象的属性查找顺序:
对象查找类的属性:
1.会先去对象的名称空间查找。
2.若对象没有则会去类的名称空间查找
4.对象的绑定方法特殊之处
1.由类来调用类内部的函数,该函数只是一个普通的函数
函数需要接收几个参数就得传几个
2.由对象来调用类内部的函数,该函数称之为对象的绑定方法
会将不同的对象绑定给不同的方法,特殊之处是会将对象当作第一个参数传给该方法
5.一起皆对象
在python中,一切皆对象。
指的是通过 type()
查看。若返回的是 <class xxx>
的都是对象
例如:python的八大数据类型
继承
什么是继承
继承指的是新建类的方法,新建的类称之为子类或者派生类。
子类继承的类叫做父类,也称之为基类或超类
继承的特征:
子类可以继承父类的属性(特征与技能),并且可以派生出自己的属性(特征与技能)
注意:在python中,一个子类可以继承多个父类,其他语言只能一个子类继承一个父类
为什么要继承
继承的目的是为了减少代码冗余(减少重复代码)
如何实现继承
1.首先要确定好谁是子类,谁是父类。
2.在定义类时,子类 + () , ()内写父类,实现继承
继承初体验
# 父类
class ParentClass1:
pass
class ParentClass2:
pass
# 子类
class SubClass1(ParentClass1):
pass
# 继承多个父类
class SubClass2(ParentClass1,ParentClass2):
pass
查看继承的父类: __bases__
,是类的属性,用来查找当前类的父类
print(SubClass1.__bases__) # (<class'__main__,ParentClass1'>,)
print(SubClass2,__bases__) # (<class'__main__,ParentClass1'>,<class'__main__,ParentClass2'>)
寻找继承关系
如何寻找继承关系
要想寻找继承关系,首先要“先抽象,再继承”
什么是抽象
抽象指的是抽取相似的部分,称之为抽象
继承的关系
- 对象是特征与技能的结合体
- 类时一系列对象相同的特征与技能的结合体
- 继承是一系列类相同的特征与技能的结合体
选课系统
# 不继承情况下:
# 老师类:名字,年龄,性别
class OldboyTeacher:
school = 'oldbuy'
def __init__(self,name,age,sex):
self.name = name
self.age = age
self.sex = sex
# 老师修改分数技能
def change_score(self):
print(f'老师[{self.name} 修改分数...]')
# 学生类:名字,年龄,性别
class OldboyStudengt:
school = 'oldboy'
def __init__(self,name,age,sex):
self.name = name
self.age = age
self.sex = sex
# 学生可以选择课程
def choose_course(self,course):
print(f'学生[{self.name}]选择课程[{course}]')
# 父类
'''
抽象:
school
__init__(self,name,age,sex)
'''
class OldboyPeople:
school = 'oldboy'
def __init__(self,name,age,sex):
self.name = name
self.age = age
self.sex = sex
# 老师类:名字,年龄,性别
class OldboyTeacher(OldboyPeople):
# 老师修改分数技能
def change_score(self):
print(f'老师[{self.name} 修改分数...]')
# 学生类:名字,年龄,性别
class OldboyStudent(OldboyPeople):
# 学生可以选择课程
def choose_course(self,course):
print(f'学生[{self.name}]选择课程[{course}]')
stu1 = OldboyStudent('小丁丁',85,'female')
tea1 = OldboyTeacher('tank',37,'male')
print(stu1.name,stu1.age,stu1.sex)
print(tea1.name,stu1.age,stu1.sex)
继承背景下对象属性查找顺序
1.对象查找属性会先从对象的名称空间中查找。
2.若对象没有,则会去类里面找
3.若当前类时子类,并且没有对象找的属性,会去父类中查找
注意:对象查找属性,若子类有,不管父类有没有,以子类的为准
# 验证对象属性的查找顺序
class Foo:
def f1(self):
print('Foo.f1')
def f2(self):
print('Foo.f2')
self.f1()
class Soo(Foo):
def f1(self):
print('Soo.f1')
soo_obj = Soo()
soo_obj.f2()
'''
Foo.f2
Soo.f1
'''
派生
派生指的是子类继承父类的属性,并且派生出新的属性。
子类派生出新的属性,若与父类的属性相同,则以子类的为准
继承是谁与谁的关系,指的是类与类的关系,子类与父类是从属关系
# 验证对象属性的查找顺序
class Foo:
def f1(self):
print('Foo.f1')
def f2(self):
print('Foo.f2')
self.f1()
class Soo(Foo):
def f1(self):
print('Soo.f1')
soo_obj = Soo()
soo_obj.f1() # Soo.f1
子类派生出新的属性,并重用父类的属性
class OldboyPeople:
def __init__(self,name,age,sex):
self.name = name
self.age = age
self.sex = sex
class OldboyTeacher(OldboyPeople):
# 等级,薪资
def __init__(self,name,age,sex,level,sal):
self.name = name
self.age = age
self.sex = sex
self.level = level
self.sal = sal
class OldboyStudent(OldboyPeople):
# 课程
def __init__(self,name,age,sex,course):
self.name = name
self.age = age
self.sex = sex
self.course = course
问题:子类继承父类的__init__
毫无意义
解决方式:
方式一:
直接通过父类.(调用) __init__
,把__init__
当做普通函数使用,传入对象与继承的属性
方式二:
super是一个特殊的类,在子类中调用super()会得到一个特殊的对象,通过"."指向的是父类的名称空间
注意:两种方式不要混合使用
class OldboyPeople:
def __init__(self, name, age, sex):
self.name = name
self.age = age
self.sex = sex
# 方式一
class OldboyTeacher(OldboyPeople):
# 等级, 薪资
def __init__(self, name, age, sex, level, sal):
OldboyPeople.__init__(self, name, age, sex)
self.level = level
self.sal = sal
class OldboyStudent(OldboyPeople):
# 课程
def __init__(self, name, age, sex, course):
OldboyPeople.__init__(self, name, age, sex)
self.course = course
def choose_course(self):
print(f'学生{self.name}选择课程{self.course}')
# 方式二
class OldboyTeacher(OldboyPeople):
# 等级, 薪资
def __init__(self, name, age, sex, level, sal):
super().__init__(name, age, sex)
self.level = level
self.sal = sal
class OldboyStudent(OldboyPeople):
# 课程
def __init__(self, name, age, sex, course):
super().__init__(name, age, sex)
self.course = course
def choose_course(self):
print(f'学生{self.name}选择课程{self.course}')
# print(super)
tea1 = OldboyTeacher('tank', 17, 'male', 9, '3.0')
stu1 = OldboyStudent('小健健', 20, 'female', 'python')
print(tea1.name, tea1.level)
print(stu1.name, stu1.course)
stu1.choose_course()
新式类和经典类
- 在python2中,才会有新式类和经典类之分
- 在python3中,所有的类都是新式类
新式类:
继承object的类都称之为新式类
python3中,子类不继承自定义的类,默认继承object
经典类:
在python2中,凡是没有继承object的类都是经典类
钻石继承
钻石继承也可以称之为菱形继承(了解,面试可能用得到)
— 在多继承的情况下形成的钻石继承(继承顺序)
— 经典类:
深度优先:
— 新式类:
广度优先:
# 验证
class A:
# def test(self):
# print('from A')
pass
class B(A):
# def test(self):
# print('from B')
pass
class C(A):
def test(self):
print('from C')
pass
class D(B):
# def test(self):
# print('from D')
pass
class E(C):
# def test(self):
# print('from E')
pass
class F(D,E):
# def test(self):
# print('from F')
pass
# 新式类: F-D-B-E-C-A-object
f1 = F()
f1.test()
# 经典类: F-D-B-A-E-C
通过继承实现修改json模块数据类型
import json
from datetime import date,datetime
print(json.JSONEcoder)
print(datetime.today()) # 当前时间
print(date.today()) # 当前日期
# 开发者的角度:直接转成str
dict1 = {
'name': 'tank',
'today': str(datetime.today()),
'today2': str(date.today())
}
res = json.dumps(dict1)
print(res)
isinstance:
python内置的函数,可以传两个参数,判断参数一是否是参数二的一个实例
# 开源者的角度:修改json源码
class MyJson(json.JSONEncoder):
def default(self,o):
# 子类派生的功能
# 判断o是否是datetime的一个实例
if isinstance(o,datetime):
return o.strftime('%Y-%m-%d')
elif isinstance(o, date):
return o.strftime('%Y-%m-%d')
else:
# 继承父类的default方法的功能
return super().default(self, o)
dict1 = {
'name': 'tank',
'today': datetime.today(),
'today2': date.today()
}
res = json.dumps(dict1, cls=MyJson) # cls=None,默认指向的是原json的JSONEncoder
print(res)