Python 面向对象


对面向对象的理解?

基础:三大特性

基础:谈面向对象就要从他的三大特性开始说起,如:封装、继承、多态。
    封装:
        - 方法封装到来类中:某一类功能相似的方法
            class File:
                def file_add():pass


                def file_update():pass


                def file_del():pass


                def file_fetch():pass

        - 数据封装到对象中
            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")
        
        应用:
            - django rest_framework中对request进行封装       request = self.initialize_request(request, *args, **kwargs)
            - session/request封装到了RequestContext对象中     ctx = RequestContext()
            - app/g封装到了AppContext中              app_ctx = APPContext()
    
            
    继承:如果多个类中有相同的方法,为了避免重复编写,可以将其放在父类(基类)中。
        python支持多继承,继承顺序按__mro__的顺序执行,新式类按广度优先,旧式类类广度优先,Python3都是新式类。先执行左边,在执行右边
        
        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 xxxx():pass
            
            def db_fetch():pass

        应用:    
            rest framework中的视图类的继承
            

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

进阶:特殊方法

进阶:
    __init__,初始化
    __new__,创建对象
    __call__,对象()
    __getattr__,对象.xx 且xx不存在
    __getattribute__, 对象.xx  xx为任何属性
    __setattr__. 对象.xx = yy
    __delattr__, del 对象.xx
    __setitem__,对象['xx'] = yy
    __getitem__, 对象['xx']
    __delitem__, del 对象['xx']
    
    __mro__,查找成员顺序
    __str__, 对象返回值
    __repr__,
    __iter__, 实现此方法,且返回一个迭代器,此对象可迭代
    __dict__, 类的成员
    __add__, 类 + xx
    __del__, 对象的生命周期结束之后  
# -*- coding: utf-8 -*-
"""
@Datetime: 2018/10/14
@Author: Zhang Yafei
"""


class Obj(object):
    """限制对象添加属性"""
    __slots__ = ['storage', 'stack_func', 'num', 'name']

    def __init__(self):
        """ 创建对象的时候若new返回一个对象会执行此方法 类名()"""
        object.__setattr__(self, 'storage', {})
        print('__init__')

    def __new__(cls, *args, **kwargs):
        """创建对象的时候会执行,返回一个对象
        应用:单例/rest framework序列化
        """
        print('__new__')
        return super(Obj, cls).__new__(cls, *args, **kwargs)

    def __call__(self):
        """ 对象()会执行 
        应用:flask源码请求入口,django请求入口(WSGIHandler.__call__)
        """
        print('__call__')

    def __str__(self):
        """
        调用对象会执行此函数
        :return: string_obj 返回一个字符串对象
        """
        return '__str__'

    def __repr__(self):
        """
        转化为机器可以解释的语言
        case 1: repr(object)时会执行此函数
        case 2: 交互模式下打印对象会执行此函数
        :return: 用于对象信息的显示
        """
        return '__repr__'

    def __getattr__(self, item):
        """当访问不存在的属性时会调用"""
        return '__getattr__'

    def __setattr__(self, key, value):
        """给对象设置属性的时候会调用"""
        # self.key = value #容易出现循环调用
        print('__setattr__')
        if key == 'num':
            object.__setattr__(self, key, value - 100)
        else:
            object.__setattr__(self, key, value)

    def __delattr__(self, item):
        """删除属性的时候会调用"""
        print('__delattr__')
        object.__delattr__(self, item)

    def __getattribute__(self, item):
        """访问任何属性的时候都会调用此方法"""
        print('__getattribute__')
        return super(Obj, self).__getattribute__(item)

    def __del__(self):
        """对象的生命周期执行结束之后执行"""
        print('__del__')

    def __setitem__(self, key, value):
        """obj[key] = value时会调用此方法"""
        print('__setitem__')
        self.storage[key] = value

    def __getitem__(self, key):
        """obj[key]会调用此方法"""
        return self.storage.get(key, None)

    def __delitem__(self, key):
        """del obj[key]调用"""
        print('__delitem__')
        del self.storage[key]

    def __add__(self, other):
        return '__add__'

    def __sub__(self, other):
        return '__sub__'

    def __mul__(self, other):
        return '__mul'

    def __floordiv__(self, other):
        return '__floatdiv__'

    def __mod__(self, other):
        return '__mod__'

    def __divmod__(self, other):
        return '__divmod__'

    def __pow__(self, power, modulo=None):
        return '__pow__'


