python_way,day8 面向對象【多態、成員--字段 方法 屬性、成員修飾符、特殊成員、異常處理、設計模式之單例模式、模塊:isinstance、issubclass】

python_way day8

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、異常處理

 


 

1、多態

   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。
例子

2、python面向對象的類成員

字段、方法、屬性

一、字段:

  靜態字段,普通字段

  class Foo:
        CC = 123 #字段: 靜態字段(屬於類)
 
         def __init__(self):
            self.name = "alex"   #這一行就是字段(普通字段),保存在對象裏面。
                                              #建立多個對象,每一個對象都有這個字段 
        def show(slef):
                print(self.name)

 靜態字段的好處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源碼
Django源碼

因此,定義屬性共有兩種方式,分別是【裝飾器】和【靜態字段】,而【裝飾器】方式針對經典類和新式類又有所不一樣。

 


3、成員修飾符

  公有、私有

  成員修飾符是對類成員設置權限的,成員:字段,方法,屬性

  公有:字段

  

在類的外部和內容部都能訪問的字段,就是公有字段

  私有:普通字段

  

哪繼承能夠訪問嗎?

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)

寫法:_類名__方法

4、面向對象中特殊成員

特殊成員就是 __ 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
__str__ 使用方法

七、__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
__add__ 使用方法

八、__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>}
__dict__ 使用方法

 九、 obj[] 這種寫法是什麼鬼?

   基本操做 

 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
__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
__setitem__ 使用方法

  

  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
__delitem__ 使用方法

 

用處:自定義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'>
obj[1:2]這樣傳入值的類型

__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
__iter__ 使用方法
使用生成器來作一個可迭代對象
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()

 

5、面向對象中其餘的知識點

  一、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’)的上面和下面分別輸出句話
源碼 : /banchend/commons.py
 
 /index.py
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()
修改的主程序 /index.py
 
/NewFoo  自定義類
from backend import commons

class New_Foo(commons.Foo): #新的類繼承源碼類
    def f1(self):
        print("befor")   #上面多輸出一行
        super(New_Foo,self).f1()#使用super來強制調用父類f1方法
        print("after")    #下面多輸出一行
新增字段位置 /NewFoo
 
還須要一個配置文件 /setting
Path = "NewFoo"     #這個就對應着反射查找的位置
ClassName = "New_Foo"    #這個對應着新的類
還須要一個配置文件 /setting

 

四、製做一個有序的字典

  思路,在字典的基礎上進行操做,字典沒有提供有序的功能,我就提供這個沒有的功能  

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))

 


6、設計模式——單例模式

   表示只有一個實例,一個對象:

      用來建立單個實例:

 

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)
IndexError

 

dic = {'k1':'v1'}
try:
    dic['k20']
except KeyError as ex:
    print(ex)
KeyError

 

s1 = 'hello'
try:
    int(s1)
except ValueError as ex:
    print(ex)
ValueError

 

捕獲想要的異常操做

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)
          tryassert 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()
源碼應用場景
相關文章
相關標籤/搜索