前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Python面向对象编程Day 27部分

Python面向对象编程Day 27部分

作者头像
py3study
发布2020-01-19 11:52:45
2810
发布2020-01-19 11:52:45
举报
文章被收录于专栏:python3python3

内置函数补充及__getattribute__

isinstance(obj,cls)检查obj是否是类cls的实例,反映族谱关系(不仅父类可以,父类的父类也可以) 

issubclass(subcls,cls)检查subcls是否是cls的子类

__getattribute__属性存不存在都会触发它 ‘大哥’ 里面抛出Attribute Error时交给小弟处理

__getattr__属性不存在触发 ‘小弟

 item系列

item是字典方式触发的

__setitem__

__getitem__

__delitem__

代码语言:javascript
复制
 1 class Foo:
 2     def __getitem__(self, item):
 3         print('getitem',item)
 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 f1=Foo()
15 print(f1.__dict__)
16 # f1.name='egon'  #---->点触发attr系列方法
17 f1['name']='egon'  #--->中括号字典形式触发item系列方法
18 f1['age']=18
19 
20 print('===>',f1.__dict__)
21 
22 # del f1.name
23 # print(f1.__dict__)
24 25 # print(f1.age)
26 del f1['name']
27 print(f1.__dict__)
28 
29 print(f1['age'])

输出

{} setitem setitem ===> {'name': 'egon', 'age': 18} delitem {'age': 18} getitem age 18

__str__和__repr__

代码语言:javascript
复制
 1 class Foo:
 2     def __init__(self,name,age):
 3         self.name=name
 4         self.age=age
 5     def __repr__(self):
 6         return 'this is repr'
 7     # def __str__(self):
 8     #     return 'this is str'
 9 f1=Foo('cy',23)
10 print(f1)   #str(f1)-->f1.__str__()

输出

this is repr

st函数或者print函数--->obj.__str__()

repr函数或者交互式解释器--->obj.__repr__()

如果__str__没被定义,那就使用__repr__来代替输出

str和repr返回的必须是字符串,否则抛出异常

自定制format

代码语言:javascript
复制
 1 format_dic={
 2     'ymd':'{0.year}{0.mon}{0.day}',
 3     'm-d-y':'{0.mon}-{0.day}-{0.year}',
 4     'y:m:d':'{0.year}:{0.mon}:{0.day}'
 5 }
 6 class Date:
 7     def __init__(self,year,mon,day):
 8         self.year=year
 9         self.mon=mon
10         self.day=day
11     def __format__(self, format_spec):
12         print('执行__format__方法')
13         print('--->',format_spec)
14         if not format_spec or format_spec not in format_dic:
15             format_spec='ymd'
16         fm=format_dic[format_spec]
17         return fm.format(self)
18 d1=Date(2016,12,26)
19 # format(d1) #d1.__format__()
20 print('没设置格式,采用默认格式==>',format(d1))
21 print(format(d1,'ymd'))
22 print(format(d1,'y:m:d'))
23 print(format(d1,'m-d-y'))
24 print('已设定格式但格式不存在,采用默认格式==>',format(d1,'m-d:y'))

输出

执行__format__方法 ---> 没设置格式,采用默认格式==> 20161226 执行__format__方法 ---> ymd 20161226 执行__format__方法 ---> y:m:d 2016:12:26 执行__format__方法 ---> m-d-y 12-26-2016 执行__format__方法 ---> m-d:y 已设定格式但格式不存在,采用默认格式==> 20161226

__slots__

(慎用)是一个类变量,变量值可以是字符串、列表、元组或者可迭代对象(意味着所有实例只有一个数据属性)

  为何使用__slots__?优势在于省内存(字典会占用大量内存,如果有一个属性很少的类,但是有很多实例,为了节省内存可以使用__slots__取代实例的__dict__,设置了__slots__之后,__dict__就没了)

  使用点来访问属性本质就是在访问类或对象的__dict__属性字典(类的字典是共享的,而每个实例是独立的)

  特点:不允许设置其他数据属性。  

代码语言:javascript
复制
 1 class Foo:
 2     __slots__=['name','age']  #{'name':None,'age':None}
 3     # __slots__='name' #{'name':None,'age':None}
 4 
 5 f1=Foo()
 6 # f1.name='egon'
 7 # print(f1.name)
 8 
 9 # f1.age=18  #--->setattr----->f1.__dict__['age']=18
10 
11 # print(f1.__dict__)
12 print(Foo.__slots__)
13 print(f1.__slots__)
14 f1.name='egon'
15 f1.age=17
16 print(f1.name)
17 print(f1.age)
18 # f1.gender='male'
19 
20 
21 f2=Foo()
22 print(f2.__slots__)
23 f2.name='alex'
24 f2.age=18
25 print(f2.name)
26 print(f2.age)

输出

['name', 'age'] ['name', 'age'] egon 17 ['name', 'age'] alex 18

__doc__

定义于开头用来说明文档信息的一个字符串,且无法被继承。

写不写都有,不写默认是None。

__module__和__class__

查看实例来自哪个模块  对象.__module__

查看实例是什么类  对象.__class__

__del__ 析构方法