obj = Obj()  # __new__   __init__
print(obj)  # __str__
obj()  # __call__
print(Obj.__mro__)  # (, )
obj.name = '__dict__'
print(obj.__dict__)
# print(Obj.__dict__)
print(repr(obj))  # __repr__
print(obj.world)  # __getattribute__    __getattr__
obj.num = 200  # __setattr__
print(obj.num)  # __getattribute__, 100
del obj.num  # __delattr__
print(obj.storage)  # {}
obj['name'] = '张亚飞'  # __setitem__
print(obj.storage)  # __getattrbute__  __getattrbute__   {'name':'张亚飞'}
print(obj['name'])  # __getattrbute__  张亚飞
del obj['name']  # __delitem__
print(obj['name'])  # __getitem__,  __getitem__, None
print(obj + 7)
print(obj - 1)
print(obj * 1)
print(obj // 1)
print(obj % 3)
print(obj.__divmod__(3))
print(obj.__pow__(2))
#  __del__

"""
这里我们想让__setattr__执行默认行为,也就是将value赋值给name,和object对象中的同样方法,做类似的操作。
但是这里我们不调用父类__setattr__的方法来实现,做这样的尝试得到的结果就是,超过循环调用深度,报错。因为
这里在执行初始化方法self.world = world的时候,就会调用__setattr__方法,而这里的__setattr__方法里面的
self.name = value又会调用自身。所以造成了循环调用。所以使用该魔法方法的时候要特别注意。
"""


class Friends(object):
    def __init__(self):
        self.name = 'zhang'
        self.age = 23

    def func(self):
        print('__func__')


class Xiaoming(Friends):
    score = 99

    def __init__(self):
        super(Xiaoming, self).__init__()
        self.run = 200


if __name__ == '__main__':
    # 一些内置数据类型没有__dict__属性
    ll = []
    dic = {}
    num = 3
    # print(ll.__dict__)     # AttributeError: 'list' object has no attribute '__dict__'
    # print(dic.__dict__)
    # print(num.__dict__)

    # 类的__dict__和对象的__dict__的区别
    f = Friends()  # 创建实例
    print(f.__dict__)
    f.message = 'hello world'
    f.func = lambda x:x
    print(f.__dict__)
    print(Friends.__dict__)

    # 继承关系的__dict__
    xiaoming = Xiaoming()
    print(xiaoming.__dict__)
    print(Xiaoming.__dict__)
"""
1. 一些内置数据类型没有__dict__
2. 实例的__dict__存有与实例相关的实例变量和函数.
类的__dict__则是和实例共享的变量,函数(方法,类属性).注意,类的__dict__并不包含其父类的属性.
3. 对象也有自己的__dict__属性, 存储self.xxx 信息,父子类对象公用__dict__
"""


class BAR(object):
    def __init__(self, cls):
        self.cls = cls


class NEW_OBJ(object):

    def __new__(cls, *args, **kwargs):
        # return super(NEW_OBJ, cls).__new__(cls, *args, **kwargs)   # <__main__.NEW_OBJ object at 0x000000D445061CF8>
        # return 123     # 123
        # return BAR          # 
        # return BAR()        # <__main__.BAR object at 0x000000AD77141C50>
        return BAR(cls)       # <__main__.BAR object at 0x0000003BFFA31D68>


obj = NEW_OBJ()
print(obj)
"""new方法的返回值决定对象到底是什么"""
进阶:python面向对象的魔法方法

高级:metaclass

metaclass:指定类由那个type创建?(type泛指继承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. 默认执行顺序
    
        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
# -*- coding: utf-8 -*-

"""
@Datetime: 2018/12/30
@Author: Zhang Yafei
"""
"""创建类的两种方式"""


class Obj(object):
    x = 123

    def func(self):
        return 666


Obj1 = type('Obj1',(object,),{'x':123,'func':lambda self:666})

obj = Obj()
obj1 = Obj1()

print(obj.x, obj.func())
print(obj1.x,obj1.func())

"""2.自定义type"""


class MyType(type):
    pass


class Obj(object, metaclass=MyType):
    x = 123

    def func(self):
        return 666

Obj2 = MyType('Obj2',(object,),{'x':123,'func': lambda self:666})

# 注意:metaclass的作用是制定当前类由谁创建, 默认是由type创建

"""3.metaclass"""


class MyType(type):
    def __init__(self, *args, **kwargs):
        print('MyType的__init__')
        super(MyType, self).__init__(*args, **kwargs)

    def __call__(cls, *args, **kwargs):
        print('MyType的__call__')
        obj3 = cls.__new__(cls)
        cls.__init__(obj3)
        return obj


class Obj3(object, metaclass=MyType):
    x = 123

    def __init__(self):
        print('Obj3的__init__')

    def __new__(cls, *args, **kwargs):
        print('Obj3的__new__')
        return object.__new__(cls)

    def func(self):
        return 666


# print(Obj3)     # MyType的__init__     
obj3 = Obj3()   # MyType的__init__  MyType的__call__      Obj3的__new__      Obj3的__init__
# obj3 = Obj3()
# Obj3是类
# Obj3是MyType的一个对象
"""
1. 创建类时,先执行metaclass(默认为type)的__init__方法
2. 类在实例化时, 执行metaclass(默认为type)的__call__方法,__call__方法的返回值就是实例化的对象
    __call__内部调用:
        - 类.__new__方法:创建对象
        _ 类.__init__方法:对象的初始化
"""


class MyType(type):
    def __init__(self, *args, **kwargs):
        print('mytype__init__')
        super(MyType, self).__init__(*args,**kwargs)


# class Base(object, metaclass=MyType):
#     pass

# class Obj4(Base):
#     pass

def with_metaclass(arg):
    Base = MyType('Base',(arg,),{})
    # class Base(arg, metaclass=MyType):
    #   pass
    return Base


class Obj4(with_metaclass(object)):
    pass
高级:metaclass的内部实现

其他知识

1.创建类的三种方式

方式一:普通方式

In [19]: class Love(object):
    ...:     def love(self):
    ...:         print('love')
    ...: 

In [20]: f = Love()

In [21]: f.love()
love

方式二:自定义type

def love(self):
    print('love')

f = type('Love',(object,),{'func':love})
obj = f()
obj.func()

out:love

In [22]: f
Out[22]: <__main__.Love at 0xdb8e81c048>


In [23]: Love
Out[23]: __main__.Love

 

方式三: metaclass

class MyType(type):
    pass


class Obj(object, metaclass=MyType):
    x = 123

    def func(self):
        return 666

Obj2 = MyType('Obj2',(object,),{'x':123,'func': lambda self:666})

# 注意:metaclass的作用是制定当前类由谁创建, 默认是由type创建

class MyType(type):
    def __init__(self, *args, **kwargs):
        print('MyType的__init__')
        super(MyType, self).__init__(*args, **kwargs)

    def __call__(cls, *args, **kwargs):
        print('MyType的__call__')
        obj3 = cls.__new__(cls)
        cls.__init__(obj3)
        return obj


class Obj3(object, metaclass=MyType):
    x = 123

    def __init__(self):
        print('Obj3的__init__')

    def __new__(cls, *args, **kwargs):
        print('Obj3的__new__')
        return object.__new__(cls)

    def func(self):
        return 666


# print(Obj3)     # MyType的__init__     
obj3 = Obj3()   # MyType的__init__  MyType的__call__      Obj3的__new__      Obj3的__init__
# obj3 = Obj3()
# Obj3是类
# Obj3是MyType的一个对象
"""
1. 创建类时,先执行metaclass(默认为type)的__init__方法
2. 类在实例化时, 执行metaclass(默认为type)的__call__方法,__call__方法的返回值就是实例化的对象
    __call__内部调用:
        - 类.__new__方法:创建对象
        _ 类.__init__方法:对象的初始化
"""


class MyType(type):
    def __init__(self, *args, **kwargs):
        print('mytype__init__')
        super(MyType, self).__init__(*args,**kwargs)


# class Base(object, metaclass=MyType):
#     pass

# class Obj4(Base):
#     pass

def with_metaclass(arg):
    Base = MyType('Base',(arg,),{})
    # class Base(arg, metaclass=MyType):
    #   pass
    return Base


class Obj4(with_metaclass(object)):
    pass

2.私有属性

类的私有变量和私有方法

在Python中可以通过在属性变量名前加上双下划线定义属性为私有属性

特殊变量命名

1、 _xx 以单下划线开头的表示的是protected类型的变量。即保护类型只能允许其本身与子类进行访问。若内部变量标示,如: 当使用“from M import”时,不会将以一个下划线开头的对象引入 。

2、 __xx 双下划线的表示的是私有类型的变量。只能允许这个类本身进行访问了,连子类也不可以用于命名一个类属性(类变量),调用时名字被改变(在类FooBar内部,__boo变成_FooBar__boo,如self._FooBar__boo)

3、 __xx__定义的是特列方法。用户控制的命名空间内的变量或是属性,如init , __import__或是file 。只有当文档有说明时使用,不要自己定义这类变量。 (就是说这些是python内部定义的变量名)

在这里强调说一下私有变量,python默认的成员函数和成员变量都是公开的,没有像其他类似语言的public,private等关键字修饰.但是可以在变量前面加上两个下划线"_",这样的话函数或变量就变成私有的.这是python的私有变量轧压(这个翻译好拗口),英文是(private name mangling.) **情况就是当变量被标记为私有后,在变量的前端插入类名,再类名前添加一个下划线"_",即形成了_ClassName__变量名.**

# -*- coding: utf-8 -*-

"""
@Datetime: 2018/12/30
@Author: Zhang Yafei
"""


class Obj(object):
    def __init__(self, name, age):
        self.name = name
        self.__age = age

    def get_age(self):
        # print(self.__age)
        return self.__age


obj = Obj('张亚飞',23)
print(obj.name)     # 张亚飞
# print(obj.__age)  # AttributeError: 'Obj' object has no attribute '__age'
print(obj.get_age())    # 23
print(obj._Obj__age)    # 23

"""私有成员只能类中访问,外部不能直接访问,但若要访问,可以强制访:_类名__var, 或者在内部提供一个接口供外部访问"""


class Obj2(Obj):
    def print_age(self):
        print(self.__age)


obj2 = Obj2('张亚飞',23)
obj2.print_age()       # AttributeError: 'Obj2' object has no attribute '_Obj2__age'


"""私有字段只能在当前类中访问,其子类也不能访问"""
成员修饰符

 3. Python内置类属性

__dict__ : 类的属性(包含一个字典,由类的数据属性组成)

__doc__ :类的文档字符串

__module__: 类定义所在的模块(类的全名是'__main__.className',如果类位于一个导入模块mymod中,那么className.__module__ 等于 mymod)

__bases__ : 类的所有父类构成元素(包含了一个由所有父类组成的元组)
class pub():
    _name = 'protected类型的变量'
    __info = '私有类型的变量'
    def _func(self):
        print("这是一个protected类型的方法")
    def __func2(self):
        print('这是一个私有类型的方法')
    def get(self):
        return(self.__info)

a = pub()
print(a._name)
a._func()
# print(a.info)
# 执行结果:
# protected类型的变量
# 这是一个protected类型的方法

# protected类型的变量和方法 在类的实例中可以获取和调用

# # print(a.__info)
# # a.__func2()
# 执行结果:
#   File "D:/Python/class/class3.py", line 46, in 
#     print(a.__info)
# # AttributeError: pub instance has no attribute '__info'
#     a.__func2()
# AttributeError: pub instance has no attribute '__func2'

# 私有类型的变量和方法 在类的实例中获取和调用不到

# 获取私有类型的变量

print(a.get())
# 执行结果:私有类型的变量
# 如果想要在实例中获取到类的私有类形变量可以通过在类中声明普通方法,返回私有类形变量的方式获取


print(dir(a))
# 执行结果:['__doc__', '__module__', '_func', '_name', '_pub__func2', '_pub__info', 'get']
print(a.__dict__)
# 执行结果:{}
print(a.__doc__)
# 执行结果: None
print(a.__module__)
# 执行结果:__main__
print(a.__bases__)
# 执行结果:
#     print(a.__bases__)
# AttributeError: pub instance has no attribute '__bases__'
内置类属性

 4. 约束

Java:

  • 接口,约子类中必须包含某个方法(约束)。
  • 抽象方法/抽象类,约子类中必须包含某个方法。(约束+继承)
Interface IMessage:
    def func1(self):
        pass 
    def func2(self):
        pass 
        
class Msg(IMessage):
    def func1(self):
        print('func1') 
    def func2(self):
        print('func1') 
接口
class abstract IMessage:
    def abstract func1(self):
        pass 
    def abstract func2(self):
        pass 
    
    def func3(self):
        print('asdfasdf') 
        
class Msg(IMessage):
    def func1(self):
        print('func1') 
    def func2(self):
        print('func1') 
抽象类

Python

  • - 接口(无)
  • - 抽象方法/抽象类(有,ABC)
  • - 类继承+异常
import abc


class Base(metaclass=abc.ABCMeta):

    @abc.abstractmethod
    def send(self):pass

    def func(self):
        print(123)


class Foo(Base):

    def send(self):
        print('发送信息')


obj = Foo()
obj.send()
obj.func()
抽象方法/抽象类 类继承+异常

  作用:的用于告知其他人以后继承时,需要实现那个方法

class BaseAuthentication(object):
"""
All authentication classes should extend BaseAuthentication.
"""

    def authenticate(self, request):
        """
        Authenticate the request and return a two-tuple of (user, token).
        """
        raise NotImplementedError(".authenticate() must be overridden.")

    def authenticate_header(self, request):
        """
        Return a string to be used as the value of the `WWW-Authenticate`
        header in a `401 Unauthenticated` response, or `None` if the
        authentication scheme should return `403 Permission Denied` responses.
        """
        pass
rest_framework示例
class BaseMessage(object):

    def send(self):
        raise NotImplementedError('必须实现send方法')


class Msg(BaseMessage):
    def send(self):
        print('发送短信')


class Wechat(BaseMessage):
    def send(self):
        print('发送微信')


class Email(BaseMessage):
    def send(self):
        print('发送邮件')



class DingDing(BaseMessage):
    def send(self):
        print('发送钉钉提醒')
发送消息示例

 面向对象知识深入:

 -*- coding: utf-8 -*-

"""
@Datetime: 2018/12/29
@Author: Zhang Yafei
"""
"""方式一"""
# my_singleton.py
#
# class Singleton(object):
#     pass
#
# singleton = Singleton()
#
# from mysingleton import singleton

"""方式二:使用装饰器"""
# def Singleton(cls):
#     _instance = {}
#
#     def _singleton(*args, **kargs):
#         if cls not in _instance:
#             _instance[cls] = cls(*args, **kargs)
#         return _instance[cls]
#
#     return _singleton
#
#
# @Singleton
# class A(object):
#     a = 1
#
#     def __init__(self, x=0):
#         self.x = x
#
#
# a1 = A(2)
# a2 = A(3)

"""方式三:使用类"""
# import threading
# import time
#
#
# class Singleton(object):
#
#     def __init__(self):
#         # time.sleep(1)
#         pass
#     @classmethod
#     def instance(cls, *args, **kwargs):
#         if not hasattr(Singleton, "_instance"):
#             Singleton._instance = Singleton(*args, **kwargs)
#         return Singleton._instance
#
#
# def task(arg):
#     obj = Singleton.instance()
#     print(obj)
#
#
# for i in range(10):
#     t = threading.Thread(target=task,args=[i,])
#     t.start()

"""解决方法:加锁"""
# import time
# import threading
#
#
# class Singleton(object):
#     _instance_lock = threading.Lock()
#
#     def __init__(self):
#         time.sleep(1)
#
#     @classmethod
#     def instance(cls, *args, **kwargs):
#         if not hasattr(Singleton, "_instance"):
#             with Singleton._instance_lock:
#                 if not hasattr(Singleton, "_instance"):
#                     Singleton._instance = Singleton(*args, **kwargs)
#         return Singleton._instance
#
#
#
#
# def task(arg):
#     obj = Singleton.instance()
#     print(obj)
#
# for i in range(10):
#     t = threading.Thread(target=task,args=[i,])
#     t.start()
# time.sleep(20)
# obj = Singleton.instance()
# print(obj)

"""方法四:基于__new__方法"""
#
# import threading
#
# class Singleton(object):
#     _instance_lock = threading.Lock()
#
#     def __init__(self):
#         pass
#
#     def __new__(cls, *args, **kwargs):
#         if not hasattr(Singleton, "_instance"):
#             with Singleton._instance_lock:
#                 if not hasattr(Singleton, "_instance"):
#                     Singleton._instance = object.__new__(cls)
#         return Singleton._instance
#
#
# obj1 = Singleton()
# obj2 = Singleton()
# print(obj1,obj2)
#
#
# def task(arg):
#     obj = Singleton()
#     print(obj)
#
#
# for i in range(10):
#     t = threading.Thread(target=task,args=[i,])
#     t.start()
#
"""方法五:元类实现单例模式"""
import threading


class SingletonType(type):
    _instance_lock = threading.Lock()

    def __call__(cls, *args, **kwargs):
        if not hasattr(cls, "_instance"):
            with SingletonType._instance_lock:
                if not hasattr(cls, "_instance"):
                    cls._instance = super(SingletonType,cls).__call__(*args, **kwargs)
        return cls._instance


class Foo(metaclass=SingletonType):
    def __init__(self,name):
        self.name = name


obj1 = Foo('name')
obj2 = Foo('name')
print(obj1,obj2)
单例模式
class Obj4():
    def __enter__(self):
        print('__enter__')

    def __exit__(self, exc_type, exc_val, exc_tb):
        print('__exit__')


with Obj4():
    print('执行中')

# __enter__
# 执行中
# __exit__
"""with 对象默认执行__enter__方法,执行结束执行__exit__方法"""
with对象的本质
class Obj(object):
    def __iter__(self):
        # return iter([1,2,3])
        yield 1
        yield 2
        yield 3


obj = Obj()

for item in obj:
    print(item)
对象可以被for循环