面向对象
面向对象的三大特性:封装、继承、多态
- 封装:
方法封装到类中
class File: def file_add():pass def file_update():pass def file_del():pass def file_fetch():pas
将数据封装到对象中
class File: def __init__(self,name,age,email): self.name = name self.age = age self.email = email def file_add():pass def file_update():pass def file_del():pass def file_fetch():pass obj1 = File('oldboy',19,"asdf@live.com") obj2 = File('oldboy1',119,"asdf12@live.com")
应用:
-
- -Flask上下文管理中把session/request封装到了RequestContex对象中
- -app/g封装到了AppContext中
- -restframework的Request(对数据的封装)
- 继承
如果多个类中有相同的方法,为了避免重复编写可以将其放在父类(基类)中
class Base(object): def xxxx():pass class File(Base): def __init__(self,name,age,email): self.name = name self.age = age self.email = email def file_add():pass def file_update():pass def file_del():pass def file_fetch():pass class DB(Base): def db_add():pass def db_update():pass def db_del():pass def db_fetch():pass
应用:
- 我印象最深的就是restframework的多继承
- 多态
多态(鸭子模型):天生支持多态,对于参数来说可以传入任何类型的对象,只要保证有想要的send方法即可。
class Msg(object): def send(): pass class WX(object): def send(): pass def func(arg): arg.send()
进阶
类里面常用的双下划线的方法
__init__
- 初始化操作
__new__
- 创建对象, 在实例化对象的时候会先触发__new__方法,创建对象,再触发__init__进行实例化
- 应用
- 单例模式
- rest framework 序列化组件,判断many=True或者False触发创建不同的返回不同类的对象
__call__
- 对象()的时候触发__call__类的方法
- 应用:
- flask源码请求入口.一旦请求进来会触发实例化Flask的对象()
- Django源码入口
- __getattr__
- 当对象.属性的时候会触发该方法
- 应用:
- Flask上下文管理中,LocalStack取值getattr()触发Local的__getattr__方法将想要的数据返回
- restframework中获取配置文件信息的时候也是通过触发__getattr__方法获取
- __setattr__
- obj.xx=1 给对象的属性赋值的时候触发
- 应用:
- Flask上下文管理中在实例化Local对象的时候在__init__方法里执行了object.__setattr__(self, '__storage__', {})设置了一个空的字典
- 还获取了object.__setattr__(self, '__ident_func__', get_ident)线程或者协程的唯一标识
- __delattr__
- __getitem__
- 对象['xx'] 触发
- 应用
- 在取session['a1']的值的时候会触发该方法
- 所有对象['x1']都会触发,需要自己定义才能够运行
- __setitem__
- 在对象['xxx']=1 触发
- __delitem__
- 删除 del 对象['触发']
- __mro__
- 查找继承顺序
- 应用
- 在wtforms源码中FormMeta在__call__方法中去找Meta类的时候使用了__mro__查看该类所有的继承顺序,然后用__dict__判断Meta是否在里面,在的话就放到一个列表中
- __str__
- 用于显示对象信息
- 应用
- 在Model中定义返回的数据格式可以在admin直观的看到
- __repr__
- __iter__
- 让对象可以迭代
- 应用
- Wtforms和Django的form组件都是用__iter__返回了一个迭代器,实例化对象后可以循环的渲染标签
- __dict__
- 应用
- 对象将__init__字段以字典的形式传回,可以用于封装数据
- 应用
高级metaclass
- 创建类时,先执行type的__init__。
- 类的实例化时,执行type的__call__,__call__方法的的返回值就是实例化的对象。
type的__call__方法内部调用:
- 类.__new__,创建对象
- 类.__init__,对象的初始化
类创建的两种方式:
#常用方式 class Foo(object): a1 = 123 def func(self): return 666 #type方式 Foo = type("Foo",(object,),{'a1':123,'func':lambda self:666}
如何指定类由自定义type创建
class MyType(type): pass class Foo(object,metaclass=MyType): # __metaclass__ = MyType # py2 pass Foo = MyType('Foo',(object,),{})
默认执行顺序
class Foo(object,metaclass=MyType): pass obj = Foo() class MyType(type): def __init__(self,*args,**kwargs): print('111') super(MyType,self).__init__(*args,**kwargs) class Base(object, metaclass=MyType): pass class Foo(Base): pass 如果类自己或基类中指定了metaclass,那么该类就是由metaclass指定的type或mytype创建。 #同: class MyType(type): def __init__(self,*args,**kwargs): print('111') super(MyType,self).__init__(*args,**kwargs) # class Base(object, metaclass=MyType): # pass Base = MyType('Base',(object,),{}) class Foo(Base): pass #同: class MyType(type): def __init__(self,*args,**kwargs): print('111') super(MyType,self).__init__(*args,**kwargs) # class Base(object, metaclass=MyType): # pass def with_metaclass(arg): Base = MyType('Base',(arg,),{}) return Base class Foo(with_metaclass(object)): pass
I can feel you forgetting me。。 有一种默契叫做我不理你,你就不理我