13.关于继承封装,以及反射

 

# 描述符

  1  1 下面这个示例可以展现多态的某些功能
  3   class Water(object):
  4   2     def __init__(self, name, template):
  5   3         self.name = name
  6   4         self.template = template
  7   5 
  8   6     def wendu(self):
  9   7         if self.template < 0:
 10   8             print("%s由是变成了冰" % self.name)
 11   9         elif (self.template > 0 and self.template < 100):
 12  10             print("%s我是水" % self.name)
 13  11         elif self.template > 100:
 14  12             print("%s水变成了水蒸气" % self.name)
 15  13 
 16  14 
 17  15 class Ice(Water):
 18  16     pass
 19  17 
 20  18 
 21  19 class Shui(Water):
 22  20     pass
 23  21 
 24  22 
 25  23 class ZhengQi(Water):
 26  24     pass
 27  25 
 28  26 
 29  27 i = Ice("bing", -1)
 30  28 s = Shui("shui", 20)
 31  29 z = ZhengQi("zhengqi", 110)
 32  30 
 33  31 # i.wendu()
 34  32 # s.wendu()
 35  33 # z.wendu()
 36  34 
 37  35 
 38  36 # 继承(扩展和改变),多态(子类继承父类的方法,一种类经过不同的引用表现出来的多种形式)
 39  37 
 40  38 
 41  39 class Person(object):
 42  40     __star = "air"
 43  41 
 44  42     def __init__(self, name):
 45  43         self.name = name
 46  44         print(self.__star)
 47  45 
 48  46     def name1(self):
 49  47         return self.name
 50  48 
 51  49     def get_star(self):  # 访问函数
 52  50         return self.__star
 53  51 
 54  52 
 55  53 class Son(Person):
 56  54     def __init__(self, name):
 57  55         super(Son, self).__init__(name)
 58  56 
 59  57 
 60  58 s = Son("body")
 61  59 # print(s.name1())
 62  60 # 封装(分出内外,__name)
 63  61 
 64  62 # p = Person("bob")
 65  63 # print(Person.__dict__)
 66  64 # print(Person._Person__star)
 67  65 
 68  66 # print(hasattr(s, "name"))
 69  67 # print(hasattr(s, "name1"))  # 对象是否可以.到字符串中的属性
 70  68 #
 71  69 # func = getattr(s, "name2", None)
 72  70 # print(func)
 73  71 #
 74  72 # setattr(s, "age", 12)
 75  73 # setattr(s, "func", lambda self: self.age + 1)
 76  74 # print(s.func(s))
 77  75 # print(s.__dict__)
 78  76 #
 79  77 # delattr(s, "age")
 80  78 # print(s.__dict__)
 81  79 
 82  80 
 83  81 # 反射
 84  82 if hasattr(s, "get"):
 85  83     func_get = getattr(s, "get")
 86  84     func_get()
 87  85 else:
 88  86     pass
 89  87     # print("其他逻辑")
 90  88 
 91  89 test = __import__("t2")
 92  90 # print(test.config['DEFAULT']['ForwardX11'])
 93  91 #
 94  92 # import importlib
 95  93 # test1 = importlib.import_module("web.apps")
 96  94 # print(test1)
 97  95 
 98  96 
 99  97 class FOO:
