python之路_面向对象相关知识点

1、方法与函数的区别?

'''
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参数
'''

2、models对象相关查询

'''
例: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

3、用type创建类的实现

'''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__"

4、反向生成url

#示例如下:namespace为名称空间,name为url别名

reverse("namespace:name")

 5、instance与type区别

  有这样一个错误说法:isinstance用于判断,对象是否是指定类的实例,具体情况见下实例:

class Foo(object):
    pass

class Bar(Foo):
    pass

obj = Bar()

print(isinstance(obj,Foo))      #True
print(isinstance(obj,Bar))       #True

  所以结论是:isinstance用于判断对象是否是指定类或其派生类的实例,如果需要排除派生类的情况,我们就不能用instance进行实例判断,为了实现这种,就需要使用type进行判断了。示例如下:

print(type(obj) == Bar)     #True

print(type(obj) == Foo)     #False

6、面向对象中的反射相关

  在django中,配置文件中中间件的配置方式如下,其实配置的就是不同中间模块的路径。我们可能好奇,这样的字符串形式的配置,内部是如何读取到相应模块中的内容的呢?

通过源码我们发现,其主要也是通过反射实现的,见如下实例:

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

7、面向对象封装数据相关

  有这样一个应用,我们需要将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), ]

  如上,通过循环列表,通过实例对象就可以获得封装到类中的所有数据。

8、两个对象相加(__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)

 9、类中的方法约束

  有这样的情况,我们需要规定多个类中,每一个类中都要一个相同的方法。如何实现这样的约束呢?有两种方式,如下。说明:如下实例要求所有写的类中必须要有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方法时候会报错。

posted @ 2018-03-05 22:30  骑猪走秀  阅读(213)  评论(0编辑  收藏  举报