python之路_面向對象相關知識點

一、方法與函數的區別?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方法時候會報錯。

相關文章
相關標籤/搜索