# 描述符
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("自定义异常"))