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)
# 自己开发时, 什么时候使用?
某一些类必须统一实现一些方法时.