今日内容回顾
对象的独有功能
针对对象独有的功能,我们无法真正实现
定义在类里面的方法,原则上是公共的方法
但其本质是那个对象调用属于那个对象独有的功能。
示例:
# 首先定义一个类
class Student:
# 在类中定义的数据属于公共的数据,在类中定义的函数属于公共方法
school = '清华大学'
# 让对象拥有独有的数据
def __init__(self, name):
self.name = name
# 定义在类中的函数,我们称之为方法
def choice_course(self):
print('%s正在选课' % self.name)
stu = Student('jason')
stu1 = Student('jack')
# 1.在全局给对象独自添加一个功能。
def func():
print("我在全局")
# 2.将功能添加给对象
stu.func = func
# 3.但是如果在全局也不是独有的
stu.func()
# 谁调用类中的方法就属于谁的独有的功能
stu.choice_course() # jason正在选课
stu1.choice_course() # jack正在选课
"""
因此python解释器在针对这类问题添加了一个非常哇塞的特性
定义在类中的函数默认是绑定给对象的(相当于是对象独有的方法)
"""
动静态方法
动静态方法专门针对在类体代码中编写的函数
-
绑定给对象的方法
直接在类体代码中编写即可
对象调用会自动将对象当作第一个参数传入,类调用则有几个形参就需要传几个实参。
class Student: # 在类中定义的数据属于公关的数据,在类中定义的函数属于公共方法 school = '清华大学' # 定义在类中的函数,我们称之为方法 def choice_course(self): print('正在选课') stu = Student() """ 对象在调用类中的方法,会自动将对象当作第一个参数传入 后面需要几个参数,在根据数量传入即可 """ stu.choice_course() # jason正在选课 # 类在调用类中的方法,里面需要几个参数则传入几个参数 Student.choice_course(111) -
绑定给类的方法
在类体代码方法上面加入装饰器@classmethod
类调用会自动将类当作第一个参数传入,对下个调用会自动将产生对象的类当作参数传入
class Student: # 在类中定义的数据属于公关的数据,在类中定义的函数属于公共方法 school = '清华大学' @classmethod # 绑定给类的方法 def choice_course(cls): # cls用于接收类 print('正在选课') stu = Student() Student.choice_course() # 相当于 Student.choice_course(Student) stu.choice_course() # stu.choice_course(Student) -
静态方法
在类体代码方法上面加入装饰器@staticmethod
无论谁来调用都必须按照普普通通的函数的传参方式
class Student: # 在类中定义的数据属于公关的数据,在类中定义的函数属于公共方法 school = '清华大学' @staticmethod # 静态方法 def choice_course(a,b): # 普通的函数传承 print('正在选课') stu1 = Student() Student(111,222) stu1.sleep(1, 2)
面向对象三大特性之继承
面向对象有着三大特性分别是,继承、封装、多态。
-
继承的含义
在现实生活中,继承用来描述人与人之间的资源关系,比如子承父业,(儿子也拥有了父亲所有的资源)
而编程世界里,继承其实就是用来描述类与类之间数据的关系,比如类A继承了类B(拥有了类B里面所有的数据和功能)
-
继承的目的
继承的目的就是为了节省代码编写,其中可以继承一个也可继承多个。
-
继承的操作
class 类名(被继承的类名):
pass
定义类的时候在类名后加括号,括号内填入需要继承的类名。
我们将被继承的类,也就是括号内的类称之为,父类或基类或者超类。
将继承类的类称为,子类或者派生类。平常最常称呼的就是父类子类。
示例:
class Fatherclass1: def Father1(self): print("this Father1号") class Fatherclass2: def Father2(self): print("this Father2号") class Fatherclass3: def father3(self): print("my Father3号") # 括号内可以填写一个父类,也可以填写多个父类 class Subclass(Fatherclass1, Fatherclass2, Fatherclass3): print("my Sub_class ") """ 目前掌握从左到右查找每个父类中的属性即可 """
继承的本质
当多个类中有同样的数据或者功能,为了避免重复劳。
将多个类其中相同的数据和功能抽出创建一个新的父类,让其他需要使用它里面功能和数据的去类继承它。
使用继承,白嫖父类其中的数据和功能。
抽象:将多个类共同的数据或者功能抽取出来形成一个基类
继承:从上往下白嫖各个基类中的数据和功能
对象:数据和功能的结合体
类:多个对象相同的数据和功能的结合体
父类:多个类相同的数据和功能的结合体
综上所述,一切都是为了节省代码。
名字的查找顺序
-
在不继承的情况下名字的查找顺序
先从对象自身查找,没有的话再去产生该对象的类中查找 对象>>>类
class Student: school = '清华大学' def choice_course(self): print('正在选课') # 1.产生一个空对象 stu1 = Student() # 2.对象查找school print(stu1.school) # 清华大学 """ 自身名称空间没有,会去产生对象的类中查找 在创建对象的类中找到了school>>>: 清华大学 """ # 3.对象在自身的名称空间内产生了一个新的 school stu1.school = '北京大学' # 4.对象查找school print(stu1.school) # 北京大学 """ 先从对象自身的名称空间查找school 此时的对象自身的名称空间已经有了新school 那么第一个找的是对象自身的名称空间,找到了school>>>:北京大学 """ # 5.类在查找school 找的是类中的school>>>:清华大学 print(Student.school) # 清华大学 -
单继承的情况下名字的查找顺序
先从对象自身查找,然后是产生该对象的类,然后是一个个父类 对象>>>类>>>父类
# 示例1 class A: name = 'from A' pass class B(A): name = 'from B' pass class C(B): name = 'from C' pass class MyClass(C): name = 'from MyClass' pass obj = MyClass() # 查找名字name print(obj.name) """ 1.先从对象自身查找,对象自身没有 2.再去产生对象的类中查找,如果有则找到。 3.如果没有,再去看产生对象的类中有没有继承父类,如果有则去父类中查找 4.父类中如果有则找到,如果没有再看父类有没有继承类如果有则取其继承的类中查找 5.依次类推知道找到这个名字 列如: 对象>>>类>>>父类>>>父类的父类>>>...... """ # 示例2 # 定义一个类A1 class A1: # A1的方法1 def func1(self): print('from A1 func1') # A1的方法2 def func2(self): print('from A1 func2') self.func1() # obj.func1() # 定义一个类MyClass,又继承了父类A1 class MyClass(A1): # MyClass的方法1 def func1(self): print('from MyClass func1') # 2.MyClass产生一个空对象 obj = MyClass() # 对象查找func2 obj.func2() """ 1.先从对象自身查找,对象自身没有 2.再去产生对象的类 MyClass中查找,产生对象的类 MyClass中也没有 3.再去产生对象的类 MyClass继承的父类A1中查找 4.父类A1中有func2,执行父类A1中的func2,此时的func2中又调用了func1 5.那么又开始从对象自身查找func1,对象自身没有 6.再去产生对象的类 MyClass中查找,产生对象的类 MyClass中有func1,执行func1。 ***** 只要涉及到对象查找名字 几乎要回到最开始的位置依次查找 """ -
多继承的情况下名字的查找顺序
也可以使用类点mro()方法查看该类产生的对象名字的查找顺序
如果涉及到对象查找名字,那么几乎都是 对象>>>类>>>父类......
3.1非菱形继承(最后不会归总到一个我们之定义的类上)
# 示例1 class F(): name = 'from F' class E(): pass class D(): pass class C(F): pass class B(E): pass class A(D): pass class MyClass(A,B,C): pass obj = MyClass() # 查找名字name print(obj.name) # 'from F'深度优先(每个分支都走到低)

