一.多继承(寻找方法)
主要学习多继承中的寻找方法的方式:分别是深度优先和广度优先
1.当类是经典类时,多继承情况下,会按照深度优先方式查找
2.当类是新式类时,多继承情况下,会按照广度优先方式查找
新式类和经典类的区分:
如果当类继承于object或者其父类继承于object,那么该类就是新式类
以后推荐使用新式类,新式类中包含有更多的功能
深度优先和广度优先:都是直接父类从左向右查询:
经典类:深度优先:
class D: ...... pass class B(D): ...... pass class C(D): ...... pass class A(B,C): ..... def bar(): self.search()
若是在A中没有该search函数---->则去(左父类)B类中去寻找,若是B类中也没有---->则去B父类(D)(向更深一级去查询) 若是D中也没有----->再去(A右父类C)中去查询 查找顺序 A--->B ---->D---->C 若是查找到了,则停止,没有则报错
新式类:广度优先
class D(object):
......
pass
class B(D):
......
pass
class C(D):
......
pass
class A(B,C):
.....
def bar():
self.search()
若是在A中没有该search函数---->则去(左父类)B类中去寻找,若是B类中也没有---->再去(A右父类C)中去查询--->则去B父类(D)(向更深一级去查询)
查找顺序 A--->B ---->C---->D 若是查找到了,则停止,没有则报错
上面只是简单介绍,并不完整,而且mro并未介绍,所以上面的继承关系,虽然易于理解,但是可能不是太准确。
详细请看:python---方法解析顺序MRO(Method Resolution Order)<主要解决类中super方法>
二.多态(多种形态)
意味着可以对不同类的对象使用同样的操作(就算不知道变量所引用的对象类型是什么,还是能对他进行操作,而他也会根据对象或类的不同而表现出不同的行为)
class Foo: def f1(self): print("foo") class Bar: def f1(self): print("bar") def func(obj): #obj有多种形态,可以是Foo,也可以是Bar obj.f1() func(Foo()) func(Bar())
毁掉这种多态的形式是使用type,isinstance或者issubclass函数等。如果可能尽量避免使用这些函数。真正重要的是让对象按照你所希望的方式工作,而不是在意是否是正确的类型。
补充:类和对象在内存中的存在形式:
类以及类中的方法在内存中只有一份,而根据类创建的每一个对象都在内存中需要存一份
三.类的成员(主要是属性)
分为三大类:字段,方法和属性
-----字段:分为普通字段,静态字段 类中成员 -----方法:分为普通方法,类方法,静态方法 -----属性:普通属性
(一)字段:
普通字段属于对象,静态字段属于类(静态字段也可以使用self(对象)访问,但是不能进行修改,修改的话,会变为普通字段,这时使用对象访问则只会访问到普通字段,而不是静态字段)
# coding:utf8 # __author: Administrator # date: 2018/4/17 0017 # /usr/bin/env python class Test: name = "asda" def __init__(self,age): self.age = age def get(self): print(self.name,self.age) #直接访问普通字段 obj = Test(10) print(obj.age) print(obj.name) #可以访问 obj.get() #直接访问静态字段 print(Test.name)
两种字段在内存中存放方式:
静态字段只存放一个,普通字段随对象的创建而增加。
obj = Test(10) obj2 = Test(11) print(id(obj.age),id(obj2.age)) #497898560 497898592 不同的对象,包含属于自己的普通字段 print(obj.age,obj2.age) #10 11 print(id(obj.name),id(obj2.name),id(Test.name)) #5282648 5282648 5282648 但是包含同一个静态字段
print(obj.name,obj2.name) #asda asda
一般对静态字段的访问,我们最好使用类来访问.因为我们若是使用对象来访问静态字段,对其进行修改时,往往达到不一样的预期(使用对象修改的话,在该对象中该字段会变为普通字段,这时使用对象访问则只会访问到普通字段,而不是静态字段,也不会影响到其他对象数据。达不到统一修改数据)
obj.name = "gaega" print(id(obj.name),id(obj2.name),id(Test.name)) #12059008 5282648 5282648 只是在内存中对其有生成了一个普通字段,叫做name print(obj.name,obj2.name,Test.name) #gaega asda asda
相同名字的普通字段和静态字段的访问:
class Test: name = "asda" def __init__(self,name,age): self.age = age self.name = name def get(self): print(self.name,self.age,Test.name) obj = Test("adadfafwad",10) obj.get() #adadfafwad 10 asda