100  98     x = 1
101  99 
102 100     # 此类中的__XXXattr__方法与类无关,是属性的方法
103 101     def __init__(self, y):
104 102         self.y = y
105 103 
106 104     # 调用一个对象不存在的方法的时候才会执行
107 105     def __getattr__(self, item):
108 106         print("执行__getattr__")
109 107         print("属性%s" %item + "不存在")
110 108 
111 109     def __delattr__(self, item):  # del f1.y
112 110         print("删除了一个对象属性__delattr__")
113 111         self.__dict__.pop(item)
114 112 
115 113     def __setattr__(self, key, value):  # f1.m=3
116 114         print("__str__执行了")
117 115         if type(value) is not str:
118 116             print("%s不是字符串" % value)
119 117         self.__dict__["key"] = value
120 118 
121 119 
122 120 # f1 = FOO(10)
123 121 # f1.name = "alex"
124 122 # f1.age = 10
125 123 # print(f1.__dict__)
126 124 
127 125 
128 126 # 二次加工的数据类型
129 127 class List(list):   # 继承了list之后 List("ss") = list("ss")
130 128     def append(self, object):
131 129         if type(object) is str:
132 130             super().append(object)   # 这里调用父类的append方法,因为调用自己的append会导致循环引用的错误
133 131         pass
134 132 
135 133     def show_middle(self):
136 134         middle = int(len(self) / 2)
137 135         return self[middle]
138 136 
139 137 
140 138 # l1 = List("hello ! world")
141 139 # print(l1)
142 140 # print(l1.show_middle())
143 141 # l1.append("ss")
144 142 # print(l1)
145 143 
146 144 class Open(object):
147 145 
148 146     def __init__(self, filename, mode="r", encoding="utf-8"):
149 147         # self.filename = filename
150 148         self.file = open(filename, mode, encoding=encoding)
151 149         self.mode = mode
152 150         self.encoding = encoding
153 151 
154 152     def write(self, content):
155 153         import time
156 154         t1 = time.localtime()
157 155         t = time.strftime("%Y-%m-%d %H:%M:%S", t1)  #  时间格式化
158 156         print(time.strptime(t, "%Y-%m-%d %H:%M:%S"))
159 157         self.file.write(str(t) + content)
160 158 
161 159     def __getattr__(self, item):
162 160         print("%s不存在" % item)
163 161         return getattr(self.file, item)  # 拿取属性中的file实例化的方法,当在当前类中不存在这个属性或者方法的时候
164 162 
165 163 
166 164 # path = r"C:\Users\lzh\PycharmProjects\day05\a.txt"
167 165 # f1 = Open(path, "w+")
168 166 # print(f1.file)
169 167 # print(f1.read)
170 168 # f1.write("ssssssssssssssssss")
171 169 
172 170 
173 171 import sys
174 172 obj1 = sys.modules[__name__]  # 可以用来获取当前模块
175 173 getattr(obj1, "get")

 

2.描述符

  1 class Foo:
  2     def __init__(self, x):
  3         self.x = x
  4 
  5     def __getattr__(self, item):  # 当__getattribute__抛出AttributeError异常的时候才会执行
  6         print("__getattr__方法执行了")
  7 
  8     def __getattribute__(self, item):  # 不管找不找得到它都会执行
  9         print("__getattribute__方法执行了")
 10         raise AttributeError("出现错误")  # 只有抛出这个错误的时候__getattr__方法才会执行
 11 
 12 
 13 # f1 = Foo(12)
 14 # f1.xxx
 15 
 16 
 17 class Foo:
 18     pass
 19 
 20 
 21 class Bar(Foo):
 22     pass
 23 
 24 
 25 # b = Bar()
 26 # print(isinstance(b, Bar))
 27 # print(isinstance(b, Foo))  # b是否是Foo中的类实例化的
 28 # print(type(b))
 29 
 30 
 31 class Foo:
 32     # __XXXitem__是字典的方式,操作需要使用[]
 33     def __getitem__(self, item):   # 获取的时候调用
 34         print("getitem")
 35         return self.__dict__[item]
 36 
 37     def __setitem__(self, key, value):  # 设置的时候调用
 38         print("setitem")
 39         self.__dict__[key] = value
 40 
 41     def __delitem__(self, key):   # 删除的时候调用
 42         print("delitem")
 43         self.__dict__.pop(key)
 44 
 45 
 46 # f1 = Foo()
 47 # f1["name"] = "alex"
 48 # f1["age"] = 18
 49 # print(f1.__dict__)
 50 # del f1["name"]
 51 # print(f1.__dict__)
 52 # print(f1["age"])
 53 
 54 
 55 # 自定制显示
 56 l = list('name')
 57 # print(l)
 58 
 59 
 60 class Car(object):
 61 
 62     def __init__(self, name, age):
 63         self.name = name
 64         self.age = age
 65 
 66     # def __str__(self):   # 实例输出的时候,显示的问题
 67     #     return "你好啊{}".format(self.name)
 68 
 69     def __repr__(self):
 70         return "你好啊{}".format(self.name)
 71 
 72 
 73 c1 = Car("tom", 12)
 74 # print(c1)  # print(f1) ---->f1.__str__----->(如果没找到执行)f1.__repr__
 75 
 76 
 77 class Data:
 78     def __init__(self, year, mon, day):
 79         self.year = year
 80         self.mon = mon
 81         self.day = day
 82 
 83 
 84 d = Data(1019, 12, 12)
 85 
 86 x = "{0.year}{0.mon}{0.day}".format(d)
 87 # print(x)
 88 
 89 
 90 # 自定制format
 91 data_format = {
 92     "ymd": "{0.year}{0.mon}{0.day}",
 93     "y-m-d": "{0.year}-{0.mon}-{0.day}",
 94     "y:m:d": "{0.year}:{0.mon}:{0.day}",
 95     "y/m/d": "{0.year}/{0.mon}/{0.day}",
 96 
 97 }
 98 
 99 
