首页 > 编程语言 > 详细

Python之反射、双下划线attr、item系列

时间:2019-07-19 20:57:26      阅读:95      评论:0      收藏:0      [点我收藏+]

一、反射(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系列

原文:https://www.cnblogs.com/Alexephor/p/11215644.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!