第五篇:python高级之面向对象高级
python高级之面向对象高级
python高级之面向对象高级
本节内容
- 成员修饰符
- 特殊成员
- 类与对象
- 异常处理
- 反射/自省
- 单例模式
1.成员修饰符
python的类中只有私有成员和公有成员两种,不像c++中的类有公有成员(public),私有成员(private)和保护成员(protected).并且python中没有关键字去修饰成员,默认python中所有的成员都是公有成员,但是私有成员是以两个下划线开头的名字标示私有成员,私有成员不允许直接访问,只能通过内部方法去访问,私有成员也不允许被继承。
class a: # 说明父类的私有成员无法在子类中继承 def __init__(self): self.ge=123 self.__gene=456class b(a): def __init__(self,name): self.name=name self.__age=18 super(b,self).__init__() # 这一行会报错 def show(self): print(self.name) print(self.__age) print(self.ge) print(self.__gene) # 这一行也会报错obj=b("xiaoming")print(obj.name)print(obj.ge)# print(obj.__gene) # 这个也会报错obj.show()
上面就是类里面的私有成员了。
2.特殊成员
1.__init__
__init__方法可以简单的理解为类的构造方法(实际并不是构造方法,只是在类生成对象之后就会被执行),之前已经在上一篇博客中说明过了。
2.__del__
__del__方法是类中的析构方法,当对象消亡的时候(被解释器的垃圾回收的时候会执行这个方法)这个方法默认是不需要写的,不写的时候,默认是不做任何操作的。因为你不知道对象是在什么时候被垃圾回收掉,所以,除非你确实要在这里面做某些操作,不然不要自定义这个方法。
3.__call__
__call__方法在类的对象被执行的时候(obj()或者 类()())会执行。
4.__int__
__int__方法,在对象被int()包裹的时候会被执行,例如int(obj)如果obj对象没有、__int__方法,那么就会报错。在这个方法中返回的值被传递到int类型中进行转换。
5.__str__
__str__方法和int方法一样,当对象被str(obj)包裹的时候,如果对象中没有这个方法将会报错,如果有这个方法,str()将接收这个方法返回的值在转换成字符串。
6.__add__
__add__方法在两个对象相加的时候,调用第一个对象的__add__方法,将第二个对象传递进来,至于怎么处理以及返回值,那是程序员自定义的,就如下面的例子:
class abc: def __init__(self,age): self.age=age def __add__(self,obj): return self.age+obj.agea1=abc(18)a2=abc(20)print(a1+a2)#执行结果:38
7.__dict__
__dict__方法在类里面有,在对象里面也有,这个方法是以字典的形式列出类或对象中的所有成员。就像下面的例子:
class abc: def __init__(self,age): self.age=age def __add__(self,obj): return self.age+obj.agea1=abc(18)print(abc.__dict__)print(a1.__dict__)#执行结果:{'__add__': <function abc.__add__ at 0x0000020666C9E2F0>, '__module__': '__main__', '__weakref__': <attribute '__weakref__' of 'abc' objects>, '__init__': <function abc.__init__ at 0x0000020666C9E268>, '__doc__': None, '__dict__': <attribute '__dict__' of 'abc' objects>}{'age': 18}
8.__getitem__ __setitem__ __delitem__
__getitem__方法匹配 对象[索引] 这种方式,__setitem__匹配 对象[索引]=value 这种方式,__delitem__匹配 del 对象[索引] 这种方式,例子如下:
class Foo: def __init__(self,name,age): self.name=name self.age=age def __getitem__(self, item): # 匹配:对象[item]这种形式 return item+10 def __setitem__(self, key, value): # 匹配:对象[key]=value这种形式 print(key,value) def __delitem__(self, key): # 匹配:del 对象[key]这种形式 print(key)li=Foo("alex",18)print(li[10])li[10]=100del li[10]执行结果:2010 10010
9.__getslice__ __setslice__ __delslice__
这三种方式在python2.7中还存在,用来对对象进行切片的,但是在python3之后,将这些特殊方法给去掉了,统一使用上面的方式对对象进行切片,因此在使用__getitem__ __setitem__ 这两个方法之前要先判断传递进参数的类型是不是slice对象。例子如下:
class Foo: def __init__(self,name,age): self.name=name self.age=age self.li=[1,2,3,4,5,6,7] def __getitem__(self, item): # 匹配:对象[item]这种形式 if isinstance(item,slice): # 如果是slice对象,返回切片后的结果 return self.li[item] # 返回切片结果 elif isinstance(item,int): # 如果是整形,说明是索引 return item+10 def __setitem__(self, key, value): # 匹配:对象[key]=value这种形式 print(key,value) def __delitem__(self, key): # 匹配:del 对象[key]这种形式 print(key) def __getslice__(self,index1,index2): print(index1,index2)li=Foo("alex",18)print(li[3:5])#执行结果:[4, 5]
10. __iter__
类的对象如果想要变成一个可迭代对象,那么对象中必须要有__iter__方法,并且这个方法返回的是一个迭代器。
for 循环的对象如果是一个可迭代的对象,那么会先执行对象中的__iter__方法,获取到迭代器,然后再执行迭代器中的__next__方法获取数据。如果for循环的是一个迭代器,那么直接执行迭代器中的__next__方法。
class Foo: def __init__(self,name,age): self.name=name self.age=age def __iter__(self): return iter([1,2,3,4,5]) # 返回的是一个迭代器li=Foo("alex",18)# 1.如果类中有__iter__方法,他的对象就是可迭代对象# 2.对象.__iter()的返回值是一个迭代器# 3.for循环的如果是迭代器,直接执行.next方法# 4.for循环的如果是可迭代对象,先执行对象.__iter(),获取迭代器再执行nextfor i in li: print(i)#执行结果:12345
11.isinstance和issubclass
之前讲过isinstance可以判断一个变量是否是某一种数据类型,其实,isinstance不只可以判断数据类型,也可以判断对象是否是这个类的对象或者是这个类的子类的对象,代码如下:
class Foo: def __init__(self,name,age): self.name=name self.age=ageclass Son(Foo): passobj=Son("xiaoming",18)print(isinstance(obj,Foo))执行结果:True
issubclass用来判断一个类是否是某个类的子类,返回的是一个bool类型数据,代码如下:
class Foo: def __init__(self,name,age): self.name=name self.age=ageclass Son(Foo): passobj=Son("xiaoming",18)print(issubclass(Son,Foo))执行结果:True
3.类与对象
__new__和__metaclass__
在python中,一切皆对象,我们定义的类其实。。。也是一个对象,那么,类本身是谁的对象呢?在python2.2之前(或者叫经典类中),所有的类,都是class的对象,但是在新式类中,为了将类型(int,str,float等)和类统一,所以,所有的类都是type类型的对象。当然,这个规则可以被修改,在类中有一个属性 __metaclass__ 可以指定当前类该由哪个类进行实例化。而创建对象过程中,其实构造器不是__init__方法,而是__new__方法,这个方法会返回一个对象,这才是对象的构造器。下面是一个解释类实例化对象内部实现过程的代码段:
class Mytype(type): def __init__(self, what, bases=None, dict=None): super(Mytype,self).__init__(what, bases, dict) def __call__(self, *args, **kwargs): obj=self.__new__(self) self.__init__(obj, *args, **kwargs) return objclass Foo: __metaclass__=Mytype def __init__(self,name,age): self.name=name self.age=age def __new__(cls, *args, **kwargs): return object.__new__(cls)obj=Foo("xiaoming",18)print(obj.name,obj.age)执行结果:xiaoming 18
4.异常处理
python中使用try except finally组合来实现异常扑捉,不像java中是使用try catch finally......其中,except中的Exception是所有异常的父类,下面是一个异常处理的示例:
try: int("aaa") #可能出现异常的代码except IndexError as e: # 捕捉索引异常的子异常,注意,这里的as e在老版本的py中可以写成,e但是新版本中用as e,",e"未来可能会淘汰 print("IndexError:",e)except ValueError as e: # 捕捉value错误的子异常 print("ValueError:",e)except Exception as e: # 如果上面两个异常没有捕获到,那么使用Exception捕获,Exception能够捕获所有的异常 print("Exception:",e)else: # 如果没有异常发生,执行else中的代码块 print("true")finally: # 不管是否发生异常,在最后都会执行finally中的代码,假如try里面的代码正常执行,先执行else中的代码,再执行finally中的代码 print("finally")执行结果:ValueError: invalid literal for int() with base 10: 'aaa'finally
那么既然Exception是所有异常的父类,我们可以自已定义Exception的子类,实现自定义异常处理,下面就是实现例子:
class OldBoyError(Exception): # 自定义错误类型 def __init__(self,message): self.message=message def __str__(self): # 打印异常的时候会调用对象里面的__str__方法返回一个字符串 return self.messagetry: raise OldBoyError("我错了...") # raise是主动抛出异常,可以调用自定义的异常抛出异常except OldBoyError as e: print(e)执行结果:我错了...
异常处理里面还有一个断言,一般用在判断执行环境上面,只要断言后面的条件不满足,那么就抛出异常,并且后面的代码不执行了。
print(123)assert 1==2 # 断言,故意抛出异常,做环境监测用,环境监测不通过,报错并结束程序print("456")执行结果: assert 1==2 # 断言,故意抛出异常,做环境监测用,环境监测不通过,报错并结束程序123AssertionError
5.反射/自省
python中的反射/自省的实现,是通过hasattr、getattr、setattr、delattr四个内置函数实现的,其实这四个内置函数不只可以用在类和对象中,也可以用在模块等其他地方,只是在类和对象中用的很多,所以单独提出来进行解释。
- hasattr(key)返回的是一个bool值,判断某个成员或者属性在不在类或者对象中
- getattr(key,default=xxx)获取类或者对象的成员或属性,如果不存在,则会抛出AttributeError异常,如果定义了default那么当没有属性的时候会返回默认值。
- setattr(key,value)假如有这个属性,那么更新这个属性,如果没有就添加这个属性并赋值value
- delattr(key)删除某个属性
注意,上面的key都是字符串,而不是变量,也就是说可以通过字符串处理类中的成员或者对象中的属性。下面是一个例子代码:
class Foo: def __init__(self,name,age): self.name=name self.age=age def show(self): return self.name,self.ageobj=Foo("xiaoming",18)print(getattr(obj,"name"))setattr(obj,"k1","v1")print(obj.k1)print(hasattr(obj,"k1"))delattr(obj,"k1")show_fun=getattr(obj,"show")print(show_fun())执行结果:xiaomingv1True('xiaoming', 18)
反射/自省能够直接访问以及修改运行中的类和对象的成员和属性,这是一个很强大的功能,并且并不像java中效率很低,所以用的很多。
下面是一个反射/自省用在模块级别的例子:
import s2operation=input("请输入URL:")if operation in s2.__dict__: getattr(s2,operation)()else: print("404")#模块s2中的代码:def f1(): print("首页")def f2(): print("新闻")def f3(): print("精选")执行结果:请输入URL:f1首页
6.单例模式
这里介绍一个设计模式,设计模式在程序员写了两三年代码的时候,到一定境界了,才会考虑到设计模式对于程序带来的好处,从而使用各种设计模式,这里只是简单的介绍一个简单的设计模式:单例模式。在面向对象中的单例模式就是一个类只有一个对象,所有的操作都通过这个对象来完成,这就是面向对象中的单例模式,下面是实现代码:
class Foo: # 单例模式 __v=None @classmethod def ge_instance(cls): if cls.__v: return cls.__v else: cls.__v=Foo() return cls.__vobj1=Foo.ge_instance()print(obj1)obj2=Foo.ge_instance()print(obj2)obj3=Foo.ge_instance()print(obj3)执行结果:<__main__.Foo object at 0x000001D2ABA01860><__main__.Foo object at 0x000001D2ABA01860><__main__.Foo object at 0x000001D2ABA01860>
可以看到,三个对象的内存地址都是一样的,其实,这三个变量中存储的都是同一个对象的内存地址,这样有什么好处呢?能够节省资源,就比如在数据库连接池的时候就可以使用单例模式,只创建一个类的对象供其他程序调用,还有在web服务中接收请求也可以使用单例模式来实现,节省资源。
第五篇:python高级之面向对象高级的更多相关文章
- python高级之面向对象高级
python高级之面向对象高级 本节内容 成员修饰符 特殊成员 类与对象 异常处理 反射/自省 单例模式 1.成员修饰符 python的类中只有私有成员和公有成员两种,不像c++中的类有公有成员(pu ...
- 第五篇python进阶之深浅拷贝
目录 第五篇python进阶之深浅拷贝 一.引言 1.1可变 和不可变 二.拷贝(只针对可变数据类型) 三.浅拷贝 四.深拷贝 第五篇python进阶之深浅拷贝 一.引言 1.1可变 和不可变 id不 ...
- 第五篇.python进阶
目录 第五篇.python进阶 1. 异常处理 2. 数字类型内置方法 2.定义: 3.常用操作+内置方法: 4.存一个值or多个值: 5.有序or无序: 6.可变和不可变 1.用途: 2.定义: 3 ...
- python基础之面向对象高级编程
面向对象基本知识: 面向对象是一种编程方式,此编程方式的实现是基于对 类 和 对象 的使用 类 是一个模板,模板中包装了多个"函数"供使用(可以讲多函数中公用的变量封装到对象中) ...
- Python学习--11 面向对象高级编程
多重继承 Python里允许多重继承,即一个类可以同时继承多个类: class Mammal(Animal): pass class Runnable(object): def run(self): ...
- Python之路【第五篇续】:面向对象编程二
aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAABgQAAALaCAIAAABxja8cAAAgAElEQVR4nOzd6X9Tdd74/+uv+f5uzF
- 9.Python笔记之面向对象高级部分
类的成员 类的成员可以分为三大类:字段.方法和属性 注:所有成员中,只有普通字段的内容保存对象中,即:根据此类创建了多少对象,在内存中就有多少个普通字段.而其他的成员,则都是保存在类中,即:无论对象的 ...
- Python基础——7面向对象高级编程
实例与类动态添加方法 实例添加属性: def Student(object): pass s = Student() s.name = ‘syz’ 实例添加方法 from types import M ...
- 【Python之路】第七篇--Python基础之面向对象及相关
面向对象基础 基础内容介绍详见一下两篇博文: 面向对象初级篇 面向对象进阶篇 其他相关 一.isinstance(obj, cls) 检查obj是否是类 cls 的对象 class Foo(objec ...
随机推荐
- 去除UINavigationBar默认透明度的方法
UINavigationbar的属性translucent,用来控制导航条的透明度的: iOS7+版本后,navigationbar的translucent属性默认为YES,及默认带有透明度 [sel ...
- 2016年 IT 趋势大预测!
新年伊始,有不少人在总结过去,也有一些人在展望未来.下面让我们跟随 OpsClarity 的 Dhruv Jain,看看他对 2016 IT 趋势有什么大胆的预测. 又到了众人纷纷对下一年进行预测的时 ...
- windows下NGINX和PHP配合(FASTCGI)
昨天测试了TOMCAT,今天考查了NGINX. 按网上说的作,比较简单. http://www.cnblogs.com/huayangmeng/archive/2011/06/15/2081337.h ...
- Windows多桌面切换(CreateDesktop,SwitchDesktop函数)
unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms ...
- TEdit,TMemo背景透明
The component below works perfectly, except for the following problem: 1) Saves the component below ...
- druid配置(转)
java程序很大一部分要操作数据库,为了提高性能操作数据库的时候,有不得不使用数据库连接池.数据库连接池有很多选择,c3p.dhcp.proxool等,druid作为一名后起之秀,凭借其出色的性能,也 ...
- android通用文件操作
最经用到android的SCCard的文件操作,因此稍作了整理,将它写成一个简单的工具类.其中,可以判断SDCard的是否可用,可用存储空间,文件的创建以及写入数据.经过测试,可以正常使用.代码如下: ...
- Linux Shell编程(10)——引用变量
当要引用一个变量的值时,一般推荐使用双引号.使用双引号除了变量名前缀($).后引符(`)和转义符(\)外,会使shell不再解释引号中其它所有的特殊字符.用双引号时$仍被当成特殊字符,允许引用一个被双 ...
- Linux系统Wpa_supplicant用法小结
Wpa_supplicant是linux系统下一个非常强大的无线网卡管理程序.google搜索到的它似乎不支持WPA2和AES,其实不然,参考它的文档可以发现,WPA2只是RSN的别名,而AES也是C ...
- 实例讲解MSSQL日期相加减比大小函数 转
1. 当前系统日期.时间select getdate() 2. dateadd 在向指定日期加上一段时间的基础上,返回新的 datetime 值例如:向日期加上2天select dateadd(day ...