1、面向對象三大特性:java
多態python
2、面向對象中的成員git
字段、方法屬性編程
3、成員修飾符c#
4、特殊成員設計模式
__init__、__doc__、__call__、__setitem__、__getitem__、___delitem__、__str__、__all__cookie
5、面向對象其餘session
--isinstance架構
--issubclassapp
--繼承2.7
--應用:一、自定義類型(作一個有序的字典)
二、源碼的擴展
6、設計模式之單例模式
7、異常處理
python裏面定義一個函數,能夠傳入不一樣類型的變量
def func(arg):
print(arg)
可是在c#/java中,arg這個參數必需要指定類型 '
若是在定義是指定了int類型數據,此時傳入了str類型,就會報錯了
在python中可傳入任意類型這就是多態的一個表現
在java中若是想讓java中支持多態,就要用繼承來實現多態了
好比:
def func(int arg)
print(arg)
這個int能夠是int和int的派生類
Class A: pass Class B(A): pass Class C(A): pass def func(A arg): print(arg) 此時arg前面就能夠是A/B/C三種類型了。 由於此時你要是寫進入一個C類型,你又傳入一個A類。它先回判斷是否是屬於C類,不屬於就往他的父類上面找。就找到了A。
字段、方法、屬性
一、字段:
靜態字段,普通字段
靜態字段的好處class Province:
def __init__(self,name): self.name = name self.county = "中國" hn = Province("河南")
county = hn.county #普通字段用對象訪問字段 hb = Province("河北") #這樣每一個建立出一個對象中都保存着省份名字,和中國 #有不少省份的時候重複儲存中國,耗費內存 若是使用靜態字段 class Province: county = "中國" def __init__(self,name): self.name = name a = Province.county 訪問靜態字段用類名訪問
#在python中靜態字段也能夠用對象訪問,可是儘可能別用,若是哪一天改版,不讓用了,你的代碼就要重構。。。
print(a) 中國 #county保存在類中,不用建立對象也能夠訪問靜態字段,由於靜態字段是屬於類 #這樣你們共用這一個靜態字段
訪問規則:
普通字段,用對象訪問
靜態字段,用類訪問,若是在你找不到類的時候萬不得已了,用一下。
二、方法
普通方法,靜態方法,類方法
類中的而函數增長一個self就是方法
普通方法:
普通方法屬於類,是由對象調用執行
靜態方法:
class Foo: def __init__(self,name): self.name = name self.age = 18 def show(self): print(self.name) def arg(self): print(self.age) #建立一個靜態方法 #這個方法用不到這個類的對象,因此把self去掉,支持傳參數 @staticmethod def f1(arg1): #參數任意,無關緊要 print(arg1) return True
#靜態方法屬於類,全部不用建立對象就能夠調用 a = Foo.f1("靜態方法") #執行, 類執行,也能夠用對象執行,不到萬不得已不要這麼用。 print(a)
靜態方法
True
其實靜態方法和函數的功能是同樣的,只不過它屬於一個類,用處就是這個方法可能和這個類有某種關係,就是爲了歸類
類方法:
屬於靜態方法的特殊形式
class Foo: def __init__(self,name): self.name = name self.age = 18 def p1(self): print(self.name) @staticmethod #靜態方法 def f1(arg1): print(arg1) return True @classmethod #類方法 def f2(cls):# cls是必須有的參數,在cls就像是函數中的self,cls就是類本身自己 print(cls) cls.f1("類方法直接調用靜態方法") t1 = cls("類方法調用普通方法") t1.p1()#類方法調用普通方法
Foo.f2() #執行 由類執行,也能夠對象執行,可是不到萬不得已不要這麼用。
<class '__main__.Foo'>
類方法直接調用靜態方法
類方法調用普通方法
三、屬性
具備方法的寫做形式,具備字段的訪問形式
屬性本質就是方法,只是用訪問字段的方式來執行方法
class pager: def __init__(self, all_count, pager_count): self.all_count = all_count self.pager_count = pager_count def all_pager(self): k1, k2 = divmod(self.all_count, self.pager_count) if k2 == 0: return k1 else: return k1 + 1 @property #加上這個裝飾器在執行這個方法就不用加括號了 def all_pager1(self): k1, k2 = divmod(self.all_count, self.pager_count) if k2 == 0: return k1 else: return k1 + 1 a = pager(101, 10) print(a.all_count) #這樣的寫法是獲取字典 pager_num = a.all_pager() #這樣的寫法是執行方法
pager_num1 = a.all_pager1 #這樣寫法就是用 獲取字段的方式 執行方法
屬性的擴展用法:
咱們能夠以調取字段的寫法 來執行 方法
哪先來看看字段均可以幹什麼
ret = a.all_count #這是讀取字段中的值 這個寫法對應屬性是 pager_num1 = a.all_pager1
a.all_count = 105 #這是從新給字段賦值 這個寫法對應屬性是什麼 ???
del a.all_count #這是刪除字段 這個寫法對應屬性有是什麼 ???
咱們來看看怎麼用賦值的方法來操做
class pager: def __init__(self, all_count, pager_count): self.all_count = all_count self.pager_count = pager_count @property #加上這個裝飾器在執行這個方法就不用加括號了 def all_pager1(self): k1, k2 = divmod(self.all_count, self.pager_count) if k2 == 0: return k1 else: return k1 + 1 @all_pager1.setter #將具備屬性的方法名做爲這個方法的裝飾器 + setter, def all_pager1(self,value): #而且這個方法的名稱和具備屬性功能的方法名稱相同 print(value)
a.all_pager1 = 106 #這樣就能夠將106這個值傳入類中的all_pager1(value)這個方法中了
106
哪del 字段 這個寫法在屬性中怎麼使用呢?class pager:
def __init__(self, all_count, pager_count): self.all_count = all_count self.pager_count = pager_count def all_pager(self):#普通方法 k1, k2 = divmod(self.all_count, self.pager_count) if k2 == 0: return k1 else: return k1 + 1 @property #屬性 k1, k2 = divmod(self.all_count, self.pager_count) if k2 == 0: return k1 else: return k1 + 1def all_pager1(self): print("del all_pager1")
a = pager(101,10)
del a.all_pager1
屬性的主流表達方式
################################# 定義 ####################################################
class Foo: def __init__(self,num): self.num = num def get_num(self): return self.num def set_num(self,value): print( self.num + value ) def del_num(self): print( self.num - 1) foo = property(fget=get_num,fset=set_num,fdel=del_num) ################################### 調用 ################################################# obj = Foo(5) result1 = obj.foo #去執行foo中的 fget對應的方法 print(result1) obj.foo = 5 #去執行foo中的 fset對應的方法 del obj.foo #去執行foo中的 fdel對應的方法
注意:Python WEB框架 Django 的視圖中 request.POST 就是使用的靜態字段的方式建立的屬性
class WSGIRequest(http.HttpRequest): def __init__(self, environ): script_name = get_script_name(environ) path_info = get_path_info(environ) if not path_info: # Sometimes PATH_INFO exists, but is empty (e.g. accessing # the SCRIPT_NAME URL without a trailing slash). We really need to # operate as if they'd requested '/'. Not amazingly nice to force # the path like this, but should be harmless. path_info = '/' self.environ = environ self.path_info = path_info self.path = '%s/%s' % (script_name.rstrip('/'), path_info.lstrip('/')) self.META = environ self.META['PATH_INFO'] = path_info self.META['SCRIPT_NAME'] = script_name self.method = environ['REQUEST_METHOD'].upper() _, content_params = cgi.parse_header(environ.get('CONTENT_TYPE', '')) if 'charset' in content_params: try: codecs.lookup(content_params['charset']) except LookupError: pass else: self.encoding = content_params['charset'] self._post_parse_error = False try: content_length = int(environ.get('CONTENT_LENGTH')) except (ValueError, TypeError): content_length = 0 self._stream = LimitedStream(self.environ['wsgi.input'], content_length) self._read_started = False self.resolver_match = None def _get_scheme(self): return self.environ.get('wsgi.url_scheme') def _get_request(self): warnings.warn('`request.REQUEST` is deprecated, use `request.GET` or ' '`request.POST` instead.', RemovedInDjango19Warning, 2) if not hasattr(self, '_request'): self._request = datastructures.MergeDict(self.POST, self.GET) return self._request @cached_property def GET(self): # The WSGI spec says 'QUERY_STRING' may be absent. raw_query_string = get_bytes_from_wsgi(self.environ, 'QUERY_STRING', '') return http.QueryDict(raw_query_string, encoding=self._encoding) # ############### 看這裏看這裏 ############### def _get_post(self): if not hasattr(self, '_post'): self._load_post_and_files() return self._post # ############### 看這裏看這裏 ############### def _set_post(self, post): self._post = post @cached_property def COOKIES(self): raw_cookie = get_str_from_wsgi(self.environ, 'HTTP_COOKIE', '') return http.parse_cookie(raw_cookie) def _get_files(self): if not hasattr(self, '_files'): self._load_post_and_files() return self._files # ############### 看這裏看這裏 ############### POST = property(_get_post, _set_post) FILES = property(_get_files) REQUEST = property(_get_request) Django源碼
因此,定義屬性共有兩種方式,分別是【裝飾器】和【靜態字段】,而【裝飾器】方式針對經典類和新式類又有所不一樣。
公有、私有
成員修飾符是對類成員設置權限的,成員:字段,方法,屬性
公有:字段
在類的外部和內容部都能訪問的字段,就是公有字段
私有:普通字段
哪繼承能夠訪問嗎?
class Foo: def __init__(self, name): self.__name = name def f1(self): print(self.__name) obj = Foo("han") print(obj.__name) obj.f1() class F1(Foo): def f1(self): print(self.__name) obj1 = F1("han") print(obj1.f1())
AttributeError: 'Foo' object has no attribute '__name'
繼承也不能訪問私有字段,只能本身類內部訪問
私有:靜態字段
class Foo: __CC = 123 def __init__(self, name): self.__name = name def f1(self): print(self.__name)
@classmethod #類方法調用本身
def f2(cls):
return cls.__CC
@staticmethod #靜態方法調用
def f3(cls):
return cls.__CC
######### 調用私有靜態字段 ######### ret = Foo.__CC
print(ret)
也是不能c從外部訪問
只能從類的內部訪問
ret = Foo.f2
ret2 = Foo.f3(Foo)
print(ret)
print(ret2)
123
123
私有:普通方法
class Foo: __CC = 123 def __init__(self, name): self.__name = name def __f1(self): print(self.__name) def t1(self,obj): obj.__f1()
obj = Foo("han")
obj.__f1() #這樣是執行不了這個方法的
obj.t1(obj) 只能這樣從內部調用
私有:靜態方法
類方法:
class Foo: __CC = 123 def __init__(self, name): self.__name = name @classmethod def __f2(cls): return cls.__CC def t2(self): return self.__f2() obj = Foo("han") obj.__f2() #這樣是執行不了的 ret = obj.t2() 這樣內部調用t2,來間接的在內部執行__f2私有方法
print(ret)
123
靜態方法
class Foo: __CC = 123 def __init__(self, name): self.__name = name @staticmethod def __f3(cls): (須要方法參數) #定義了一個私有方法 return cls.__CC def t3(self,cls): #內部定義了一個方法,訪問上面的私有方法 return self.__f3(cls) obj = Foo("han") obj.t3(Foo) #也須要在內部調用
#python中也能夠訪問私有方法
############################ 定義 靜態私有字段、私有字段、靜態私有方法 #########################
class Foo: __CC = 123 #靜態私有字段 def __init__(self, name): self.__name = name #靜態字段 @staticmethod def __f3(cls): (須要方法參數) #定義了一個靜態私有(類)方法 return cls.__CC def t3(self,cls): #內部定義了一個方法,訪問上面的私有方法 return self.__f3(cls)
######################## 調用 ############################################################
#一、咱們想從外部直接訪問私有方法
obj = Foo("han")
ret = obj._Foo__f3
print(ret)
#二、咱們想從外部直接訪問私有靜態字段
ret1 = Foo._Foo__CC(使用類訪問靜態私有字段)
ret2 = obj._Foo__CC(使用函數訪問靜態私有字段---不建議使用)
#三、咱們從外部直接訪問私有字段
ret3 = obj._Foo__name
_Foo 就是後門
print(ret1,ret2,ret3)
寫法:_類名__方法
特殊成員就是 __ XXX__,兩邊有下劃線的。
一、__init__ : 構造方法,建立對象自動執行
obj = Foo() 此時對象剛出生,這時是自動執行__init__
二、__del__ : 析構方法,垃圾回收機制立刻要清除不用的對象時就會執行這個方法
等咱們不用這obj的時候。垃圾回收機制就會清除這個對象,在清除以前的一剎那,要是有__del__ 就會自動執行__del__.沒有就直接清除。
三、__doc__ : 把類的註釋保存在裏面
四、__module__ & __class__
module:在建立一個對象時,想要知道這個對象在那個模塊中
class : 這個對象的類名是什麼
shuxing
<class 'shuxing.Foo'> #若是在相同的模塊下就會顯示 <class '__main__.Foo'>
五、__call__
class Foo: def __init__(self,arg1): self.name = arg1 def __call__(self,arg2): return arg2 obj = Foo("init") #類後面加() 是執行__init__ 方法 print(obj.name) ret = obj("call") #對象後面加() 是執行 __call__ 方法 print(ret)
init
call
class Foo: def __init__(self): print("init") def __call__(self): print("call") Foo()() #先執行構造方法,再執行call方法
init
call
#這個知道就能夠了
六、__str__
打印一個建立好的對象,在沒有定義str的時候 只會打印這個對象的內存地址
定之後就會打印這個方法下面return的內容
class Foo: def __init__(self,name): self.name = name def __str__(self): return self.name obj = Foo("han") print(obj), #不打印就用str(obj)來回去到return的值 han ret = str(obj) print(ret) han
七、__and__
用途:兩個對象相加,就會執行前面對象中定義的 __add__ 方法
lass Foo: def __init__(self,name, age): self.name = name self.age = age def __add__(self, other): msg = "%s - %d" % (self.name, other.age) return msg obj1 = Foo("han",20) obj2 = Foo("shi",40) ret = obj1 + obj2 #self 則是 obj1 ,other 則是obj2 print(ret) han - 40
八、__dict__
用途:將對象中全部封裝的字段取出來
#dict 本身不用寫,對象中默認就有
class Foo: __CC = 123 BB = 000 def __init__(self,name, age): self.name = name self.age = age def __add__(self, other): msg = "%s - %d" % (self.name, other.age) return msg obj1 = Foo("han",20) obj2 = Foo("shi",40) ret1 = obj1.__dict__ ret2 = Foo.__dict__ print(ret1,"\n",ret2) {'age': 20, 'name': 'han'} {'__module__': '__main__', '__add__': <function Foo.__add__ at 0x0000000D688CF2F0>, '__doc__': None, '__weakref__': <attribute '__weakref__' of 'Foo' objects>, 'BB': 0, '_Foo__CC': 123, '__dict__': <attribute '__dict__' of 'Foo' objects>, '__init__': <function Foo.__init__ at 0x0000000D688CF268>}
基本操做
a、__getitem__
提問:
dic = {"k1":123} #建立dic字段 dic = dict("k1" = 123) d1 = dic["k1"] #獲取k1的value dic["k1"] = 345 #給k1的value 改值
del dic["k1"] #刪除
在一個對象後面加() obj()執行call方法
那麼在對象後面加[] obj[] 是什麼鬼?這個語法究竟是執行什麼方法呢?
obj[] 這麼寫就是執行 __gititem__方法
lass Foo: __CC = 123 BB = 000 def __init__(self,name, age): self.name = name self.age = age def __getitem__(self, item=None): if not item: print("getitem") else: print(item) obj = Foo("han",123) obj["ab"] getitem
語法:在執行obj[]語法的時候就會執行 __getitem__這個方法,而後會把【】中的值傳進item中
b、__setitem__
obj[] = 123 這麼寫就是執行 __setitem__方法
class Foo: __CC = 123 BB = 000 def __init__(self,name, age): self.name = name self.age = age def __setitem__(self, key, value): print(key,value) obj = Foo("han",123) obj["ab"] = 444 ab 444
c、__delitem__
del obj[]這麼寫就是執行__delitem__方法
class Foo: __CC = 123 BB = 000 def __init__(self,name, age): self.name = name self.age = age def __delitem__(self, key): print(key,"del") obj = Foo("han",123) del obj["ab"] ab del
用處:自定義session框架時會使用
===================================================================
切片方式操做
obj[1:2] 這樣咱們怎麼操做?
class Foo: __CC = 123 BB = 000 def __init__(self,name, age): self.name = name self.age = age def __getitem__(self, item): print(type(item)) obj = Foo("han",123) ret = obj[1:5] <class 'slice'>
__getitem__
obj[1:2] 仍是用的 getitem 方法
因此obj[1:2]傳入的類型是slice
那咱們怎麼操做這樣傳入的數據哪?
python3中就這樣作的
obj[1:5:4] = [11,22,33,44]
__setitem__
obj[1:5:4] = [11,22,33,44] 也是用的 __setitem__方法
del obj[1:5:4]
__delitem__
del obj[1:5:4]也是用的 __deltiem__方法
十、__iter__
讓對象的返回值迭代起來
默認返回的對象是不可迭代的
class Foo: def __init__(self,num): self.num = num def test(self): return self.num obj = Foo([1,2,3,4]) for i in obj: print(i) TypeError: 'Foo' object is not iterable 默認對象是不能迭代的
使用__iter__ 方法後,迭代這個對象時,就會默認執行類中的__iter__方法。
class Foo: def __init__(self,num): self.num = num def test(self): return self.num def __iter__(self): return iter(self.num) obj = Foo([1,2,3,4]) for i in obj: print(i) 1 2 3 4
使用生成器來作一個可迭代對象
class Foo: def __init__(self,num): self.num = num def test(self): return self.num def __iter__(self): for i in self.num: yield i 1 2 3 4
對象被迭代的步驟,一、將對象放到for中,二、找對象中的__iter__方法,三、__iter__中返回值能夠被迭代。 ''
十一、 __all__
這個特殊方式是在被倒入的時候生效的
好比咱們有2個module 一個是 test1,一個是test2
test2 要倒入test1 中的類咱們能夠有幾種方式
1. import test1.Foo1 ... ...
2.import test1
3.from test1 import Foo1
4.from test1 import *
目前測試 __all__ 是在最後一種方式倒入的時候生效
若是咱們在test1中定義了 __all__ , from test1 import * 時只會找到再__all__ 裏面定義的類作倒入
test1.py
__all__ = ["Foo1", "Foo2"] class Foo1: def f1(self): print("foo1") class Foo2: def f1(self): print("foo2") class Foo3: def f1(self): print("foo3") class Foo4: def f1(self): print("foo4")
test2.py
from test1 import * #若是這樣倒入就只能找到Foo1,和Foo2,由於Foo3和Foo4沒有在test1的__all__列表中 a = Foo1() a.f1() b = Foo2() b.f1() c = Foo3() c.f1() d = Foo4() d.f1()
一、isinstence
判斷這個對象是否是某個類的子類
class Foo: def __init__(self,num): self.num = num def test(self): return self.num def __iter__(self): for i in self.num: yield i obj = Foo([1,2,3,4]) ret = isinstance(obj,Foo) print(ret) True
補充:Foo,能夠是bar的類型,也能夠是bar的父類。
class Bar: pass class Foo(Bar): def __init__(self,num): self.num = num def test(self): return self.num def __iter__(self): for i in self.num: yield i obj = Foo([1,2,3,4]) ret = isinstance(obj,Bar) print(ret)
二、issubclass
查看一個類是否是另外一個類的子類
class Foo: def __init__(self,num): self.num = num def test(self): return self.num def __iter__(self): for i in self.num: yield i class Bar(Foo): pass obj = Foo([1,2,3,4]) ret = issubclass(Bar,Foo) print(ret) True
三、super()
執行父類中相同名稱的方法
class C1: def f1(self): print("c1.f1") class C2(C1): def f1(self): print("c2.f1") obj = C2() obj.f1() #由於子類和父類同時都有一個f1方法,因此優先執行子類C2中的函數
此時我要是想主動的執行如下父類C1的函數怎麼辦?
class C1: def f1(self): print("c1.f1") return 123 class C2(C1): def f1(self): a = super(C2,self).f1() #這一步就是主動的先執行父類中的f1方法,並能夠獲取f1方法中的返回值 print(a) obj = C2() obj.f1() c1.f1 #先執行C1中的f1方法 123 #再執行C2中的f1方法
私用場景:假如使用了大型的第三方架構,若是某一個功能不是你想要的,想要增長一點功能,若是你修改源碼,很差,就本身寫一個類,而後繼承原來的源碼使用super就能夠
#另外一種非主流的寫法 class C1: def f1(self): print("c1,f1") return 123 class C2(C1): def f1(self): C1.f1(self) #執行C1這個類的f1方法,可是要講本身的self傳進去。 #這樣也能夠主動執行父類的f1方法
應用
/banchend/commons.py 源碼
class Foo: def f1(self): print('Foo.f1') #源碼的代碼,咱們要在不改動源碼的前提下在 print(‘Foo.f1’)的上面和下面分別輸出句話
from settings import ClassName from settings import Path def execute(): module = __import__(Path,fromlist=True) if hasattr(module,ClassName): cls = getattr(module,ClassName) obj = cls() obj.f1() else: print("no module") if __name__ == '__main__': execute()
from backend import commons class New_Foo(commons.Foo): #新的類繼承源碼類 def f1(self): print("befor") #上面多輸出一行 super(New_Foo,self).f1()#使用super來強制調用父類f1方法 print("after") #下面多輸出一行
Path = "NewFoo" #這個就對應着反射查找的位置 ClassName = "New_Foo" #這個對應着新的類
四、製做一個有序的字典
思路,在字典的基礎上進行操做,字典沒有提供有序的功能,我就提供這個沒有的功能
class MyDict(dict): def __init__(self): self.li = [] #個人init方法,可是咱們又還要使用dict的init方法 super(MyDict,self).__init__()#這樣就保留下來了源碼的init方法 def __setitem__(self, key, value): self.li.append(key) #將key添加到本身維護的列表中 , 可是咱們key,value沒有傳入到字典中去 super(MyDict, self).__setitem__(key,value) #那就再使用父類的setitem方法來保存key,value def __delitem__(self, key): #刪除字典用某個元素 num = self.li.index(key) #從列表中找到key的位置 del self.li[num] #從列表中刪除 super(MyDict, self).__delitem__(key) #還要從字典中刪除,那就交給父類的delitem把 def __str__(self): #orint的時候展現 new_list = [] for k in self.li: #循環遍歷自定義的key列表 v = self.get(k) #用繼承過來的get功能獲取到對應的velue new_list.append("'%s':%s" % (k, v)) #將key和velue 按照 key:velue的方式保存到新的空列表中 temp_str = ",".join(new_list) #以,分割轉換成爲字符串 temp = "{" + temp_str + "}" #先後各加上大括號 return temp #輸出
執行
###### 生成對象 ############## from My_Dict import MyDict obj = MyDict() ###### 賦值 ################# #此時使用了__setitem__ 功能 obj["k1"] = [1,2,3] obj["k2"] = [2,3,4] obj["k3"] = [4,5,6] ####### 刪除 ################ #此時使用了__delitem__ 功能 del obj["k1"] ####### 輸出 ################ #此時使用了__str__功能 print(obj,type(obj))
表示只有一個實例,一個對象:
用來建立單個實例:
class C1: instance = None #靜態字段 def __init__(self,name): self.name = name def __str__(self): return self.name @classmethod def get_inistance(cls): #建立個類方法 if cls.instance: #若是此時的靜態字段爲真 return cls.instance #返回這個靜態字段 else: #不爲真,也就是第一次訪問 obj = cls("han") #對這個類建立一個對象 cls.instance = obj #而後賦值給靜態字段 return obj #而後返回這個對象 obj = C1.get_inistance() obj1 = C1.get_inistance() print(id(obj)) print(id(obj1)) 949172666552 949172666552
第一次建立對象,將對象賦值給靜態字段,再次要建立對象時會去看看靜態字段裏面,有值則會把以前在類中生成的obj返回出來。
經過靜態字段保存對象狀態,下次再來時直接返回。
在編程過程當中爲了增長友好性,在程序出現bug時通常不會將錯誤信息顯示給用戶,而是現實一個提示的頁面,通俗來講就是不讓用戶看見大黃頁!!!
try: pass 若是準確就執行try中代碼 except Exception,ex: #若是有錯誤就執行這裏面的代碼 pass
一、普通異常處理
while True: num1 = input('num1: ') num2 = input("num2: ") num1 = int(num1) num2 = int(num2) ret = num1 + num2 #若是num1 或 num2 不爲 整數類型就會報錯 ValueError: invalid literal for int() with base 10: 'ads' #而後程序就終止了
while True: num1 = input('num1: ') num2 = input("num2: ") try: #若是正常,則執行try裏的代碼 num1 = int(num1) num2 = int(num2) ret = num1 + num2 except Exception as ex: #若是不正常,報錯被Exception截獲,並建立ex對象,而後打印ex。這樣就不會由於報錯,致使程序終止了。 print(ex)
二、多種異常種類
1 AttributeError 試圖訪問一個對象沒有的樹形,好比foo.x,可是foo沒有屬性x 2 IOError 輸入/輸出異常;基本上是沒法打開文件 3 ImportError 沒法引入模塊或包;基本上是路徑問題或名稱錯誤 4 IndentationError 語法錯誤(的子類) ;代碼沒有正確對齊 5 IndexError 下標索引超出序列邊界,好比當x只有三個元素,卻試圖訪問x[5] 6 KeyError 試圖訪問字典裏不存在的鍵 7 KeyboardInterrupt Ctrl+C被按下 8 NameError 使用一個還未被賦予對象的變量 9 SyntaxError Python代碼非法,代碼不能編譯(我的認爲這是語法錯誤,寫錯了) 10 TypeError 傳入對象類型與要求的不符合 11 UnboundLocalError 試圖訪問一個還未被設置的局部變量,基本上是因爲另有一個同名的全局變量, 12 致使你覺得正在訪問它 13 ValueError 傳入一個調用者不指望的值,即便值的類型是正確的
1 ArithmeticError 2 AssertionError 3 AttributeError 4 BaseException 5 BufferError 6 BytesWarning 7 DeprecationWarning 8 EnvironmentError 9 EOFError 10 Exception 11 FloatingPointError 12 FutureWarning 13 GeneratorExit 14 ImportError 15 ImportWarning 16 IndentationError 17 IndexError 18 IOError 19 KeyboardInterrupt 20 KeyError 21 LookupError 22 MemoryError 23 NameError 24 NotImplementedError 25 OSError 26 OverflowError 27 PendingDeprecationWarning 28 ReferenceError 29 RuntimeError 30 RuntimeWarning 31 StandardError 32 StopIteration 33 SyntaxError 34 SyntaxWarning 35 SystemError 36 SystemExit 37 TabError 38 TypeError 39 UnboundLocalError 40 UnicodeDecodeError 41 UnicodeEncodeError 42 UnicodeError 43 UnicodeTranslateError 44 UnicodeWarning 45 UserWarning 46 ValueError 47 Warning 48 ZeroDivisionError
實例:
dic = ["han","xu"] #一共就2個元素 try: dic[10] #這裏卻獲取第10個元素 except IndexError as ex: #indexerror就是捕獲索引錯誤的 print(ex)
dic = {'k1':'v1'} try: dic['k20'] except KeyError as ex: print(ex)
s1 = 'hello' try: int(s1) except ValueError as ex: print(ex)
捕獲想要的異常操做
while True: num1 = input("num1 ") num2 = input("num2 ") try: num1 = int(num1) num2 = int(num2) ret = num1 + num2 print(ret) except ValueError as ex: #若是想對某種錯誤進行關注,就能夠這樣有針對性的進行錯誤捕獲 print(ex) #這裏就能夠用日誌來記錄到文件中 except IndexError as ex: print(ex) except Exception as ex: #除了這兩種錯誤,我就能夠把其餘的進行籠統的捕獲 print(ex) #這裏的錯誤就能夠顯示到屏幕上來。
看到上面的例子咱們就知道了,爲了程序的正常運行咱們會在最下面用一個Exception這個萬能的異常,上面是想捕捉的這些異常。
三、完整異常處理:
while True: num1 = input("num1 ") num2 = input("num2 ") try: num1 = int(num1) #正常的業務邏輯代碼 num2 = int(num2) ret = num1 + num2 print(ret) except ValueError as ex: #若是想對某種錯誤進行關注,就能夠這樣有針對性的進行錯誤捕獲 print(ex) #這裏就能夠用日誌來記錄到文件中 except IndexError as ex: print(ex) except Exception as ex: #除了這兩種錯誤,我就能夠把其餘的進行籠統的捕獲 print(ex) #這裏的錯誤就能夠顯示到屏幕上來。 else: print("沒有錯就執行") finally: print("有沒有錯都執行")
四、主動觸發異常
while True: num1 = input("num1 ") num2 = input("num2 ") try: raise Exception("錯誤") #這裏能夠隨意定義異常的類型,定義什麼類型的異常,下面就能夠接受什麼樣的類型 print(123) #由於上面主動執行了異常,因此這裏就不執行了 except ValueError as ex: #若是想對某種錯誤進行關注,就能夠這樣有針對性的進行錯誤捕獲 print(ex,"value") except IndexError as ex: print(ex,"index") except Exception as ex: #上面raise的異常就被這裏接受了 print(ex,"except")
五、斷言
assert
使用方法
while True: num1 = input("num1 ") num2 = input("num2 ") try: assert int(num1) == int(num2) #若是這兩個值相等,則執行print(123) print(123) #若是不相等,就直接報錯 except AssertionError as ex: print(ex, "assert") else: print("沒有錯就執行") finally: print("有沒有錯都執行")
若是有個對象是啓動某個程序的,想啓動某些程序須要知足的條件: 當前這個程序應該是中止狀態, 這個程序有個方法 class process: def status(self): ret = 查看當前程序的狀態 (True/False) return ret def start(self) try: assert self.status() == False #在這裏就至關於判斷了狀態,若是等於False,就知足啓動條件,不然就報錯了 則執行啓動程序 except AssertionError as ex: #這裏接受報錯 print(ex, "assert") #並打印
from multiprocessing import pool b = pool.Pool b.join() def join(self): util.debug('joining pool') assert self._state in (CLOSE, TERMINATE) #能知足我這個條件就往下執行,不然就拋出個異常 self._worker_handler.join() self._task_handler.join() self._result_handler.join() for p in self._pool: p.join()