15 内置方法(下)
2018-06-18 02:24:53来源:未知 阅读 ()
面向对象学习目录
1 面向对象介绍
2 类、实例、属性、方法详解
3 面向过程与面向对象进一步比较
4 类与对象
5 属性查找与绑定方法
6 小结
7 继承与派生
8 组合
9 抽象类
10 多态
11 封装
12 绑定方法与非绑定方法
13 内置方法(上)
14 内置方法(中)之描述符
15 内置方法(下)
16 元类
七、再看property
1 class Foo: 2 @property 3 def AAA(self): 4 print('get的时候运行我啊') 5 6 @AAA.setter 7 def AAA(self,value): 8 print('set的时候运行我啊') 9 10 @AAA.deleter 11 def AAA(self): 12 print('delete的时候运行我啊') 13 14 #只有在属性AAA定义property后才能定义AAA.setter,AAA.deleter 15 f1=Foo() 16 f1.AAA 17 f1.AAA='aaa' 18 del f1.AAA
用法二
1 class Foo: 2 def get_AAA(self): 3 print('get的时候运行我啊') 4 5 def set_AAA(self,value): 6 print('set的时候运行我啊') 7 8 def delete_AAA(self): 9 print('delete的时候运行我啊') 10 11 AAA=property(get_AAA,set_AAA,delete_AAA) #内置property三个参数与get,set,delete一一对应 12 13 f1=Foo() 14 f1.AAA 15 f1.AAA='aaa' 16 del f1.AAA
怎么用?
1 class Goods: 2 def __init__(self): 3 # 原价 4 self.original_price = 100 5 # 折扣 6 self.discount = 0.8 7 8 @property 9 def price(self): 10 # 实际价格 = 原价 * 折扣 11 new_price = self.original_price * self.discount 12 return new_price 13 14 @price.setter 15 def price(self, value): 16 self.original_price = value 17 18 @price.deleter 19 def price(self): 20 del self.original_price 21 22 23 obj = Goods() 24 obj.price # 获取商品价格 25 obj.price = 200 # 修改商品原价 26 print(obj.price) 27 del obj.price # 删除商品原价
案例二
1 #实现类型检测功能 2 3 #第一关: 4 class People: 5 def __init__(self,name): 6 self.name=name 7 8 @property 9 def name(self): 10 return self.name 11 12 # p1=People('alex') 13 #property自动实现了set和get方法属于数据描述符,比实例属性优先级高,所以你这面写会触发property内置的set,抛出异常 14 15 16 #第二关:修订版 17 18 class People: 19 def __init__(self,name): 20 self.name=name #实例化就触发property 21 22 @property 23 def name(self): 24 # return self.name #无限递归 25 print('get------>') 26 return self.DouNiWan 27 28 @name.setter 29 def name(self,value): 30 print('set------>') 31 self.DouNiWan=value 32 33 @name.deleter 34 def name(self): 35 print('delete------>') 36 del self.DouNiWan 37 38 p1=People('alex') #self.name实际是存放到self.DouNiWan里 39 print(p1.name) 40 print(p1.name) 41 print(p1.name) 42 print(p1.__dict__) 43 44 p1.name='egon' 45 print(p1.__dict__) 46 47 del p1.name 48 print(p1.__dict__) 49 50 51 #第三关:加上类型检查 52 class People: 53 def __init__(self,name): 54 self.name=name #实例化就触发property 55 56 @property 57 def name(self): 58 # return self.name #无限递归 59 print('get------>') 60 return self.DouNiWan 61 62 @name.setter 63 def name(self,value): 64 print('set------>') 65 if not isinstance(value,str): 66 raise TypeError('必须是字符串类型') 67 self.DouNiWan=value 68 69 @name.deleter 70 def name(self): 71 print('delete------>') 72 del self.DouNiWan 73 74 p1=People('alex') #self.name实际是存放到self.DouNiWan里 75 p1.name=1
八、__setitem__,__getitem__,__delitem__
1 class Foo: 2 def __init__(self,name): 3 self.name=name 4 5 def __getitem__(self, item): 6 print(self.__dict__[item]) 7 8 def __setitem__(self, key, value): 9 self.__dict__[key]=value 10 def __delitem__(self, key): 11 print('del obj[key]时,我执行') 12 self.__dict__.pop(key) 13 def __delattr__(self, item): 14 print('del obj.key时,我执行') 15 self.__dict__.pop(item) 16 17 f1=Foo('sb') 18 f1['age']=18 19 f1['age1']=19 20 del f1.age1 21 del f1['age'] 22 f1['name']='alex' 23 print(f1.__dict__)
九、__str__,__repr__,__format__
1 format_dict={ 2 'nat':'{obj.name}-{obj.addr}-{obj.type}',#学校名-学校地址-学校类型 3 'tna':'{obj.type}:{obj.name}:{obj.addr}',#学校类型:学校名:学校地址 4 'tan':'{obj.type}/{obj.addr}/{obj.name}',#学校类型/学校地址/学校名 5 } 6 7 class School: 8 def __init__(self,name,addr,type): 9 self.name=name 10 self.addr=addr 11 self.type=type 12 13 def __repr__(self): 14 return 'School(%s,%s)' %(self.name,self.addr) 15 def __str__(self): 16 return '(%s,%s)' %(self.name,self.addr) 17 18 def __format__(self, format_spec): 19 # if format_spec 20 if not format_spec or format_spec not in format_dict: 21 format_spec='nat' 22 fmt=format_dict[format_spec] 23 return fmt.format(obj=self) 24 25 s1=School('oldboy1','北京','私立') 26 print('from repr: ',repr(s1)) 27 print('from str: ',str(s1)) 28 print(s1) 29 30 ''' 31 str函数或者print函数--->obj.__str__() 32 repr或者交互式解释器--->obj.__repr__() 33 如果__str__没有被定义,那么就会使用__repr__来代替输出 34 注意:这俩方法的返回值必须是字符串,否则抛出异常 35 ''' 36 print(format(s1,'nat')) 37 print(format(s1,'tna')) 38 print(format(s1,'tan')) 39 print(format(s1,'asfdasdffd'))
自定义format练习
1 date_dic={ 2 'ymd':'{0.year}:{0.month}:{0.day}', 3 'dmy':'{0.day}/{0.month}/{0.year}', 4 'mdy':'{0.month}-{0.day}-{0.year}', 5 } 6 7 class Date: 8 def __init__(self,year,month,day): 9 self.year=year 10 self.month=month 11 self.day=day 12 13 def __format__(self, format_spec): 14 if not format_spec or format_spec not in date_dic: 15 format_spec='ymd' 16 fmt=date_dic[format_spec] 17 return fmt.format(self) 18 19 d1=Date(2016,12,29) 20 print(format(d1)) 21 print('{:mdy}'.format(d1))
issubclass和isinstance
1 class A: 2 pass 3 4 class B(A): 5 pass 6 7 print(issubclass(B,A)) #B是A的子类,返回True 8 9 a1=A() 10 print(isinstance(a1,A)) #a1是A的实例
十、slots
1 ''' 2 1.__slots__是什么:是一个类变量,变量值可以是列表,元祖,或者可迭代对象,也可以是一个字符串(意味着所有实例只有一个数据属性) 3 2.引子:使用点来访问属性本质就是在访问类或者对象的__dict__属性字典(类的字典是共享的,而每个实例的是独立的) 4 3.为何使用__slots__:字典会占用大量内存,如果你有一个属性很少的类,但是有很多实例,为了节省内存可以使用__slots__取代实例的__dict__ 5 当你定义__slots__后,__slots__就会为实例使用一种更加紧凑的内部表示。实例通过一个很小的固定大小的数组来构建,而不是为每个实例定义一个 6 字典,这跟元组或列表很类似。在__slots__中列出的属性名在内部被映射到这个数组的指定小标上。使用__slots__一个不好的地方就是我们不能再给 7 实例添加新的属性了,只能使用在__slots__中定义的那些属性名。 8 4.注意事项:__slots__的很多特性都依赖于普通的基于字典的实现。另外,定义了__slots__后的类不再 支持一些普通类特性了,比如多继承。大多数情况下,你应该 9 只在那些经常被使用到 的用作数据结构的类上定义__slots__比如在程序中需要创建某个类的几百万个实例对象 。 10 关于__slots__的一个常见误区是它可以作为一个封装工具来防止用户给实例增加新的属性。尽管使用__slots__可以达到这样的目的,但是这个并不是它的初衷。 更多的是用来作为一个内存优化工具。 11 12 ''' 13 class Foo: 14 __slots__='x' 15 16 17 f1=Foo() 18 f1.x=1 19 f1.y=2 #报错 20 print(f1.__slots__) #f1不再有__dict__ 21 22 class Bar: 23 __slots__=['x','y'] 24 25 n=Bar() 26 n.x,n.y=1,2 27 n.z=3 #报错
刨根问底
1 class Foo: 2 __slots__=['name','age'] 3 4 f1=Foo() 5 f1.name='alex' 6 f1.age=18 7 print(f1.__slots__) 8 9 f2=Foo() 10 f2.name='egon' 11 f2.age=19 12 print(f2.__slots__) 13 14 print(Foo.__dict__) #f1与f2都没有属性字典__dict__了,统一归__slots__管,节省内存
十一、__next__和__iter__实现迭代器协议
1 class Foo: 2 def __init__(self,x): 3 self.x=x 4 5 def __iter__(self): 6 return self 7 8 def __next__(self): 9 n=self.x 10 self.x+=1 11 return self.x 12 13 f=Foo(3) 14 for i in f: 15 print(i)
1 class Foo: 2 def __init__(self,start,stop): 3 self.num=start 4 self.stop=stop 5 def __iter__(self): 6 return self 7 def __next__(self): 8 if self.num >= self.stop: 9 raise StopIteration 10 n=self.num 11 self.num+=1 12 return n 13 14 f=Foo(1,5) 15 16 from collections import Iterable,Iterator 17 print(isinstance(f,Iterator)) 18 19 for i in Foo(1,5): # obj=iter(Foo(1,5)) ---> 相当于Foo(1,5).__iter__() 20 print(i) # obj.__next__(),直到遇到StopIteration就自动终止(但for循环不会抛出异常报错)
练习:简单模拟range,加上步长
1 class Range: 2 def __init__(self,n,stop,step): 3 self.n=n 4 self.stop=stop 5 self.step=step 6 7 def __next__(self): 8 if self.n >= self.stop: 9 raise StopIteration 10 x=self.n 11 self.n+=self.step 12 return x 13 14 def __iter__(self): 15 return self 16 17 for i in Range(1,7,3): # obj=iter(Range(1,7,3)) ---> 相当于Range(1,7,3).__iter__() 18 print(i) # obj.__next__(),直到遇到StopIteration就自动终止(但for循环不会抛出异常报错)
斐波那契数列
1 class Fib: 2 def __init__(self): 3 self._a=0 4 self._b=1 5 6 def __iter__(self): 7 return self 8 9 def __next__(self): 10 self._a,self._b=self._b,self._a + self._b 11 return self._a 12 13 f1=Fib() 14 15 print(f1.__next__()) 16 print(next(f1)) 17 print(next(f1)) 18 19 for i in f1: 20 if i > 100: 21 break 22 print('%s ' %i,end='')
十二、__doc__
1 class Foo: 2 '我是描述信息' 3 pass 4 5 print(Foo.__doc__)
该属性无法被继承
1 class Foo: 2 '我是描述信息' 3 pass 4 5 class Bar(Foo): 6 pass 7 8 print(Bar.__doc__) #该属性无法继承给子类
十三、__module__和__class__
1 class C: 2 def __init__(self): 3 self.name = ‘SB'
index.py
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 class Foo: 2 def __del__(self): 3 print('执行我啦') 4 5 f1=Foo() 6 del f1 7 print('------->') 8 9 #输出结果 10 执行我啦 11 ------->
挖坑埋了你
1 class Foo: 2 def __del__(self): 3 print('执行我啦') 4 5 f1=Foo() # del f1 6 print('------->') 7 8 #输出结果 9 -------> 10 执行我啦
1 f=open('a.txt') #做了两件事,在用户空间拿到一个f变量,在操作系统内核空间打开一个文件 2 del f #只回收用户空间的f,操作系统的文件还处于打开状态 3 4 #所以我们应该在del f之前保证f.close()执行,即便是没有del,程序执行完毕也会自动del清理资源,于是文件操作的正确用法应该是 5 f=open('a.txt') 6 读写... 7 f.close() 8 很多情况下大家都容易忽略f.close,这就用到了with上下文管理
十五、__enter__和__exit__
1 with open('a.txt') as f: 2 '代码块'
上述叫做上下文管理协议,即with语句,为了让一个对象兼容with语句,必须在这个对象的类中声明__enter__和__exit__方法
1 class Open: 2 def __init__(self,name): 3 self.name=name 4 def __enter__(self): 5 print('出现with语句,对象的__enter__被触发,有返回值则赋值给as声明的变量') 6 # return self 7 def __exit__(self, exc_type, exc_val, exc_tb): 8 print('with中代码块执行完毕时执行我啊') 9 10 11 with Open('a.txt') as f: 12 print('=====>执行代码块') 13 # print(f,f.name)
__exit__()中的三个参数分别代表异常类型,异常值和追溯信息,with语句中代码块出现异常,则with后的代码都无法执行
1 class Open: 2 def __init__(self,name): 3 self.name=name 4 5 def __enter__(self): 6 print('出现with语句,对象的__enter__被触发,有返回值则赋值给as声明的变量') 7 8 def __exit__(self, exc_type, exc_val, exc_tb): 9 print('with中代码块执行完毕时执行我啊') 10 print(exc_type) 11 print(exc_val) 12 print(exc_tb) 13 14 15 with Open('a.txt') as f: 16 print('=====>执行代码块') 17 raise AttributeError('***着火啦,救火啊***') 18 print('0'*100) #------------------------------->不会执行
如果__exit()返回值为True,那么异常会被清空,就好像啥都没发生一样,with后的语句正常执行
1 class Open: 2 def __init__(self,name): 3 self.name=name 4 5 def __enter__(self): 6 print('出现with语句,对象的__enter__被触发,有返回值则赋值给as声明的变量') 7 8 def __exit__(self, exc_type, exc_val, exc_tb): 9 print('with中代码块执行完毕时执行我啊') 10 print(exc_type) 11 print(exc_val) 12 print(exc_tb) 13 return True 14 15 16 with Open('a.txt') as f: 17 print('=====>执行代码块') 18 raise AttributeError('***着火啦,救火啊***') 19 print('0'*100) #------------------------------->会执行
练习:模拟Open
1 class Open: 2 def __init__(self,filepath,mode='r',encoding='utf-8'): 3 self.filepath=filepath 4 self.mode=mode 5 self.encoding=encoding 6 7 def __enter__(self): 8 # print('enter') 9 self.f=open(self.filepath,mode=self.mode,encoding=self.encoding) 10 return self.f 11 12 def __exit__(self, exc_type, exc_val, exc_tb): 13 # print('exit') 14 self.f.close() 15 return True 16 def __getattr__(self, item): 17 return getattr(self.f,item) 18 19 with Open('a.txt','w') as f: 20 print(f) 21 f.write('aaaaaa') 22 f.wasdf #抛出异常,交给__exit__处理
用途或者说好处:
- 使用with语句的目的就是把代码块放入with中执行,with结束后,自动完成清理工作,无须手动干预
- 在需要管理一些资源比如文件,网络连接和锁的编程环境中,可以在__exit__中定制自动释放资源的机制,你无须再去关系这个问题,这将大有用处
十六、__call__
1 class Foo: 2 def __init__(self): 3 pass 4 5 def __call__(self, *args, **kwargs): 6 print('__call__') 7 8 9 obj = Foo() # 执行 __init__ 10 obj() # 执行 __call__
标签:
版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有
- python_字符串方法 2019-08-13
- python_公共方法 2019-08-13
- python3 之 判断闰年小实例 2019-08-13
- python之函数、面向对象 2019-08-13
- pycharm查看函数用法,参数信息的设置方法 2019-07-24
IDC资讯: 主机资讯 注册资讯 托管资讯 vps资讯 网站建设
网站运营: 建站经验 策划盈利 搜索优化 网站推广 免费资源
网络编程: Asp.Net编程 Asp编程 Php编程 Xml编程 Access Mssql Mysql 其它
服务器技术: Web服务器 Ftp服务器 Mail服务器 Dns服务器 安全防护
软件技巧: 其它软件 Word Excel Powerpoint Ghost Vista QQ空间 QQ FlashGet 迅雷
网页制作: FrontPages Dreamweaver Javascript css photoshop fireworks Flash