100 class Data1:
101     def __init__(self, year, mon, day):
102         self.year = year
103         self.mon = mon
104         self.day = day
105 
106     def __format__(self, format_spec=None):  # 定义返回格式
107         if not format_spec or format_spec not in data_format:
108             return data_format["ymd"].format(self)
109         return data_format[format_spec].format(self)
110 
111 
112 d1 = Data1(2019, 8, 5)
113 # print(format(d1, "y-m-d"))
114 
115 
116 class Tpp:
117     """你好啊"""
118     # 限制添加属性,只能改变__slots__中的属性(省内存,不常用)
119     __slots__ = ["name", 'age']  # {"name": None, "age": None}
120 
121 
122 t1 = Tpp()
123 t1.age = 18  # t1.__setattr__----->fl.__dict__["age"]=18
124 # print(t1.age)
125 # print(t1.__slots__)
126 # print(t1.__doc__)
127 # __module__(查看创建实例的类在哪个模块)和__class__(查看实例是哪个类创建的)
128 
129 
130 class A:
131     def __init__(self):
132         self.name = "liu"
133 
134     def __del__(self):  # 当时(实例)被删除的时候执行
135         print("析构函数执行了")
136 
137 
138 # a1 = A()
139 # del a1.name
140 # print("____________>")
141 
142 
143 class A1:
144     def __init__(self):
145         self.name = "liu"
146 
147     def __call__(self, *args, **kwargs):  # 当实例加()执行时,调用这个方法
148         print("实例执行了, obj()")
149         # return self.name
150 
151     def __str__(self):
152         return self.name
153 
154 
155 a2 = A1()
156 print(a2())  # A1的__call__方法
157 A1()()  # abc(假设)的__call__(类加A1()()也可以执行)
158 
159 
160 # 1.迭代器协议:对象必须有一个next方法,执行该方法要么返回迭代中的下一项,
161 # 要么就引起一个StopIteration异常,用来终止迭代
162 # 2.可迭代对象:实现了迭代器协议的对象(如何实现,对象内部顶一个__iter__方法)
163 # 3.协议是一种约定,可迭代对象实现了迭代器协议,python的内部工具
164 # (如for循环,sum,mi,max等函数)使用迭代器协议访问对象
165 
166 class Abb:
167     def __init__(self, n):
168         self.n = n
169 
170     def __iter__(self):  # 遍历时检查是否有这个方法
171         return self
172 
173     def __next__(self):   # 执行next()或者遍历的时候执行
174         self.n += 1
175         if self.n > 13:
176             raise StopIteration("没了")
177         return self.n
178 
179 
180 aa1 = Abb(10)
181 # for i in aa1:  # aa1.__iter__
182 # print(i)
183 
184 
185 class Fib:
186     def __init__(self):
187         self.n = 1
188         self.m = 1
189 
190     def __iter__(self):
191         return self
192 
193     def __next__(self):
194         self.m, self.n = self.n, self.n + self.m
195         return self.m
196 
197 
198 # f1 = Fib()
199 # print(next(f1))
200 # print(next(f1))
201 # print(next(f1))
202 # print(next(f1))
203 # print(next(f1))
204 
205 
206 # 描述符
207 class Mn:
208     def __init__(self, name):
209         self.name = name
210 
211     def __get__(self, instance, owner):
212         print(self.name, "111111111", instance, "aaa", owner, 'a')
213 
214     # def __set__(self, instance, value):
215     #     print(self, instance, value, 'b')
216     #     instance.__dict__["x"] = value
217 
218     # def __delete__(self, instance):
219     #     print(instance, 'c')
220 
221 
222 # 1.类属性
223 # 2.数据描述符
224 # 3.实例属性
225 # 4.非数据描述符
226 # 5.找不到的属性触发__getattr__()
227 class Uoo:
228     x = Mn("hua")  # 描述符, 代理属性,归代理管
229 
230     # def __init__(self, n):
231     #     self.x = n
232 
233 
234 u1 = Uoo()
235 u1.x = 100  # 实例属性被描述符覆盖
236 # print(u1.__dict__)
237 # print(u1.x)
238 # Uoo.x = 1
239 # print(Uoo.__dict__)  # 描述符类属性被覆盖了
240 
241 
242 # 上下文
243 class Doo:
244     def __init__(self, name):
245         self.name = name
246 
247     def __enter__(self):
248         print("执行enter")
249         return self
250 
251     def __exit__(self, exc_type, exc_val, exc_tb):
252         print("执行exit")
253         print(exc_type)  # 错误类型
254         print(exc_val)  # 错误值
255         print(exc_tb)  # 错误的追踪信息
256         return True  # 程序报出的一场会被隐藏掉
257 
258 
259 # with Doo("a.txt") as f:  # 1. __enter__(),拿到返回值 == obj.__enter__()
260 # #     print(f)
261 # #     print(AFSDFSD)  # 2. 触发错误__exit__执行,打印错误
262 # #     # print(f.name)   #
263 # # print("==========>")
264 
265 # 描述符应用(用来限制传入的值)
266 def test(x):
267     print("===>", x)
268 
269 
270 # test(10)
271 
272 class Typed:
273     def __init__(self, key, except_type):
274         self.key = key
275         self.except_type = except_type
276 
277     def __get__(self, instance, owner):
278         print("get")
279         print(instance, "instance")
280         print(owner, "owner")
281         return instance.__dict__[self.key]
282 
283     def __set__(self, instance, value):
284         print("set")
285         print(instance, "instance")
286         print(value, "value")
287         if not isinstance(value, self.except_type):
288             raise TypeError("{0}不是{1}类型".format(self.key, self.except_type))
289         instance.__dict__[self.key] = value
290 
291     def __delete__(self, instance):
292         print("delete")
293         print(instance, "instance")
294         instance.__dict__.pop(self.key)
295 
296 
297 class People:
298     name = Typed("name", str)
299     age = Typed("age", int)
300 
301     def __init__(self, name, age, salary):
302         self.name = name
303         self.age = age
304         self.salary = salary
305 
306 
307 # p1 = People("name", 12, 7000.00)
308 # print(p1.__dict__)
309 
310 
311 # 类的装饰器
312 def deco1(**kwargs):
313     def deco(obj):
314         print("======>", kwargs)
315         for key, value in kwargs.items():
316             setattr(obj, key, value)
317         return obj
318     print("=====>", kwargs)
319     return deco
320 
321 
322 @deco1(name="name", age=12)  # Poo==deco(Poo)
323 class Poo:
324     pass
325 
326 
327 p1 = Poo()
328 print(Poo.__dict__)

 3.使用描述符实现property装饰器(可以看另外一篇随笔,https://www.cnblogs.com/liuzhanghao/p/11089653.html 关于python的双下划线方法),借用了其他人的一篇文章链接,我也是看这个的,这个老师的课程非常好,有兴趣可以多做了解。

  1 # 装饰器加上描述符
  2 def deco1(**kwargs):
  3     def deco(obj):
  4         for key, value in kwargs.items():
  5             value = Typed(key, value)
  6             setattr(obj, key, value)
  7         return obj
  8     return deco
  9 
 10 
 11 @deco1(name=str, age=int)
 12 class People1:
 13     # name = Typed("name", str)
 14     # age = Typed("age", int)
 15 
 16     def __init__(self, name, age, salary):
 17         self.name = name
 18         self.age = age
 19         self.salary = salary
 20 
 21 
 22 # pp1 = People1("name", 12, 123)
 23 
 24 
 25 # 利用描述符字典纸property
 26 class LazyProperty:
 27     def __init__(self, fun):
 28         print("=====>", fun)
 29         self.fun = fun
 30 
 31     def __get__(self, instance, owner):  # 只加__get__就是实例属性
 32         print("get")
 33         # print(self)
 34         # print(instance)
 35 
 36         if instance == None:
 37             return self
 38         # 不需要下面三行代码的原因是,设置到实例属性的字典中之后,他下次取就从属性字典中取,
 39         # 所以不需要下面的判断
 40         # if hasattr(instance, self.fun.__name__):
 41         #     res = self.__dict__[self.fun.__name__]
 42         # else:
 43         res = self.fun(instance)
 44         setattr(instance, self.fun.__name__, res)
 45         return res
 46 
 47     def __set__(self, instance, value):  # 加上__set__就是数据描述符,只比类属性优先级低
 48         print("set")
 49 
 50 
 51 class Room:
 52     def __init__(self, width, length, name):
 53         self.name = name
 54         self.length = length
 55         self.width = width
 56 
 57     @LazyProperty
 58     def area(self):   # area = LazyProperty(area)
 59         return self.length * self.width
 60 
 61     @property
 62     def area1(self):
 63         return self.length * self.width
 64 
 65     @area1.setter
 66     def area1(self, val):
 67         print("set的时候运行", val)
 68 
 69     @area1.deleter
 70     def area1(self, key):
 71         print("del的时候运行", key)
 72 
 73 
 74 r1 = Room(100, 100, "liu")
 75 # print(Room.__dict__)
 76 # print(r1.area)
 77 """
 78 大概解释一下,自定值property的流程,因为在这之前,我从来没有想过这样做
 79 1.在加载类的时候,会执行__init__方法,在执行到area方法的时候,会先执行@LazyProperty方法,等价于
 80 area = LazyProperty(area),可以理解就是一个描述符(而描述符必须包含__get__,__set__,__delete__中的一种,
 81 所以我们写了一个__get__方法),代理了area方法,可以看到LazyProperty(area),将area方法名传入了其中,
 82 所有我们需要在LazyProperty中写一个__init__方来接收参数,这时初始化时的加载已经完成
 83 2.当我们在实例化完成之后,r1.area的时候其实就调用了LazyProperty描述符的__get__方法,要实现自定义的property
 84 肯定需要执行r1.area()的方法,并且返回值。我们需要则么做呢?有没有记得第一步中LazyProperty的__init__方法,
 85 我们传过去了什么呢?LazyProperty(area)其实就是将area方法传入了描述符中,呢么我们只需要在实例r1.area调用
 86 描述符的__get__方法的时候,执行这个方法,反回结果就可以了,return self.fun(instance)(对于__get__(instance, owner),
 87 中的instance代表的是实例r1,owner代表的则是Room类<也就是r1通过哪个类实例的>)
 88 """
 89 
 90 # 类调用
 91 # print(Room.test)
 92 
 93 # print(r1.area)
 94 r1.area1 = 1000
 95 
 96 
 97 class Boom:
 98     def __init__(self, width, length, name):
 99         self.name = name
100         self.length = length
101         self.width = width
102 
103     @LazyProperty
104     def area(self):   # area = LazyProperty(area)
105         return self.length * self.width
106 
107     def get_area1(self):
108         return self.length * self.width
109 
110     def set_area1(self, val):
111         print("set的时候运行", val)
112 
113     def del_area1(self, key):
114         print("del的时候运行", key)
115 
116     area1 = property(get_area1, set_area1, del_area1)

 

 1 # 元类
 2 class Foo:
 3     pass
 4 
 5 
 6 f1 = Foo()
 7 # print(type(f1))
 8 # print(type(Foo))
 9 
10 
11 def __init__(self, name, age):
12     self.name = name
13     self.age = age
14 
15 
16 def test(self):
17     print("====》")
18 
19 
20 FFo = type("FFo", (object, ), {"x": 1, "__init__": __init__, "test": test})
21 # print(FFo)
22 # print(FFo.__dict__)
23 
24 
25 # 控制类的生成过程
26 class MyType(type):
27 
28     def __init__(self, clazname, bases, attrs):
29         """
30         :param clazname:  类名  Nll
31         :param bases:   继承的类  ()
32         :param attrs:   属性和方法  __dict__
33         """
34         # print("指定元类的生成")
35         pass
36     
37     def __call__(self, *args, **kwargs):
38         """
39         :param self: 调用这个方法的《类》对象
40         :param args:  传入类的属性
41         :param kwargs: 传入类的属性
42         :return:
43         """
44         obj = object.__new__(self)  # object.__new__(Foo)  n1
45         self.__init__(obj, *args, **kwargs)  # Nll.__init__()
46         return obj
47 
48 
49 class Nll(metaclass=MyType):  # Nll = MyType(self, "Nll", (), {}) ---->__init__
50     def __init__(self, name):
51         self.name = name
52 
53 
54 # n1 = Nll(name="pass")
55 # print(n1)
56 # print(n1.__dict__)
57 
58 
59 # 异常处理
60 # 语法错误,逻辑错误
61 try:
62     # age = input("===>")
63     int(12)
64 
65 except ValueError as e:
66     print("值错误")
67 except Exception as e:
68     print("出现错误")
69 
70 # else:
71 #     print("没有异常执行")
72 # finally:
73 #     print("不管有没有异常,都会执行finally下的代码")
74 
75 
76 class CustomException(BaseException):
77     def __init__(self, message):
78         self.message = message
79 
80 
81 # print(CustomException("自定义异常"))

 

posted @ 2019-08-06 17:51  楠海  阅读(270)  评论(0编辑  收藏  举报