3.2多继承的情况下名字的查找顺序
非菱形继承(最后归总到一个我们中定义的类上)
# 示例1
class G():
name = 'from G'
class F(G):
pass'
class E(G):
pass
class D(G):
pass
class C(F):
pass
class B(E):
pass
class A(D):
pass
class MyClass(A,B,C):
pass
obj = MyClass()
# 查找名字name
print(obj.name) # 'from G'
广度优先(前面几个分支都不会走最后一个类,最后一个分支才会走)

经典类与新式类
-
经典类
不继承object或其子类的类(什么都不继承的类)
-
新式类
继承了object或其子类的类
-
版本的不同
在python3中所有的类默认都会继承object
也就意味着python3里面只有新式类
在python2中有经典类和新式类
由于经典类没有核心功能所以到了python3中直接被 砍掉了
-
示例
# python2中的经典类和新式类 # 经典类 class MyClass: pass # 新式类 class MyClass(object): pass # python3中的类默认都是新式类 class MyClass: # 不加括号不写object也会被默认为此操作(object) pass """ 以后我们在定义类的时候,如果没有想要继承的父类 一般推荐一下写法 class MyClass(object): pass 其目的是为了兼容python2 """
派生方法
子类中定义类与父类一摸一样的方法并且扩展了该功能>>>:派生
class Person(object):
def __init__(self, name, age, gender):
self.name = name
self.age = age
self.gender = gender
class Teacher(Person):
def __init__(self, name, age, gender, salary):
# 使用super 专门用于子类调用父类的方法
super.__init__(name,age,gender)
# 自己在添加需要补充的数据
self.salary = salary
"""
当一个子类继承了一个父类,子类中需要使用了父类的功能。
但又觉得父类中的功能不够全面,又在其功能上做一些扩展,这就就叫做派生
"""

浙公网安备 33010602011771号