基礎:談面向對象就要從他的三大特性開始提及,如:封裝、繼承、多態。 封裝: - 方法封裝到來類中:某一類功能類似的方法 class File: def file_add():pass def file_update():pass def file_del():pass def file_fetch():pass - 數據封裝到對象中 class File: def __init__(self,name,age,email): self.name = name self.age = age self.email = email def file_add():pass def file_update():pass def file_del():pass def file_fetch():pass obj1 = File('oldboy',19,"asdf@live.com") obj2 = File('oldboy1',119,"asdf12@live.com") 應用: - django rest_framework中對request進行封裝 request = self.initialize_request(request, *args, **kwargs) - session/request封裝到了RequestContext對象中 ctx = RequestContext() - app/g封裝到了AppContext中 app_ctx = APPContext() 繼承:若是多個類中有相同的方法,爲了不重複編寫,能夠將其放在父類(基類)中。 python支持多繼承,繼承順序按__mro__的順序執行,新式類按廣度優先,舊式類類廣度優先,Python3都是新式類。先執行左邊,在執行右邊 class Base(object): def xxxx():pass class File(Base): def __init__(self,name,age,email): self.name = name self.age = age self.email = email def file_add():pass def file_update():pass def file_del():pass def file_fetch():pass class DB(Base): def db_add():pass def db_update():pass def db_del():pass def xxxx():pass def db_fetch():pass 應用: rest framework中的視圖類的繼承 多態(鴨子模型):天生支持多態,對於參數來講能夠傳入任何類型的對象,只要保證有想要的send方法便可。 class Msg(object): def send(): pass class WX(object): def send(): pass def func(arg): arg.send()
進階: __init__,初始化 __new__,建立對象 __call__,對象() __getattr__,對象.xx 且xx不存在 __getattribute__, 對象.xx xx爲任何屬性 __setattr__. 對象.xx = yy __delattr__, del 對象.xx __setitem__,對象['xx'] = yy __getitem__, 對象['xx'] __delitem__, del 對象['xx'] __mro__,查找成員順序 __str__, 對象返回值 __repr__, __iter__, 實現此方法,且返回一個迭代器,此對象可迭代 __dict__, 類的成員 __add__, 類 + xx __del__, 對象的生命週期結束以後
# -*- coding: utf-8 -*- """ @Datetime: 2018/10/14 @Author: Zhang Yafei """ class Obj(object): """限制對象添加屬性""" __slots__ = ['storage', 'stack_func', 'num', 'name'] def __init__(self): """ 建立對象的時候若new返回一個對象會執行此方法 類名()""" object.__setattr__(self, 'storage', {}) print('__init__') def __new__(cls, *args, **kwargs): """建立對象的時候會執行,返回一個對象 應用:單例/rest framework序列化 """ print('__new__') return super(Obj, cls).__new__(cls, *args, **kwargs) def __call__(self): """ 對象()會執行 應用:flask源碼請求入口,django請求入口(WSGIHandler.__call__) """ print('__call__') def __str__(self): """ 調用對象會執行此函數 :return: string_obj 返回一個字符串對象 """ return '__str__' def __repr__(self): """ 轉化爲機器能夠解釋的語言 case 1: repr(object)時會執行此函數 case 2: 交互模式下打印對象會執行此函數 :return: 用於對象信息的顯示 """ return '__repr__' def __getattr__(self, item): """當訪問不存在的屬性時會調用""" return '__getattr__' def __setattr__(self, key, value): """給對象設置屬性的時候會調用""" # self.key = value #容易出現循環調用 print('__setattr__') if key == 'num': object.__setattr__(self, key, value - 100) else: object.__setattr__(self, key, value) def __delattr__(self, item): """刪除屬性的時候會調用""" print('__delattr__') object.__delattr__(self, item) def __getattribute__(self, item): """訪問任何屬性的時候都會調用此方法""" print('__getattribute__') return super(Obj, self).__getattribute__(item) def __del__(self): """對象的生命週期執行結束以後執行""" print('__del__') def __setitem__(self, key, value): """obj[key] = value時會調用此方法""" print('__setitem__') self.storage[key] = value def __getitem__(self, key): """obj[key]會調用此方法""" return self.storage.get(key, None) def __delitem__(self, key): """del obj[key]調用""" print('__delitem__') del self.storage[key] def __add__(self, other): return '__add__' def __sub__(self, other): return '__sub__' def __mul__(self, other): return '__mul' def __floordiv__(self, other): return '__floatdiv__' def __mod__(self, other): return '__mod__' def __divmod__(self, other): return '__divmod__' def __pow__(self, power, modulo=None): return '__pow__' obj = Obj() # __new__ __init__ print(obj) # __str__ obj() # __call__ print(Obj.__mro__) # (<class '__main__.Obj'>, <class 'object'>) obj.name = '__dict__' print(obj.__dict__) # print(Obj.__dict__) print(repr(obj)) # __repr__ print(obj.world) # __getattribute__ __getattr__ obj.num = 200 # __setattr__ print(obj.num) # __getattribute__, 100 del obj.num # __delattr__ print(obj.storage) # {} obj['name'] = '張亞飛' # __setitem__ print(obj.storage) # __getattrbute__ __getattrbute__ {'name':'張亞飛'} print(obj['name']) # __getattrbute__ 張亞飛 del obj['name'] # __delitem__ print(obj['name']) # __getitem__, __getitem__, None print(obj + 7) print(obj - 1) print(obj * 1) print(obj // 1) print(obj % 3) print(obj.__divmod__(3)) print(obj.__pow__(2)) # __del__ """ 這裏咱們想讓__setattr__執行默認行爲,也就是將value賦值給name,和object對象中的一樣方法,作相似的操做。 可是這裏咱們不調用父類__setattr__的方法來實現,作這樣的嘗試獲得的結果就是,超過循環調用深度,報錯。由於 這裏在執行初始化方法self.world = world的時候,就會調用__setattr__方法,而這裏的__setattr__方法裏面的 self.name = value又會調用自身。因此形成了循環調用。因此使用該魔法方法的時候要特別注意。 """ class Friends(object): def __init__(self): self.name = 'zhang' self.age = 23 def func(self): print('__func__') class Xiaoming(Friends): score = 99 def __init__(self): super(Xiaoming, self).__init__() self.run = 200 if __name__ == '__main__': # 一些內置數據類型沒有__dict__屬性 ll = [] dic = {} num = 3 # print(ll.__dict__) # AttributeError: 'list' object has no attribute '__dict__' # print(dic.__dict__) # print(num.__dict__) # 類的__dict__和對象的__dict__的區別 f = Friends() # 建立實例 print(f.__dict__) f.message = 'hello world' f.func = lambda x:x print(f.__dict__) print(Friends.__dict__) # 繼承關係的__dict__ xiaoming = Xiaoming() print(xiaoming.__dict__) print(Xiaoming.__dict__) """ 1. 一些內置數據類型沒有__dict__ 2. 實例的__dict__存有與實例相關的實例變量和函數. 類的__dict__則是和實例共享的變量,函數(方法,類屬性).注意,類的__dict__並不包含其父類的屬性. 3. 對象也有本身的__dict__屬性, 存儲self.xxx 信息,父子類對象公用__dict__ """ class BAR(object): def __init__(self, cls): self.cls = cls class NEW_OBJ(object): def __new__(cls, *args, **kwargs): # return super(NEW_OBJ, cls).__new__(cls, *args, **kwargs) # <__main__.NEW_OBJ object at 0x000000D445061CF8> # return 123 # 123 # return BAR # <class '__main__.BAR'> # return BAR() # <__main__.BAR object at 0x000000AD77141C50> return BAR(cls) # <__main__.BAR object at 0x0000003BFFA31D68> obj = NEW_OBJ() print(obj) """new方法的返回值決定對象究竟是什麼"""
metaclass:指定類由那個type建立?(type泛指繼承type的全部類) 1. 類建立 class Foo(object):pass Foo = type('Foo',(object,),{}) 2. 如何指定類由自定義type建立? class MyType(type): pass class Foo(object,metaclass=MyType): # __metaclass__ = MyType # py2 pass Foo = MyType('Foo',(object,),{}) 3. 默認執行順序 class Foo(object,metaclass=MyType): pass obj = Foo() class MyType(type): def __init__(self,*args,**kwargs): print('111') super(MyType,self).__init__(*args,**kwargs) class Base(object, metaclass=MyType): pass class Foo(Base): pass 若是一類本身或基類中指定了metaclass,那麼該類就是由metaclass指定的type或mytype建立。 同: class MyType(type): def __init__(self,*args,**kwargs): print('111') super(MyType,self).__init__(*args,**kwargs) # class Base(object, metaclass=MyType): # pass Base = MyType('Base',(object,),{}) class Foo(Base): pass 同: class MyType(type): def __init__(self,*args,**kwargs): print('111') super(MyType,self).__init__(*args,**kwargs) # class Base(object, metaclass=MyType): # pass def with_metaclass(arg): Base = MyType('Base',(arg,),{}) return Base class Foo(with_metaclass(object)): pass
# -*- coding: utf-8 -*- """ @Datetime: 2018/12/30 @Author: Zhang Yafei """ """建立類的兩種方式""" class Obj(object): x = 123 def func(self): return 666 Obj1 = type('Obj1',(object,),{'x':123,'func':lambda self:666}) obj = Obj() obj1 = Obj1() print(obj.x, obj.func()) print(obj1.x,obj1.func()) """2.自定義type""" class MyType(type): pass class Obj(object, metaclass=MyType): x = 123 def func(self): return 666 Obj2 = MyType('Obj2',(object,),{'x':123,'func': lambda self:666}) # 注意:metaclass的做用是制定當前類由誰建立, 默認是由type建立 """3.metaclass""" class MyType(type): def __init__(self, *args, **kwargs): print('MyType的__init__') super(MyType, self).__init__(*args, **kwargs) def __call__(cls, *args, **kwargs): print('MyType的__call__') obj3 = cls.__new__(cls) cls.__init__(obj3) return obj class Obj3(object, metaclass=MyType): x = 123 def __init__(self): print('Obj3的__init__') def __new__(cls, *args, **kwargs): print('Obj3的__new__') return object.__new__(cls) def func(self): return 666 # print(Obj3) # MyType的__init__ <class '__main__.Obj3'> obj3 = Obj3() # MyType的__init__ MyType的__call__ Obj3的__new__ Obj3的__init__ # obj3 = Obj3() # Obj3是類 # Obj3是MyType的一個對象 """ 1. 建立類時,先執行metaclass(默認爲type)的__init__方法 2. 類在實例化時, 執行metaclass(默認爲type)的__call__方法,__call__方法的返回值就是實例化的對象 __call__內部調用: - 類.__new__方法:建立對象 _ 類.__init__方法:對象的初始化 """ class MyType(type): def __init__(self, *args, **kwargs): print('mytype__init__') super(MyType, self).__init__(*args,**kwargs) # class Base(object, metaclass=MyType): # pass # class Obj4(Base): # pass def with_metaclass(arg): Base = MyType('Base',(arg,),{}) # class Base(arg, metaclass=MyType): # pass return Base class Obj4(with_metaclass(object)): pass
方式一:普通方式前端
In [19]: class Love(object): ...: def love(self): ...: print('love') ...: In [20]: f = Love() In [21]: f.love() love
方式二:特殊方式python
def love(self): print('love')
f = type('Love',(object,),{'func':love})
obj = f() obj.func() out:love
In [22]: f
Out[22]: <__main__.Love at 0xdb8e81c048>django
In [23]: Love
Out[23]: __main__.Loveflask
"""微信
類的私有變量和私有方法session
在Python中能夠經過在屬性變量名前加上雙下劃線定義屬性爲私有屬性app
特殊變量命名ide
一、 _xx 以單下劃線開頭的表示的是protected類型的變量。即保護類型只能容許其自己與子類進行訪問。若內部變量標示,如: 當使用「from M import」時,不會將以一個下劃線開頭的對象引入 。 二、 __xx 雙下劃線的表示的是私有類型的變量。只能容許這個類自己進行訪問了,連子類也不能夠用於命名一個類屬性(類變量),調用時名字被改變(在類FooBar內部,__boo變成_FooBar__boo,如self._FooBar__boo) 三、 __xx__定義的是特列方法。用戶控制的命名空間內的變量或是屬性,如init , __import__或是file 。只有當文檔有說明時使用,不要本身定義這類變量。 (就是說這些是python內部定義的變量名)
在這裏強調說一下私有變量,python默認的成員函數和成員變量都是公開的,沒有像其餘相似語言的public,private等關鍵字修飾.可是能夠在變量前面加上兩個下劃線"_",這樣的話函數或變量就變成私有的.這是python的私有變量軋壓(這個翻譯好拗口),英文是(private name mangling.) **狀況就是當變量被標記爲私有後,在變量的前端插入類名,再類名前添加一個下劃線"_",即造成了_ClassName__變量名.**函數
# -*- coding: utf-8 -*- """ @Datetime: 2018/12/30 @Author: Zhang Yafei """ class Obj(object): def __init__(self, name, age): self.name = name self.__age = age def get_age(self): # print(self.__age) return self.__age obj = Obj('張亞飛',23) print(obj.name) # 張亞飛 # print(obj.__age) # AttributeError: 'Obj' object has no attribute '__age' print(obj.get_age()) # 23 print(obj._Obj__age) # 23 """私有成員只能類中訪問,外部不能直接訪問,但若要訪問,能夠強制訪:_類名__var, 或者在內部提供一個接口供外部訪問""" class Obj2(Obj): def print_age(self): print(self.__age) obj2 = Obj2('張亞飛',23) obj2.print_age() # AttributeError: 'Obj2' object has no attribute '_Obj2__age' """私有字段只能在當前類中訪問,其子類也不能訪問"""
__dict__ : 類的屬性(包含一個字典,由類的數據屬性組成) __doc__ :類的文檔字符串 __module__: 類定義所在的模塊(類的全名是'__main__.className',若是類位於一個導入模塊mymod中,那麼className.__module__ 等於 mymod) __bases__ : 類的全部父類構成元素(包含了一個由全部父類組成的元組)
class pub(): _name = 'protected類型的變量' __info = '私有類型的變量' def _func(self): print("這是一個protected類型的方法") def __func2(self): print('這是一個私有類型的方法') def get(self): return(self.__info) a = pub() print(a._name) a._func() # print(a.info) # 執行結果: # protected類型的變量 # 這是一個protected類型的方法 # protected類型的變量和方法 在類的實例中能夠獲取和調用 # # print(a.__info) # # a.__func2() # 執行結果: # File "D:/Python/class/class3.py", line 46, in <module> # print(a.__info) # # AttributeError: pub instance has no attribute '__info' # a.__func2() # AttributeError: pub instance has no attribute '__func2' # 私有類型的變量和方法 在類的實例中獲取和調用不到 # 獲取私有類型的變量 print(a.get()) # 執行結果:私有類型的變量 # 若是想要在實例中獲取到類的私有類形變量能夠經過在類中聲明普通方法,返回私有類形變量的方式獲取 print(dir(a)) # 執行結果:['__doc__', '__module__', '_func', '_name', '_pub__func2', '_pub__info', 'get'] print(a.__dict__) # 執行結果:{} print(a.__doc__) # 執行結果: None print(a.__module__) # 執行結果:__main__ print(a.__bases__) # 執行結果: # print(a.__bases__) # AttributeError: pub instance has no attribute '__bases__'
Java:fetch
Interface IMessage: def func1(self): pass def func2(self): pass class Msg(IMessage): def func1(self): print('func1') def func2(self): print('func1')
class abstract IMessage: def abstract func1(self): pass def abstract func2(self): pass def func3(self): print('asdfasdf') class Msg(IMessage): def func1(self): print('func1') def func2(self): print('func1')
Python
import abc class Base(metaclass=abc.ABCMeta): @abc.abstractmethod def send(self):pass def func(self): print(123) class Foo(Base): def send(self): print('發送信息') obj = Foo() obj.send() obj.func()
做用:的用於告知其餘人之後繼承時,須要實現那個方法
class BaseAuthentication(object): """ All authentication classes should extend BaseAuthentication. """ def authenticate(self, request): """ Authenticate the request and return a two-tuple of (user, token). """ raise NotImplementedError(".authenticate() must be overridden.") def authenticate_header(self, request): """ Return a string to be used as the value of the `WWW-Authenticate` header in a `401 Unauthenticated` response, or `None` if the authentication scheme should return `403 Permission Denied` responses. """ pass
class BaseMessage(object): def send(self): raise NotImplementedError('必須實現send方法') class Msg(BaseMessage): def send(self): print('發送短信') class Wechat(BaseMessage): def send(self): print('發送微信') class Email(BaseMessage): def send(self): print('發送郵件') class DingDing(BaseMessage): def send(self): print('發送釘釘提醒')
-*- coding: utf-8 -*- """ @Datetime: 2018/12/29 @Author: Zhang Yafei """ """方式一""" # my_singleton.py # # class Singleton(object): # pass # # singleton = Singleton() # # from mysingleton import singleton """方式二:使用裝飾器""" # def Singleton(cls): # _instance = {} # # def _singleton(*args, **kargs): # if cls not in _instance: # _instance[cls] = cls(*args, **kargs) # return _instance[cls] # # return _singleton # # # @Singleton # class A(object): # a = 1 # # def __init__(self, x=0): # self.x = x # # # a1 = A(2) # a2 = A(3) """方式三:使用類""" # import threading # import time # # # class Singleton(object): # # def __init__(self): # # time.sleep(1) # pass # @classmethod # def instance(cls, *args, **kwargs): # if not hasattr(Singleton, "_instance"): # Singleton._instance = Singleton(*args, **kwargs) # return Singleton._instance # # # def task(arg): # obj = Singleton.instance() # print(obj) # # # for i in range(10): # t = threading.Thread(target=task,args=[i,]) # t.start() """解決方法:加鎖""" # import time # import threading # # # class Singleton(object): # _instance_lock = threading.Lock() # # def __init__(self): # time.sleep(1) # # @classmethod # def instance(cls, *args, **kwargs): # if not hasattr(Singleton, "_instance"): # with Singleton._instance_lock: # if not hasattr(Singleton, "_instance"): # Singleton._instance = Singleton(*args, **kwargs) # return Singleton._instance # # # # # def task(arg): # obj = Singleton.instance() # print(obj) # # for i in range(10): # t = threading.Thread(target=task,args=[i,]) # t.start() # time.sleep(20) # obj = Singleton.instance() # print(obj) """方法四:基於__new__方法""" # # import threading # # class Singleton(object): # _instance_lock = threading.Lock() # # def __init__(self): # pass # # def __new__(cls, *args, **kwargs): # if not hasattr(Singleton, "_instance"): # with Singleton._instance_lock: # if not hasattr(Singleton, "_instance"): # Singleton._instance = object.__new__(cls) # return Singleton._instance # # # obj1 = Singleton() # obj2 = Singleton() # print(obj1,obj2) # # # def task(arg): # obj = Singleton() # print(obj) # # # for i in range(10): # t = threading.Thread(target=task,args=[i,]) # t.start() # """方法五:元類實現單例模式""" import threading class SingletonType(type): _instance_lock = threading.Lock() def __call__(cls, *args, **kwargs): if not hasattr(cls, "_instance"): with SingletonType._instance_lock: if not hasattr(cls, "_instance"): cls._instance = super(SingletonType,cls).__call__(*args, **kwargs) return cls._instance class Foo(metaclass=SingletonType): def __init__(self,name): self.name = name obj1 = Foo('name') obj2 = Foo('name') print(obj1,obj2)
class Obj4(): def __enter__(self): print('__enter__') def __exit__(self, exc_type, exc_val, exc_tb): print('__exit__') with Obj4(): print('執行中') # __enter__ # 執行中 # __exit__ """with 對象默認執行__enter__方法,執行結束執行__exit__方法"""
class Obj(object): def __iter__(self): # return iter([1,2,3]) yield 1 yield 2 yield 3 obj = Obj() for item in obj: print(item)