面向对象之多态以及进阶

一.多态

1.什么是多态?

多态是一种事物具备多种不同的形态

官方解释:多个不同类对象可以响应同一个方法,产生不同的结果

2.多态的好处:

  对于使用者而言,大大的降低了使用难度

3.怎么实现多态:

python中处处都是多态,例如:接口,抽象类,鸭子类型,都可以写出具备多态的代码,其中最简单的就是鸭子类型。

案例:

 1 class Ji:
 2     def bark(self):
 3         print('咯咯咯..')
 4    
 5 class Duck:
 6     def bark(self):
 7         print('嘎嘎嘎...')
 8 
 9 class E:
10     def bark(self):
11         print('鹅鹅鹅...')
12 j = Ji()
13 y = Duck()
14 e = E()
15 
16 def manage(obj):
17     obj.bark()
18 manage(j)
19 manage(y)
20 manage(e)

二.进阶部分

1.isinstance

 判断一个对象是否是某个类的实例

1 class A:
2     pass
3 a = A()
4 isinstance(a,A)

 参数1:要判断的对象

参数2:要判断的类型

2.issubclass

 判断一个类是否是另一个类的子类

1 class A:
2     pass
3 
4 class B(A):
5     pass
6 issubclass(B,A)

  参数1:是子类

  参数2:是父类

3.__str__

在对象被转换为字符串时,转换的结果就是这个函数的返回值

使用场景:我们可以利用该函数来自定义,对象的打印格式

1 class B:
2 
3     def __str__(self):
4         return '是一个对象'
5 b = B()
6 print(b)
7 #是一个对象

4.__del__

执行时机:手动删除对象时立刻执行,或是程序运行结束时也会自动执行

使用场景:当你的对象在使用过程时,打开了不属于解释器的资源例如:文件,网络端口

 1 class FileTool:
 2     
 3     def __init__(self,path):
 4             self.file = open(path,'rt',encoding='utf-8')
 5             self.a = 100
 6     
 7     def read(self):
 8             return self.file.read()
 9 
10     def __del__(self):
11             self.file.close()
12 
13 tool = FileTool('a.txt')
14 print(tool.read())

5.__call__

执行时机:在调用对象时自动执行(就是对象加括号时)

1 class A:
2     def __call__(self,*args,**kwargs):
3             print("call run")
4             print(args)
5             print(kwargs)
6 
7 a = A()
8 a(1,a=100)

6.__slots__

这是一个类属性,用于优化对象内存占用

优化的原理:将原本不固定的属性数量,变得固定了

这样的解释器就不会为这个对象创建名称空间,所以__dict__也没了

从而达到减少内存开销的效果

另外当类中出现了slots时将导致这个类的对象无法在添加新的属性

 1 import sys
 2 class Person:
 3     __slots__=['name']
 4     def __init__(self,name):
 5         self.name = name
 6 p = Person("jack")
 7 
 8 #查看内存的占用
 9 print(sys.getsizeof(p))
10 p.age = 20  #无法添加,因为已经被限制死了,只有一个name属性
11 print(p.__dict__) #此时的dict也没有了

7.点方法  getattr setattr delattr

getattr 用点访问属性的时候如果属性不存在时执行

setattr 用点设置属性时执行

delattr 用del 对象.属性 时 删除属性时执行

 1 class A:
 2 
 3     def __getattr__(self, item):
 4         print('__getattr__')
 5 
 6     def __setattr__(self, key, value):
 7         print('__setattr__')
 8 
 9     def __delattr__(self, item):
10         print('__delattr__')
11 
12 a = A()
13 a.age = 16
14 print(a.age)
15 del a.age
16 #执行结果:
17 #__setattr__
18 #__getattr__
19 #None
20 #__delattr__
 1 class A:
 2 
 3     def __getattr__(self, item):
 4         print('__getattr__')
 5         return self.item
 6 
 7     def __setattr__(self, key, value):
 8         print('__setattr__')
 9         self.__dict__[key] = value
