python面向对象知识补充

一 偏函数

# 帮助开发者自动传递参数, 相当于对函数做封装, 自动给函数传参
# 应用场景: LocalStack

import functools

def index(a1,a2):
    return a1 + a2

# 方式一:原来的调用方式
# ret = index(1,23)
# print(ret)

# 方式二:偏函数,帮助开发者自动传递参数
new_func = functools.partial(index,666)
ret = new_func(1)
print(ret)

二 super和执行类方法的区别

super是根据mro的继承顺序来执行

查询一个类的mro继承顺序  ---->     cls.__mro__

class Base(object):

    def func(self):
        print('Base.func')

class Foo(Base):

    def func(self):
        # 方式一:根据mro的顺序执行方法,     主动执行下一个mro类的方法
        # super(Foo,self).func()
        # 方式二:主动执行Base类的方法
        # Base.func(self)

        print('Foo.func')

# print(Foo.__mro__)        # 类的继承顺序
obj = Foo()
obj.func()

三 面向对象中特殊的方法

setattr/getattr的注意事项:
# 要使用类的属性时必须先设置其值, 不能再没设置前使用

    class Foo(object):
    def __init__(self):
        # self.storage = {}
        object.__setattr__(self,'storage',{})    # 1 先设置

    def __setattr__(self, key, value):
        print(key,value,self.storage)    # 2 再使用 (使用self.storage之前必须先设置)
__init__    # 实例化对象时, 初始化对象
__new__        # 1 实例化时,用来创建对象 (init之前)
            # 2 返回值决定对象到底是什么
            # 3 应用: 单例模式,drf里序列化many=True/False时用到
__str__        # print的时候才调用        
__repr__



__call__    # 对象()

__getattr__    # flask Local对象用到        对象.xx
__setattr__
__delattr__

__setitem__    # 对象['xx'], 就会有这三个方法, 
__getitem__        
__delitem__

__dict__    # api封装返回数据时, BaseResponse
__mro__        # 继承顺序    print(Foo.__mro__)
__slots__    # 允许对象能有什么字段暴露在外面,     flask Local对象用到
__iter__    # 将对象变成可迭代对象

四 对象可以被for循环  (变成可迭代对象)

# 类中实现了__iter__方法即可
def
__iter__(self): return iter([11,22,33]) # 必须返回迭代器, 生成器是一种特殊的迭代器

五 metaclass 指定当前类由谁来创建

默认的metaclass是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 默认type的执行顺序

a. 创建类时先执行type的__init__方法
b. 当一个类实例化时先执行type的__call__方法, __call__的返回值就是实例化的对象
    - 先执行类的__new__创建对象
    - 再执行类的__init__初始化

注意: 如果类自己或父类中指定了metaclass,那么该类就是由指定的metaclass创建
应用: wtforms

六 查看类的所有成员

print(dir(cls))

七 谈谈你对面向对象的认识?

基础

谈面向对象就要从他的三大特性开始说起,如:封装、继承、多态。

1 封装
    a 将方法封装到类中
    b 将属性(数据)封装到对象中
    应用: 
        - session/request封装到RequestContext中, 
        - current_app/g封装到AppContext中
    
2 继承
    如果多个类中有相同的方法/属性,为了避免重复编写,可以将其放在父类(基类)中。
    
    应用:    
        rest framework中的视图类的继承

3 多态(鸭子模型)
    天生支持多态,对于参数来说可以传入任何类型的对象,只要保证有想要的send方法即可。
    
        class Msg(object):
            def send():
                pass 
                
        class WX(object):
            def send():
                pass 
        
    
        def message_send(arg):    # 多态
            arg.send()    

进阶

双下方法  --> 参照三

高级

metaclass --> 参照五

八 面向对象的私有属性

class Foo(object):
    def __init__(self,name,age):
        self.name = name
        self.__age = age    # 私有属性

    def func(self):
        print(self.__age)

obj = Foo('oldboy',50)
print(obj.name)
print(obj._Foo__age)    # 硬取

# 注意: 私有字段子类中也不能访问

九 with一个对象会调用什么方法

with obj:
    # 1 进入时, 会自动触发__enter__方法;
    print("在其中")
    # 2 结束时, 触发__exit__方法

十 面向对象的约束

接口: (约束)       约束子类中必须包含父类规定的方法
抽象类: (约束+继承)    约束子类中必须包含某些方法

# python中无接口这个概念

python中的抽象类实现:

方式一: 类继承+异常    
    class IMessage(object):

        def func1(self):
            raise NotImplementedError("没有实现func方法")


    class Img(IMessage):

        def func1(self):  # 如果没有实现这个方法则在此类的对象调用此方法时报错..
            print("111")


    obj = Img()
    obj.func1()    # 如果没有实现抽象类的抽象方法, 会报错
            
方式二: abc模块
    import abc


    class Payment(metaclass=abc.ABCMeta):

        @abc.abstractmethod
        def pay(self, money):
            pass


    class Wx(Payment):

        def pay(self, money):   # 如果没有实现此方法, 会报错
            print(money)


    obj = Wx()
    obj.pay(77)

# 自己开发时, 什么时候使用?
某一些类必须统一实现一些方法时.

posted @ 2019-04-28 11:06  孙昌恒  阅读(95)  评论(0编辑  收藏  举报