一、方法與函數的區別?mysql
''' class Foo(object): def __init__(self): self.name = 'alex' def func(self): print(self.name) from types import FunctionType,MethodType obj = Foo() print(isinstance(obj.func,FunctionType)) # False print(isinstance(obj.func,MethodType)) # True print(isinstance(Foo.func,FunctionType)) # True print(isinstance(Foo.func,MethodType)) # False 注意: 方法,無需傳入self參數;函數,必須手動傳入self參數 '''
二、models對象相關查詢sql
''' 例:model.UserInfo爲models類 ''' #(1)獲取models類所在app名:model.UserInfo._meta.app_label #(2)獲取models類的類名小寫:model.UserInfo._meta.model_name #(3)獲取models類中的字段內容:model.UserInfo._meta.get_field('username') #(4)獲models類中字段的verbose_name:model.UserInfo._meta.get_field('username').verbose_name
三、用type建立類的實現django
'''type建立TestModelForm類,參數分別爲類名,繼承類,類中屬性'''
meta = type('Meta',(object,),{'model':self.model_class,'fields':'__all__'}) TestModelForm = type('TestModelForm',(ModelForm,),{'Meta':meta}) #等價於 class TestModelForm(ModelForm): class Meta: model = self.model_class fields = "__all__"
四、反向生成url後端
#示例以下:namespace爲名稱空間,name爲url別名
reverse("namespace:name")
五、instance與type區別微信
有這樣一個錯誤說法:isinstance用於判斷,對象是不是指定類的實例,具體狀況見下實例:session
class Foo(object): pass class Bar(Foo): pass obj = Bar() print(isinstance(obj,Foo)) #True print(isinstance(obj,Bar)) #True
因此結論是:isinstance用於判斷對象是不是指定類或其派生類的實例,若是須要排除派生類的狀況,咱們就不能用instance進行實例判斷,爲了實現這種,就須要使用type進行判斷了。示例以下:app
print(type(obj) == Bar) #True print(type(obj) == Foo) #False
六、面向對象中的反射相關函數
在django中,配置文件中中間件的配置方式以下,其實配置的就是不一樣中間模塊的路徑。咱們可能好奇,這樣的字符串形式的配置,內部是如何讀取到相應模塊中的內容的呢?sqlserver
經過源碼咱們發現,其主要也是經過反射實現的,見以下實例:fetch
MIDDLEWARE = [ 'django.middleware.security.SecurityMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.common.CommonMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', ]
有這樣一個setting.py文件,配置了某類的路徑:
DB_PATH = "db.sqlserver.SqlServerHelper"
得到SqlServerHelper類,並執行其中相關方法:
from settings import DB_PATH def func(): # DB_PATH = "db.mysql.MySQLHelper" module_path,cls_name = DB_PATH.rsplit('.',maxsplit=1) # 以字符串的形式導入模塊 import importlib module_obj = importlib.import_module(module_path) # 去模塊中導入類 cls = getattr(module_obj,cls_name) # 類實例化 obj = cls() obj.fetchone() if __name__ == '__main__': func()
還有這樣一個實例:根據方法名,去實例對象中得到該方法。
class Foo(object): def func(self): pass obj = Foo() name = "func" fc = getattr(obj,name) fc()
七、面向對象封裝數據相關
有這樣一個應用,咱們須要將models對象中相應的部分字段信息傳給後端,咱們至關的數據類型多是:[{},{},{}.....],其中字典中爲每一個字段的相應信息。這樣作沒有問題,可是當咱們須要的數據不但不含字段的直接信息,還要包含根據字段得到其餘間接數據。這樣的話,上述方式就比較難作到。此時咱們就能夠藉助面向對象的封裝特性,將數據封裝到類中,間接數據的得到能夠在類中的方法實現,最終只需將實例化的類對象發給後端就能夠。具體實例以下:
#封裝數據的類 class FilterOption(object): def __init__(self,field_name,multi=False,condition=None,is_choice=False): """ :param field_name: 字段 :param multi: 是否多選 :param condition: 顯示數據的篩選條件 :param is_choice: 是不是choice """ self.field_name = field_name self.multi = multi self.is_choice = is_choice self.condition = condition def get_queryset(self,_field): if self.condition: return _field.rel.to.objects.filter(**self.condition) return _field.rel.to.objects.all() def get_choices(self,_field): return _field.choices
#發送的數據形式: comb_filter = [ FilterOption('gender',is_choice=True), FilterOption('depart',condition={'id__gt':3}), FilterOption('roles',True), ]
如上,經過循環列表,經過實例對象就能夠得到封裝到類中的全部數據。
八、兩個對象相加(__add__)
class Foo(object): def __init__(self,age): self.age = age def __add__(self, other): return self.age + other.age # return Foo(self.age + other.age) obj1 = Foo(19) obj2 = Foo(18) obj3 = obj1 + obj2 print(obj3)
九、類中的方法約束
有這樣的狀況,咱們須要規定多個類中,每個類中都要一個相同的方法。如何實現這樣的約束呢?有兩種方式,以下。說明:以下實例要求全部寫的類中必需要有send方法,若是沒有該方法時,實例化對象調用該方法時會報錯。
方式一:抽象類、抽象方法實現
以下實例,咱們定義了一個基類BaseMessage,繼承抽象類,經過使用@abstractmethod裝飾方法send,send方法成爲抽象方法,全部繼承BaseMessage基類的類中必需要有send方法,不然執行此類時會報錯。
from abc import ABCMeta from abc import abstractmethod class BaseMessage(metaclass=ABCMeta): @abstractmethod def send(self,subject,body,to,name): pass ######################################3 class WeChat(BaseMessage): def __init__(self): pass print("xxx") def send(self,subject,body,to,name): print('微信發送成功')
方法二:自定義基類方式實現
以下,自定義基類BaseMessage,在基類中定義一個send方法,方法內拋出沒有該方法的異常NotImplementedError。WeChat類繼承基類,實例化後調用send方法時,若是此類中沒有定義該方法,則會去基類中找。從而會拋出異常。
class BaseMessage(object): def send(self, subject, body, to, name): raise NotImplementedError('未實現send方法') class WeChat(BaseMessage): def __init__(self): pass print("xxx") def send(self,subject,body,to,name): print('微信發送成功')
總結,以上兩種方法均在基類中進行特定方法限制,全部繼承此基類的類中必需要有此方法。不一樣的是,方法一中要求全部繼承基類的類中必須有抽象方法規定的方法,不然類在實例化的時候就會報錯。可是方法二中不一樣的是,若自定義的類中沒有實現send方法時候,在類的實例化過程當中不會報錯,實例對象能夠正常調用類中有的方法和屬性,只有實例對象在調用send方法時候會報錯。