面向对象

面向对象的三大特性:封装、继承、多态

  • 封装:

             方法封装到类中

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

 

posted @ 2019-03-05 22:24  离人怎挽_wdj  阅读(149)  评论(0编辑  收藏  举报