Python之反射、双下划线attr、item系列
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了Python之反射、双下划线attr、item系列,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含8380字,纯文字阅读大概需要12分钟。
内容图文
![Python之反射、双下划线attr、item系列](/upload/InfoBanner/zyjiaocheng/755/42799972d1d44111b919c49e4fa88e27.jpg)
一、反射(hasattr/getattr/setattr/delattr)
1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 4 5 class BlackMedium: 6 7 def __init__(self, name, addr): 8 self.name = name 9 self.addr = addr 10 11 def sale_house(self): 12 print('【%s】正在卖房子,煞笔才买呢?' % self.name) 13 14 def rent_house(self): 15 print('【%s】正在租房子,煞笔才租呢?' % self.name) 16 17 18 b1 = BlackMedium('万科置地', '锦江花园路') 19 # hasattr 20 # print(hasattr(b1, 'name')) 21 # print(hasattr(b1, 'rent_house')) 22 # print(b1.rent_house) 23 # func = b1.rent_house 24 # func() 25 26 # getattr 27 # print(getattr(b1, 'name')) 28 # print(getattr(b1, 'sale_house')) # == b1.sale_house 29 # print(getattr(b1, 'sale_house1111111111')) # 没有就会报错 30 # print(getattr(b1, 'sale_house1111', '没有这个属性')) # default=None 加上默认就不会报错了 31 32 33 # setattr 34 # 设置对象值 b1.sb = True 35 # setattr(b1, 'sb', True) 36 # setattr(b1, 'sb1', 123) 37 # setattr(b1, 'name', 'SB') 38 # 加函数属性 39 # setattr(b1, 'func', lambda self: self.name + 'SB') 40 # print(b1.__dict__) 41 # print(b1.func(b1)) 42 43 # delattr 44 # del b1.sb 45 # del b1.sb1 46 # print(b1.__dict__) 47 # delattr(b1, 'sb') 48 # print(b1.__dict__)
二、双下划线attr
1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 4 5 class Foo: 6 x = 1 7 8 def __init__(self, y): 9 self.y = y 10 11 def __getattr__(self, item): 12 print('执行__getattr__') 13 14 def __delattr__(self, item): 15 print('执行__delattr__') 16 # self.__dict__.pop(item) 17 18 def __setattr__(self, key, value): 19 print('执行__setattr__') 20 # self.key = value # RecursionError: maximum recursion depth exceeded 无限死递归超过最大层数了 21 # self.__dict__[key] = value # 直接在修改底层字典 22 23 24 # __getattr__方法 25 f = Foo(10) 26 # print(f.y) 27 # print(getattr(f, 'y')) 28 print(f.z) # 调用对象不存在属性的时候就触发__getattr__方法 29 30 31 # __delattr__方法 32 # del f.y # 触发__delattr__方法执行 33 34 35 # __setattr__方法 设置属性的时候就会触发__setattr__ 36 print(f.__dict__) 37 f.v = 2 38 setattr(f, 'z', 1) 39 print(f.__dict__) 40 print(dir(Foo))
三、继承方式完成包装标准类型
1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 4 5 class List(list): 6 def show_midlle(self): 7 mid_index = int(len(self)/2) 8 return self[mid_index] 9 10 def append(self, p_obj): 11 if type(p_obj) is str: 12 # list.append(self, p_obj) 13 super().append(p_obj) 14 else: 15 print('必须添加字符串类型的') 16 17 18 l1 = List('helloworld') 19 print(l1.show_midlle()) 20 print(l1) 21 l1.append(11111) 22 l1.append('sb') 23 print(l1)
四、授权
1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 import time 4 5 6 class FileHandler: 7 def __init__(self, filename, mode='r', encoding='utf-8'): 8 self.file = open(filename, mode, encoding=encoding) 9 self.mode = mode 10 self.encoding = encoding 11 12 def write(self, line): 13 t = time.strftime('%Y-%m-%d %X') 14 self.file.write('%s %s' % (t, line)) 15 16 def __getattr__(self, item): 17 # print('----->', item) 18 return getattr(self.file, item) 19 20 21 f = FileHandler('a.txt', 'r+') 22 print(f.read()) # 先找自己 然后找类 类还是没有就触发__getattr__ 23 f.write('111111\n') 24 f.write('222222\n') 25 f.write('333333\n')
五、isinstance issubclass
1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 4 5 class Foo: 6 pass 7 8 9 class Bar(Foo): 10 pass 11 12 13 # 一个对象是否是一个类的对象 14 f = Foo() 15 print(isinstance(f, Foo)) 16 17 # 判断一个类是否是另外一个类的子类 18 print(issubclass(Bar, Foo))
六、__getattr__ 、__getattribute__区别
1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 4 5 class Foo: 6 def __init__(self, x): 7 self.x = x 8 9 def __getattr__(self, item): 10 print('执行__getattr__', item) 11 12 def __getattribute__(self, item): 13 # print('执行__getattribute__', item) 14 print('不管是否存在我都要跑起来!') 15 raise AttributeError('哈哈') 16 17 18 f = Foo(10) 19 f.x 20 f.xxxx 21 # 当二者__getattr__ __getattribute__同时存在,\ 22 # 只会执行__getattribute__,除非抛出raise AttributeError()才去执行__getattr__
七、item系列
1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 4 5 class Foo: 6 def __getitem__(self, item): 7 print('执行__getitem__') 8 return self.__dict__[item] 9 10 def __setitem__(self, key, value): 11 print('执行__setitem__') 12 self.__dict__[key] = value 13 14 def __delitem__(self, key): 15 print('执行__delitem__') 16 self.__dict__.pop(key) 17 18 19 f = Foo() 20 print(f.__dict__) 21 # f.name = 'egon' #.的方式是调用的attr哪些方法 没调用setitem 22 f['name'] = 'egon' 23 f['age'] = 18 24 print(f.__dict__) 25 26 # del f.age # 通过字典的方式删才会执行delitem 27 # del f['age'] 28 # print(f.__dict__) 29 30 print(f.age) # 执行的attr哪些方法 31 print(f['age']) # 执行的是getitem
八、__str__、__repr__
1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 4 5 class Foo: 6 def __init__(self, name): 7 self.name = name 8 9 def __str__(self): 10 ret = '%s' % self.name 11 return ret 12 # 这里不能返回其它类型的值只能返回字符串类型 13 14 def __repr__(self): 15 ret = '%s' % self.name 16 return ret 17 18 19 f = Foo('egon') 20 print(f) # 不定义__str__就返回<__main__.Foo object at 0x0000021F398281D0> 定义之后的返回值egon 21 # str(f) ------->f.__str__() print实际是触发系统的__str__方法 22 print(str(f)) 23 print(f.__str__()) 24 25 # repr(f) ------->f.__repr__() 在终端解释器操作返回的结果 26 # 共存的情况下 print本质就是调用__str__, 如果没有__str__,就去找__repr__(替代品)
九、类变量 (__slots__)
1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 4 5 """ 6 1.__slots__是什么:是一个类变量,变量值可以是列表,元祖,或者可迭代对象,也可以是一个字符串(意味着所有实例只有一个数据属性) 7 2.引子:使用点来访问属性本质就是在访问类或者对象的__dict__属性字典(类的字典是共享的,而每个实例的是独立的) 8 3.为何使用__slots__:字典会占用大量内存,如果你有一个属性很少的类,但是有很多实例,为了节省内存可以使用__slots__取代实例的__dict__ 9 当你定义__slots__后,__slots__就会为实例使用一种更加紧凑的内部表示。实例通过一个很小的固定大小的数组来构建,而不是为每个实例定义一个 10 字典,这跟元组或列表很类似。在__slots__中列出的属性名在内部被映射到这个数组的指定小标上。使用__slots__一个不好的地方就是我们不能再给 11 实例添加新的属性了,只能使用在__slots__中定义的那些属性名。 12 4.注意事项:__slots__的很多特性都依赖于普通的基于字典的实现。另外,定义了__slots__后的类不再 支持一些普通类特性了,比如多继承。大多数情况下,你应该 13 只在那些经常被使用到 的用作数据结构的类上定义__slots__比如在程序中需要创建某个类的几百万个实例对象 。 14 关于__slots__的一个常见误区是它可以作为一个封装工具来防止用户给实例增加新的属性。尽管使用__slots__可以达到这样的目的,但是这个并不是它的初衷。
更多的是用来作为一个内存优化工具。 15 """ 16 17 18 class Foo: 19 # __slots__ = 'name' 20 __slots__ = ['name', 'age'] # 实例化对象只能设置两个属性name age 21 22 23 f1 = Foo() 24 f1.name = 'egon' 25 print(f1.name) 26 27 # print(f1.__dict__) # 没dict这个属性了 28 print(f1.__slots__)
十、__doc__
1 类中的文档信息 但是不能继承
十一、__module__ 、__class__
1 class C: 2 3 def __init__(self): 4 self.name = 'SB'
1 from lib.aa import C 2 3 obj = C() 4 print(obj.__module__) # 输出 lib.aa,即:输出模块 5 print(obj.__class__) # 输出 lib.aa.C,即:输出类
十二、__del__析构方法
1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 4 5 """ 6 析构方法,当对象在内存中被释放时,自动触发执行。 7 8 注:如果产生的对象仅仅只是python程序级别的(用户级), 9 那么无需定义__del__,如果产生的对象的同时还会向操作系统发起系统调用, 10 即一个对象有用户级与内核级两种资源,比如(打开一个文件,创建一个数据库链接), 11 则必须在清除对象的同时回收系统资源,这就用到了__del__ 12 """ 13 14 15 class Foo: 16 def __init__(self, name): 17 self.name = name 18 19 def __del__(self): 20 print('我开始执行') 21 22 23 f1 = Foo('egon') 24 # del f1.name 删属性 25 del f1 # 删对象 垃圾回收机制 释放掉f1对象 26 print('-------------------------')
十三、__call__方法
1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 4 5 """ 6 对象后面加括号,触发执行。 7 8 注:构造方法的执行是由创建对象触发的,即:对象 = 类名() ;而对于 __call__ 方法的执行是由对象后加括号触发的,即:对象() 或者 类()() 9 """ 10 11 12 class Foo: 13 def __init__(self): 14 pass 15 16 def __call__(self, *args, **kwargs): 17 print('我开始执行了') 18 19 20 f1 = Foo() 21 print(dir(Foo)) 22 print(f1) 23 24 f1() # 触发call 方法
内容总结
以上是互联网集市为您收集整理的Python之反射、双下划线attr、item系列全部内容,希望文章能够帮你解决Python之反射、双下划线attr、item系列所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。