此方法一般无需定义,因为python是门高级语言,使用时无需关心内存的分配和释放,此工作交由python解释器执行,所以析构函数的调用是由解释器在进行垃圾回收时自动触发执行的,文件执行完毕之后触发该函数执行。

代码语言:javascript
复制
 1 class Foo:
 2     def __init__(self,name):
 3         self.name=name
 4     def __del__(self):
 5         print('我执行啦')
 6 
 7 f1=Foo('alex')
 8 
 9 # del f1    #删除实例会触发__del__
10 del f1.name #删除实例的属性不会触发__del__
11 print('--------------------->')
12 
13 #程序运行完毕会自动回收内存,触发__del__

输出

---------------------> 我执行啦

__call__

对象后面加括号,触发执行。

__next__和__iter__实现迭代器协议

代码语言:javascript
复制
 1 class Foo:
 2     def __init__(self,n):
 3         self.n=n
 4     def __iter__(self):
 5         return self
 6 
 7     def __next__(self):
 8         if self.n == 13:
 9             raise StopIteration('终止了')
10         self.n+=1
11         return self.n
12 
13 f1=Foo(10)
14 
15 for i in f1:  # obj=iter(f1)------------>f1.__iter__()
16      print(i)  #obj.__next__()

输出

11 12 13

  迭代器协议实现斐波那契数列

代码语言:javascript
复制
 1 class Fib:
 2     def __init__(self):
 3         self._a=1
 4         self._b=1
 5 
 6     def __iter__(self):
 7         return self
 8     def __next__(self):
 9         if self._a > 100:
10             raise StopIteration('终止了')
11         self._a,self._b=self._b,self._a + self._b
12         return self._a
13 
14 f1=Fib()
15 print(next(f1))
16 print(next(f1))
17 print(next(f1))
18 print(next(f1))
19 print(next(f1))
20 print('==================================')
21 for i in f1:
22     print(i)

输出

1 2 3 5 8 ================================== 13 21 34 55 89 144

描述符理论

(开发大型框架时用到)

本质是一个新式类,至少实现了__get__()/__set__()/__delete__()中的一个,这也被成为描述符协议。

  __get__():调用一个属性时触发

  __set__():为一个属性赋值时触发

  __delete__():采用del删除属性时触发

描述符有什么用?描述符的作用是用来代理另外一个类的属性的

描述符分为两种:

  数据描述符:至少实现了__get__()和__set__()

  非数据描述符:没实现__set__()

注意事项:

  1.描述符本身应该定义成新式类,被代理的类也应该是新式类;

  2.必须把描述符定义成类属性,而不能定义到构造函数中;

  3.要严格遵循该优先级,从高到低:

    类属性---数据描述符---实例属性---非数据描述符---找不到的属性触发__getattr__()

例:

代码语言:javascript
复制
 1 class Foo:
 2     def __get__(self, instance, owner):
 3         print('===>get方法')
 4     def __set__(self, instance, value):
 5         print('===>set方法',instance,value)
 6         instance.__dict__['x']=value #对b1.__dict__进行修改
 7     def __delete__(self, instance):
 8         print('===>delete方法')
 9 
10 class Bar:
11     x=Foo() #描述符定义位置 在何地?   x用描述符来描述
12     def __init__(self,n):
13         self.x=n #b1.x=10 触发Foo的set方法
14 #触发在何时?
15 b1=Bar(10)  #在执行赋值操作
16 print(b1.__dict__)
17 b1.x=1  #在执行赋值操作
18 print(b1.__dict__)
19 
20 b1.y=2  #没有触发set,因为变量y并没用描述符描述
21 print(b1.__dict__)

输出

===>set方法 <__main__.Bar object at 0x000001CDBB0197B8> 10 {'x': 10} ===>set方法 <__main__.Bar object at 0x000001CDBB0197B8> 1 {'x': 1} {'x': 1, 'y': 2}

优先级的体现

代码语言:javascript
复制
 1 class Foo:
 2     def __get__(self, instance, owner):
 3         print('===>get方法')
 4     def __set__(self, instance, value):
 5         print('===>set方法',instance,value)
 6         instance.__dict__['x']=value #b1.__dict__
 7     def __delete__(self, instance):
 8         print('===>delete方法')
 9 
10 class Bar:
11     x=Foo()
12 Bar.x=1    #覆盖类属性,改变了Bar的__dict__
13 print(Bar.__dict__)
14 print(Bar.x)

输出

{'__module__': '__main__', 'x': 1, '__dict__': <attribute '__dict__' of 'Bar' objects>, '__weakref__': <attribute '__weakref__' of 'Bar' objects>, '__doc__': None} 1

反序列化的时候要保证类还在内存中。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2019-03-13 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 内置函数补充及__getattribute__
  •  item系列
  • __str__和__repr__
  • 自定制format
  • __slots__
  • __doc__
  • __module__和__class__
  • __del__ 析构方法
  • __call__
  • __next__和__iter__实现迭代器协议
    •   迭代器协议实现斐波那契数列
    • 描述符理论
      • 优先级的体现
      相关产品与服务
      日志服务
      日志服务(Cloud Log Service,CLS)是腾讯云提供的一站式日志服务平台,提供了从日志采集、日志存储到日志检索,图表分析、监控告警、日志投递等多项服务,协助用户通过日志来解决业务运维、服务监控、日志审计等场景问题。
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档