继承
继承是一种创建新类的方式,如果子类需要父类的属性和方法时,就可以使用继承;同样子类也可以有自己的属性和方法
语法:
class Father:
pass # 父类,超类
class Son(Father):
pass # 子类,派生类
注意:在Python中,新建的类可以继承一个或多个父类,继承的作用就是要避免重复轮子、减少代码的冗余。
新式类与经典类
在python2中类分成新式类和经典类,如果有继承父类object则是新式类,否则则为经典类。
在Python3中,全部默认是新式类。
class Demo: # Python2中 经典类
pass
class Demo2(Demo): # 继承了父类object,在Python2中是新式类
pass
d1 = Demo()
d2 = Demo2()
----------------------------------
# 比较继承与无继承两个空类的成员是否一致
print(d1.__dir__()) # 长度26
print(d2.__dir__()) # 长度26
单继承
子类继承父类,可以直接享受父类中已经封装好的方法
所有的类都会继承最大的父类,即object
例如用代码实现下图的逻辑
class GrandFather(object):
def sleep(self):
print('GrandFather sleep')
class Father(GrandFather):
def run(self):
print('Father run')
def drink(self):
print('Father drink')
class Son(Father):
def study_python(self):
print('Son study python')
s = Son()
s.study_python() # Son study python
s.run() # Father run 通过子类的对象可以使用父类的方法
s.sleep() # GrandFather sleep 子类没有则会去父类去找,父类没有则继续会去父类的父类寻找...
s.play() # 报错!!!
重写
需要注意的是,当子类与父类有相同的名称方法时,子类会优先调用执行自身的方法,即子类的方法会覆盖父类的方法,也称为重写。
class GrandFather(object):
def sleep(self):
print('GrandFather sleep 10')
class Father(GrandFather):
def run(self):
print('Father run')
def drink(self):
print('Father drink')
class Son(Father):
def study_python(self):
print('Son study python')
def sleep(self):
print('Son sleep 8')
s = Son()
s.run() # Father run
s.sleep() # Son sleep 8
super()方法
super()函数是调用超类的一个方法
这种方法在执行自己的方法时,也会继承父类的方法
语法:super(type,[,object or type])
- type —> 类
object or type —> 对象或类,一般是指self
# 上面的代码中实现GrandFater sleep 10的代码可以用到的方法是:在20行sleep内部加入下列代码(任意一条)
super(Son,self).sleep() # Son的对象去调用父类的sleep方法
super.sleep() # 这里可以不传参数
GrandFather.sleep(self) # 通过类名.方法名(sleep)
总结:
单继承:深度优先
- 重写:防止执行父类当真的方法
- self永远是执行该方法的调用者
- super(执行当前类,self).父类中的方法(arg)
注意:
- init()方法也会继承,它同实例方法一致,深度优先
- 私有属性和私有方法不会被继承
```python
init方法继承
class Father(object): def init(self):print('Father')
class Son(Father): pass
s = Son() # Father
class Father(object): def init(self): self.name = “amy” self.__age = 18
def test(self):
print("test")
def __test2(self):
print("__test2")
class Son(Father): def get_test(self):
# print(self.name)
# self.test()
# 注意:私有属性不会被继承
# print(self.__age)
# 注意:私有方法也不会被继承
# self.__test2()
s = Son()
print(s.name)
print(s.__age)
s.get_test()
<a name="Qzk2c"></a>
## 多继承
子类有多个父类,并且具有它们的特征<br />Case 1:<br />
- 左侧优先
```python
class Father(object):
def run(self):
print('Father会跑')
class Father1(object):
def run(self):
print('Father1会跑')
class Son(Father1, Father2):
pass
s = Son()
s.run() # Father会跑
Case 2:
- 左边一条路走到底
```python
class GrandFather(object):
def sleep(self):
print('GrandFather睡觉')
class Father(GrandFather): def run(self): print(‘Father会跑’)
class Father1(object): def run(self): print(‘Father会跑’)
def sleep(self):
print('Father1睡觉')
class Son(Father, Father1): pass
s = Son()
s.sleep() # GrandFather睡觉
print(Son.mro) # C3算法
‘’’
可以理解成继承的顺序
(
Case 3:<br />
- 左边优先,根会最后执行
```python
class GrandFather(object):
def sleep(self):
print('GrandFather睡觉')
class Father(GrandFather):
def run(self):
print('Father会跑')
class Father1(GrandFather):
def run(self):
print('Father会跑')
def sleep(self):
print('Father1睡觉')
class Son(Father, Father1):
pass
s = Son()
s.sleep() # Father1睡觉
print(Son.__mro__)
'''
(<class '__main__.Son'>, <class '__main__.Father'>, <class '__main__.Father1'>, <class '__main__.GrandFather'>, <class 'object'>)
'''
多态
- 多态的概念是应用于 Java 和 C# 这一类强类型语言中,在Python中则崇尚”鸭子类型”
- 动态语言调用实例方法时不检查类型,只要方法存在,参数正确,就可以调用。这就是动态语言的“鸭子类型”,它并不要求严格的继承体系,一个对象只要“看起来像鸭子,走起路来像鸭子”,那它就可以被看做是鸭子。
- 多态就是指定义时的类型和运行时的类型不一样。
```python
class Person(object):
def print_self(self):
print('我是你的机器人')
class Man(Person): def print_self(self): print(‘小胖机器人’)
def print_self(obj): obj.print_self
xp = Person() xp.print_self()
print_self(xp)
fg = Man() fg.print_self()
print_self(fg)
<a name="BSiLs"></a>
# 常用魔法方法
在Python中,有一些内置好的特定方法,这些方法在进行特定的操作时会自动被调用,称为**魔法方法**。<br />魔法方法的命名总是被双下划线包围,比如**__名称__**。
<a name="a0V9e"></a>
## __doc__
- 用来查看类的说明文档
例如查看类里面的注释
```python
class Demo(object):
'''
这里面写的是注释
'''
d = Demo()
print(d.__doc__) # 这里面是注释
print(Demo.__module__) # __main__ 这里面指的是当前文件所在的模块
print(Demo.__class__) # <class 'type'> Demo是type的对象
print(d.__class__) # <class '__main__.Demo'> d是Demo的对象
dict
用来获取类或实例的字典 ```python class Demo(object): country = ‘China’
def init(self):
self.name = '小胖' self.age = 19
def test(self):
self.gender = 'male' print('测试')
d = Demo() d.test() # 测试 print(d.dict) ‘’’ 结果是字典,且只能访问到对象中的属性(实例属性) {‘name’: ‘小胖’, ‘age’: 19, ‘gender’: ‘male’} ‘’’
print(Demo.dict)
‘’’
结果是字典,用类名去访问,就可以访问到类中的成员(除了实例属性之外的属性与方法)
{‘module‘: ‘main‘, ‘country’: ‘China’, ‘init‘:
print(d.dir()) ‘’’ 结果为列表,返回所有的成员(dict更倾向于是dir()的子集) [‘name’, ‘age’, ‘gender’, ‘module‘, ‘country’, ‘init‘, ‘test’, ‘dict‘, ‘weakref‘, ‘doc‘, ‘repr‘, ‘hash‘, ‘str‘, ‘getattribute‘, ‘setattr‘, ‘delattr‘, ‘lt‘, ‘le‘, ‘eq‘, ‘ne‘, ‘gt‘, ‘ge‘, ‘new‘, ‘reduce_ex‘, ‘reduce‘, ‘subclasshook‘, ‘init_subclass‘, ‘format‘, ‘sizeof‘, ‘dir‘, ‘class‘] ‘’’
获取实例属性:
- 对象.__dict__
- 类.__dict__
<a name="GG7yP"></a>
## __del__()
- 析构方法,当由该类创建的实例对象被删除或者在内部被是否,将自动触发执行
Case 1:
```python
class Demo(object):
def __del__(self):
print('我被回收了')
d = Demo()
print('海绵宝宝')
print('牛仔裤')
# 在所有的代码都执行完毕后,会自动的执行__del__方法
运行结果: 海绵宝宝 牛仔裤 我被回收了
Case 2:
class Demo(object):
def __del__(self):
print('我被回收了')
d = Demo()
print('海绵宝宝')
del d # 通过关键字del将对象删除会自动的执行__del__方法
print('牛仔裤')
运行结果: 海绵宝宝 我被回收了 牛仔裤
Case 3:
class Demo(object):
def __del__(self):
print('我被回收了')
d = Demo()
d1 = d
print('海绵宝宝')
del d
print('牛仔裤')
# 只有当对象全部释放,才会自动触发__del__
运行结果: 海绵宝宝 牛仔裤 我被回收了
注意:python解释器中会有自动的垃圾回收机制,所以我们不必主动封装del()
call()
用于将对象变成一个可调用的对象 ```python class Demo(object): def init(self):
print('小胖嘚瑟')
def call(self, args, *kwargs):
print('牛仔裤')
d = Demo() # 小胖嘚瑟 d() # 牛仔裤 d() = Demo()()
**当未有__call__时,会报错 TypeError:'Demo' object is not callable**
<a name="MdjSB"></a>
## __new__()
- 用于创建与返回一个对象,在类准备返回将自身实例化时调用
练习:
```python
class Demo(object):
def __init__(self):
print("__init__")
def __new__(cls, *args, **kwargs):
print("__new__") # 重写了父类的new方法,对象并没有创建成功,所以不会再触发__init__方法
d = Demo()
执行的结果是new
总结:1. init创建对象自动调用的方法;2. new用来创建对象的
扩展:对象的创建顺序
class Demo(object):
def __init__(self):
print('创建对象')
def __new__(cls, *args, **kwargs):
print('--new--') # 重写父类的__new__,还需要执行父类的代码
# super().__new__(cls) # 创建了对象,还并没有自动执行__init__
return super().__new__(cls) # 将对象返回出去,自动执行__init__方法
d = Demo()
单例模式
- 单例模式是一种常用的软件设计模式,该类只有一个实例
- 通过单例模式可以保证系统中一个类只有一个实例而且该实例易于外界访问,从而方便对实例个数的控制并节约系统资源。如果希望在系统中某个类的对象只能存在一个,单例模式是最好的解决方案。
```python
class Single(object):
def new(cls, args, *kwargs):
return super().__new__(cls)
s = Single() s1 = Single() print(id(s)) print(id(s1)) # s和s1的id不同
**总结:**
- 当对象不存在时,创建对象
- 当对象存在时,永远只返回当前对象
```python
class Single(object):
__isinstance = None # 类属性,建立标识
def __new__(cls, *args, **kwargs):
if cls.__isinstance == None:
cls.__isinstance = super().__new__(cls) # 将一个对象存储到__isinstance类属性中
return cls.__isinstance # 返回cls.__isinstance,也是我们的对象
else: # __isinstance不为None,意味着它已经存储一个对象,我们直接将它返回即可
return cls.__isinstance
s = Single()
s1 = Single()
print(id(s))
print(id(s1)) # s和s1的id相同