10 
11     def __delattr__(self, item):
12         print('__delattr__')
13         self.__dict__.pop(item)
14 
15 a = A()
16 a.age = 16
17 print(a.__dict__)
18 del a.age
19 print(a.__dict__)
20 #执行结果:
21 #__setattr__
22 #{'age': 16}
23 #__delattr__
24 #{}

getattribute 该函数也是用来获取属性

在获取属性时如果存在getattribute则先执行该函数,如果没有拿到属性则继续调用getattr函数,如果拿到了则直接返回。

8.[]的实现原理 getitem setiteem delitem

任何的符号 都会被解释器解释称特殊含义,例如. [] ()

getitem 当你用中括号去获取属性时 执行

setitem 当你用中括号去设置属性时 执行

delitem 当你用中括号去删除属性时 执行

 1 class A:
 2     def __getitem__(self,item):
 3         print('__getitem__')
 4         return self.__dict__[item]
 5 
 6     def __setitem__(self, key, value):
 7         print('__setitem__')
 8         self.__dict__[key] = value
 9 
10     def __delitem__(self, key):
11         print('__delitem__')
12         self.__dict__.pop(key)
13 
14 a = A()
15 a['name'] = 'jack'
16 print(a['name'])
17 print(a.__dict__)
18 del a['name']
19 print(a.__dict__)
20 #执行结果:
21 __setitem__
22 __getitem__
23 jack
24 {'name': 'jack'}
25 __delitem
26 {}

9.运算符重载

当我们在使用某个符号时,python解释器都会为这个符号定义一个含义,同时调用对应的处理函数,当我们需要自定义对象的比较规则时,就可以在子类中覆盖 大于,小于,等于等一系列方法

案例:

 1 class Student:
 2     def __init__(self,name,height,age):
 3         self.name = name
 4         self.age = age
 5         self.height = height
 6 
 7     def __gt__(self, other):
 8         return self.height>other.height
 9 
10     def __lt__(self, other):
11         return self.height<other.height
12 
13     def __eq__(self, other):
14         if self.name == other.name and self.height == other.height and self.age == other.age:
15             return True
16         return False
17 
18 stu1 = Student("jack",180,28)
19 stu2 = Student("jack",180,28)
20 print(stu1 < stu2)
21 print(stu1 == stu2)

10.迭代器协议

迭代器是指具有__iter__和__next__的对象

我们可以为对象增加这两个方法来让对象变成一个迭代器

 1 class MyRange:
 2 
 3     def __init__(self,start,end,step):
 4         self.start = start
 5         self.end = end
 6         self.step = step
 7 
 8     def __iter__(self):
 9         return self
10 
11     def __next__(self):
12         a = self.start
13         self.start += self.step
14         if a < self.end:
15             return a
16         else:
17             raise StopIteration
18             
19 for i in MyRange(1,10,2):
20     print(i)

11.上下文管理

在python中,上下文可以理解为是一个代码区间,一个范围,例如with open 打开的文件尽在这个上下文中有效

涉及到两个方法:

  enter

    表示进入上下文,(进入某个场景了)

  exit

    表示退出上下文,(退出某个场景)

 1 class MyOpen(object):
 2 
 3 
 4     def __init__(self,path):
 5         self.path = path
 6 
 7     def __enter__(self):
 8         self.file = open(self.path)
 9         print("enter.....")
10         return self
11 
12     def __exit__(self, exc_type, exc_val, exc_tb):
13         print("exit...")
14         # print(exc_type,exc_val,exc_tb)
15         self.file.close()
16         return True
17 
18 
19 with MyOpen("a.txt") as m:
20     # print(m)
21     # print(m.file.read())
22     "123"+1
23 
24 # m.file.read()

当执行with语句时,会先执行enter

当代码执行完毕后执行exit,或者代码遇到了异常会立即执行exit,并传入错误信息,包含错误的类型,错误的信息,错误的追踪信息

注意:

  enter函数应该返回对象自己

  exit函数可以有返回值,是一个bool类型,用于表示异常是否被处理,仅在上下文中出现异常有用,如果为True,则意味着异常已经被处理了  如果为 False 异常未被处理,程序将终端报错

  

posted @ 2019-07-29 16:34  s686编程传  阅读(154)  评论(0编辑  收藏  举报