多继承
所谓多继承,即子类有多个父类,并且具有它们的特征。
情景一,多个父亲
class Father(GrandFather):
def Car(self):
print("继承父亲的房子")
class Father1(object):
def House(self):
print("继承干爹的房子")
class Son(Father, Father1): # 用有相同的方法时,左边优先执行
s = Son()
s.House()#继承父亲的房子
情景二,父亲继承爷爷的房子,儿子继承父亲和干爹的房子
class GrandFather(object):
# def House(self):
# print("继承爷爷的房子")
pass
class Father(GrandFather):
def Car(self):
print("继承父亲的房子")
class Father1(object):
def House(self):
print("继承干爹的房子")
class Son(Father, Father1): #左边执行完了,才执行父类
pass
s = Son()
s.House()#继承爷爷的房子
情景三,父亲和叔叔继承爷爷的房子,儿子继承父亲和叔叔的房子
# 情景三
class GrandFather(object):
# def House(self):
# print("继承爷爷的房子")
pass
class Father(GrandFather):
def Car(self):
print("继承父亲的房子")
class uncle(GrandFather):
def House(self):
print("继承叔叔的房子")
class Son(Father, uncle): # 同一个根的时候,跟随最后执行
pass
s = Son()
s.House()#继承叔叔的房子,
若自己定义了相同的方法,优先执行自己的方法
class GrandFather(object):
# def House(self):
# print("继承爷爷的房子")
pass
class Father(GrandFather):
def Car(self):
print("继承父亲的房子")
class uncle(GrandFather):
def House(self):
print("继承叔叔的房子")
class Son(Father, uncle): # 用有相同的方法时,左边优先执行,左边执行完了,才执行父类
def House(self):
print("自己的房子")
s = Son()
s.House()#自己的房子
多态
多态的概念是应用于java和c#这一类强类型语言中,而python崇尚“鸭子类型”
动态语言调用实例方法时不检查类型,只要方法存在,参数正确,就可以调用。这就是动态语言的“鸭子类型”,它并不要求严格的继承体系,一个对象只要“看起来像鸭子,走起路来像鸭子”,那么它就可以被看作是鸭子。
所谓多态:定义时的类型和运行时的类型不一样,此时就成为多态。
# 传入不同的对象,产生的结果不同
class Animal(object):
def Who(self):
print("动物")
class Dog(Animal):
def Who(self):
print("狗狗")
class Cat(Animal):
def Who(self):
print("小猫")
def func(obj): #obj = cat
obj.Who() # cat.Who
dog = Dog()
dog.Who() # 狗狗
cat = Cat()
cat.Who() # 小猫
func(dog)# 狗狗
func(cat)# 小猫 传入不同的对象,产生不同结果
''' 1,多态必须发生在父类与子类之间(继承) 2,子类重写父类的方法 3.增加了程序的可拓展性,增加了程序的灵活性 '''
魔法方法
在python中,有一些内置好的特定方法,这些方法在进行特定的操作时会自动被调用,称为魔法方法。
魔法方法的命名总是被双下划线包围,比如__名称__
常用的魔法方法
__doc__:用来查看类的说明文档
练习:
查看类的说明文档
# doc用来查看说明文档
print(list().__doc__)
# If no argument is given, the constructor creates a new empty list.
# The argument must be an iterable if specified.
class Demo(object):
'''
知识内容
'''
pass
print(Demo().__doc__) # 知识内容
__dict__:用于获取类或实例的属性字典
注意:
~实例属性存储在对象中,所以通过对象__dict__获取的是实例属性
~除实例属性以外的成员都存储在类中,所以通过类__dict__来获取
class Demo(object):
country = "China"
def __init__(self):
self.name="zs"
self.__age=19
def test(self):
self.gender="男"
d = Demo()
d.test()
print(d.__dict__) #返回类型是字典,只能访问实例属性
print(Demo.__dict__)#返回类型是字典,只能访问实例属性
__del__():叫做析构方法。当由该类创建的实例对象,被删除或者说在内存中被稀释放,将会自动触发执行。
总结:
~当代码全部执行完毕才自动触发__del__()
~如果需要提前触发,则需要通过del关键字,删除所有对象后触发__del__()
注意:
此方法一般不需要定义,因为python是一门高级语言,程序员在使用是无需关心内存分配与释放,一般都是交给python解释器来执行。所以,析构函数的调用是由解释器在进行垃圾回收时自动触发执行。
class Demo(object):
def __del__(self):
print("3释放了")
d = Demo()
# print("1")
# print("2")#只有当对象全部执行完毕,会自行执行__del__方法
# d1 = d
print('1')
del d # 通过关键字del,将对象删除
print('2')
__call__():用于将对象变成一个可调用的对象,也就是说,当一个类中有__call__()方法时,其实例化得到的对象便是可调用的(callable)
class Demo(object):
def __init__(self):
print('__init__')
def __call__(self, *args, **kwargs):
print('__call__')
d = Demo()
d() #对象.方法
__new__():用于创建与返回一个对象。在类准备将自身实例化时调用。
练习:代码打印输出顺序
class Demo(object): # 父类的new:大别墅 重写的new方法:毛坯房
def __init__(self): # 创建对象之后主动触发__init__方法
print("__init__")
def __new__(cls, *args, **kwargs): # 重写的,本身是这样
# 重写了父类的new方法,对象并没有创建成功
print("__new__") # 创建对象代码
return super().__new__(cls) # 找父类的new方法,cls当前类
d = Demo()#__new__创建对象,先主动触发new方法创建对象,创建完对象主动触发init方法
print(d)
A.__init__,__new__
B.__init__
C.__new__
D.__new__,__init__
单例模式
单例模式是一种常用的软件设计模式。也就是说该类只包含一个实例。
通过单例模式可以保证系统中一个类只有一个实例而且该实例易于外界访问,从而方便对实例个数的控制并节约系统资源。如果希望在系统中某个类的对象只能存在一个,单例模式是最好解决方案。
通常应用在一些资源管理器中,比如日志记录等。
''' 单例模式---只需要一个对象 __new__方法创建对象, 当对象不存在的时候--创建对象 当对象已经存在的时候--返回当前已经存在的对象 定义类 条件判断 new方法 return 如果对象存在 保存下来 '''
class Single(object):
__instance = None
def __new__(cls, *args, **kwargs):
if cls.__instance is None:
Single.__instance = super().__new__(cls) #调用父类方法,进行保存
return Single.__instance
else:
return Single.__instance
s = Single()
s1 = Single()
print(id(s))
print(id(s1))