面向对象编程
多继承
所谓多继承,即子类有多个父类,并且具有它们的特征。
class Father(object):
def run(self):
print("Father会跑")
class Father1(object):
def run(self):
print("Father1会跑")
class Son(Father, Father1):
pass
s = Son()
s.run() # Father会跑 左边优先
class GrandFather(object):
def sleep(self):
print("GrandFather 睡觉")
class Father(GrandFather):
def run(self):
print("Father 会跑")
class Father1(object):
def run(self):
print("Father1会跑")
def sleep(self):
print('Father1 睡觉')
class Son(Father, Father1):
pass
s = Son()
s.sleep() # GrandFather 睡觉 左边一条路走到底
class GrandFather(object):
def sleep(self):
print("GrandFather 睡觉")
class Father(GrandFather):
def run(self):
print('Father 会跑')
class Father1(GrandFather):
def run(self):
print("Father1 会跑")
def sleep(self):
print("Father1 睡觉")
class Son(Father, Father1):
pass
s = Son()
s.sleep() # Father1 睡觉 同一个根时,根最后执行
print(Son.__mro__) # C3算法
"""
python支持多继承
- 1.左边优先
- 2.一条道路走到底
- 3.同一个根时,根最后执行
"""
多态
多态的概念是应用于 Java 和 C# 这一类强类型语言中,而 Python 崇尚"鸭子类
型"
动态语言调用实例方法时不检查类型,只要方法存在,参数正确,就可以调用。
这就是动态语言的“鸭子类型”,它并不要求严格的继承体系,一个对象只要
“看起来像鸭子,走起路来像鸭子”,那它就可以被看做是鸭子。
所谓多态:定义时的类型和运行时的类型不一样,此时就成为多态。
class Person(object):
def print_self(self):
print('自我介绍')
class Man(Person):
def print_self(self):
print('man的自我介绍')
def print_self(obj):
obj.print_self()
zs = Person()
# zs.print_self()
print_self(zs)
hansen = Man()
# hansen.print_self()
print_self(hansen)
面向对象编程
魔法方法介绍
在Python中,有一些内置好的特定方法,这些方法在进行特定的操作时会自动被调
用,称为魔法方法。
魔法方法的命名总是被4120双下划线包围,比如__ 名称 __
常用魔法方法
__doc__
:用来查看类的说明文档
练习:
查看列表类的说明文档
print(list().__doc__)
li = list('abc')
print(li.__doc__)
s = '1234'
print(s.__doc__)
class Demo(object):
"""
我是注释
"""
pass
d = Demo()
print(d.__doc__)
print(Demo.__module__) # __main__ 指的是当前文件所在的模块
print(Demo.__class__) # Demo类是type的对象 <class 'type'>
print(d.__class__) # d是Demo对象
常用魔法方法
__dict__
:用于获取类或者实例的属性字典
注意:
- 实例属性存储在对象中,所以通过
对象 .__dict__
获取的是实例属性 - 除实例属性以外的成员都存储在类中,所以通过
类 .__dict__
来获取
class Demo(object):
country = '中国'
def __init__(self):
self.name = 'deng'
self.__age = 18
def test(self):
self.gender = 'female'
print('test')
d = Demo()
d.test()
print(d.__dict__) # 字典,对象去访问,只能访问到对象中的成员(实例属性)
print(Demo.__dict__) # 字典,类名去访问,就可以访问到类当中的成员(除了实例属性之外的属性与方法)
print(d.__dir__()) # 列表,返回所有的成员(__dict__更倾向于 是__dir__()的子集)
常用魔法方法
__del__()
:叫做析构方法。当由该类创建的实例对象,被删除或者说在内存中被释
放,将会自动触发执行。
总结:
- 当代码
全部执行完毕
才自动触发__del__()
- 如果需要提前触发,则需要通过
del
关键字,删除所有对象后触发__del__()
注意:
此方法一般不需要定义,因为 Python 是一门高级语言,程序员在使用时无需关心
内存的分配与释放,一般都是交给 Python 解释器来执行。所以,析构函数的调用
是由解释器在进行垃圾回收时自动触发执行。
class Demo(object):
def __del__(self):
print('我被回收了')
d = Demo() # 1
print('--'*10)
print('--'*10)
# 2 在所有代码都执行完毕之后,会自动执行 __del__方法
class Demo(object):
def __del__(self):
print('我被回收了')
d = Demo() # 1
print('--'*10) # 2
del d # 3 通过关键字 del 将对象删除则会主动的执行__del__方法
print('--'*10) # 4
class Demo(object):
def __del__(self):
print('我被回收了')
d = Demo() # 1
d1 = d
print('--'*10) # 2
del d
del d1 # 3
print('--'*10) # 4 只有当对象全部释放 才会自动触发__del__
"""
注意:python解释器会有自动的垃圾回收机制,所以,我们并不需要主动的去封装__del__()
"""
常用魔法方法
call() :用于将对象变成一个可调用的对象。也就是说,当一个类中有
call() 方法时,其实例化得到的对象便是可调用的 (callable)
class Demo(object):
def __init__(self):
print('aaa')
def __call__(self, *args, **kwargs):
print('我可以调用了奥')
d = Demo()
d() # Demo()() TypeError: 'Demo' object is not callable
常用魔法方法
new() :用于创建与返回一个对象。在类准备将自身实例化时调用。
练习:
所示右边代码打印输出的顺序?
A.init,new
B.init
C.new
D.__new,init
class Dome(object):
def __init__(self):
print('__init__')
def __new__(cls, *args, **kwargs):
# 重写了父类的new方法,对象并没有创建成功,所以不会再触发__init__方法
print('__new__')
d = Dome()
# 1.__init__创建对象之后自动调用的方法
# 2.__new__用来创建对象的
class A(object):
def sleep(self):
print('创建对象')
class B(A):
def sleep(self):
print('我在玩')
d = B()
d.sleep() # 我在玩
常用魔法方法
对象创建执行顺序
- 通过
__new__()
方法 创建对象
- 通过
- 并将
对象返回
,传给__init__()
练习:
在自定义类中实现创建对象
思路:
- 并将
- 重写父类
__new__()
方法 - 并且在该方法内部,调用父类的
__new__()
方法
class Dmeo(object):
def __init__(self):
print('__init__')
def __new__(cls, *args, **kwargs):
print('__new__')
# 重写父类的__new__,还需要执行父类的代码
# super().__new__(cls) # 执行了父类创建对象的代码,还并没有自动的执行__init__
return super().__new__(cls) # 将对象返回出去,自动执行__init__方法
d = Dmeo()
# __new__
# __init__
注意
- 在创建对象时,一定要将对象返回,才会自动触发
__init__()
方法 -
__init__()
方法当中的 self ,实际上就是__new__
返回的实例,也就是该对象
__init__()
与__new__()
区别: -
__init__
实例方法,__new__
静态方法 -
__init__
在对象创建后自动调用,__new__
创建对象的方法
单例模式介绍
单例模式是一种常用的软件设计模式。也就是说该类只包含一个实例。
通过单例模式可以保证系统中一个类只有一个实例而且该实例易于外界访问,从而
方便对实例个数的控制并节约系统资源。如果希望在系统中某个类的对象只能存在
一个,单例模式是最好的解决方案。
通常应用在一些资源管理器中,比如日志记录等。
class Single(object):
def __new__(cls, *args, **kwargs):
return super().__new__(cls)
s = Single()
s1 = Single()
print(id(s)) # 25891376
print(id(s1)) # 25892176
'''
当对象不存在的时候-->创建对象
当对象已经存在的时候-->永远只返回当前对象
'''
class Single(object):
__isinstance = None # 1.类属性,建立标识
def __new__(cls, *args, **kwargs):
if cls.__isinstance is None:
cls.__isinstance = super().__new__(cls) # 2.将一个对象存储到__isinstance类属性中。
# 3.返回cls.__isinstance,也就是我们的对象
return cls.__isinstance
else:
# 4.__isinstance不为None,意味着它已经储存着一个对象,我们直接将放回出去即可
return cls.__isinstance
s = Single()
s1 = Single()
s2 = Single()
print(id(s)) # 23730128
print(id(s1)) # 23730128
print(id(s2)) # 23730128
思路
- 当对象不存在时,创建对象
- 当对象存在时,永远返回当前已经创建对象