• Python 面向对象


    Python 面向对象

    1.成员共分三类

    1.1 变量

    1.1.1 实例变量与类变量
    • class Foo:
          # 类变量(静态字段)
          country="中国"# 每个对象中的值都相同。
          # 方法
          def __init__(self,name):
              self.name=name     # 实例变量,字段
      
          # 方法
          def func(self):
              print(self.country)
              
              print(Foo.country)# 推荐使用
      
      obj1=Foo('章北海')
      obj2=Foo('泰勒')
      print(obj1.name,obj1.country,Foo.country)# obj1.country 没有设置,默认取类的值
      obj2.country='美国'
      # 类变量,可以通过类直接访问
      print(obj2.name,obj2.country,Foo.country)
      
    • 准则:

      • 实例变量(字段)访问时,使用对象访问,即obj.name
      • 类变量(静态字段)访问时,使用类方法,即Foo.country,实在不方便时,才使用对象。
    • 类变量的是使用场景:当所有对象中有共同的字段时,且要改都改要删都删,可以将实例变量(字段)提取到类变量(静态字段)。

    1.1.2 私有变量
    • 私有变量也分为两种,即私有类变量私有实例变量

    • class Foo:
          __country="中国"
          def __init__(self,name):
              self.__name=name #私有实例变量,字段
              self.age=123
      
          def func(self):
              print(self.__name)
              print(Foo.__country)
      
      obj=Foo('程心')
      # print(obj.__name) # 报错: AttributeError:'Foo' object has no attribute '__name'
      # print(Foo.__country)
      obj.func()
      
    • 私有的成员变量在 Python 中使用较少。特点是外部无法访问。特殊写法亦可获取到。一般不用。

    1.2 方法

    • 分类
      • 实例方法
      • 静态方法
      • 类方法
    • 私有方法
      • 私有实例方法
      • 私有静态方法
      • 私有类方法
    1.2.1 实例方法
    • 函数中必须包含self,
    • 一般通过对象调用
    1.2.2静态方法
    • 编写时:

      • 方法上写上@staticmethod
      • 参数可有可无
    • 调用时:

      • 类.方法名()
      • 对象.方法名() # 不推荐使用此种方法
    • 使用场景:静态方法无需使用对象中封装的值,那么就可以使用静态方法。

    • class Foo:
          def __init__(self,name):
              self.name=name
      
          # 实例方法
          def func(self):
              print(self.name)
      
          @staticmethod
          def display():
              print(666)
      
      obj=Foo("逻辑")
      Foo.display()# 一般使用类调用
      
    1.2.3 类方法
    • # -*- coding: utf-8 -*-
      '''
      @Time    : 2022/1/23 13:18
      @Author  : ziqingbaojian
      @File    : 03.方法.py
      '''
      class Foo:
          def __init__(self,name):
              self.name=name
      
          # 实例方法
          def func(self):
              print(self.name)
          
          # 静态方法
          @staticmethod
          def display():
              print(666)
      
          # 类方法
          @classmethod
          def show(cls,x1,x2):
              print(cls,x1,x2)
      
      # obj=Foo("逻辑")
      # Foo.display()# 一般使用类调用
      
      Foo.show(1,8)
      
      • 补充:self代值对象,cls代指类。
    • 定义时:

      • 方法上写上:@classmethod
      • 至少包含一个cls参数
    • 执行时:

      • 类名.方法名;默认会讲话当前类传值参数中
    • 使用场景:

      • 如果在方法中会使用到当前类,那么就可以使用类方法。单利模式可能会使用到对应的类方法。
    • 类方法与静态方法特别相似。调用时无需实例化。

    1.2.4 私有方法的使用
    # -*- coding: utf-8 -*-
    '''
    @Time    : 2022/1/23 13:18
    @Author  : ziqingbaojian
    @File    : 03.方法.py
    '''
    class Foo:
        def __init__(self,name):
            self.name=name
    
        # 实例方法
        def func(self):
            print(self.name)
    
        def __f1(self,args):
            print("私有方法")
        # 静态方法
        @staticmethod
        def __display():
            print("私有静态方法")
        @staticmethod
        def get_display():
            Foo.__display()
        # 类方法
        @classmethod
        def show(cls,x1,x2):
            print(cls,x1,x2)
    
    # obj=Foo("逻辑")
    # Foo.display()# 一般使用类调用
    
    Foo.get_display()
    

    1.3 属性

    class Foo:
    
        @property
        def start(self):
            return 1
        @property
        def end(self):
            return 2
    
    obj=Foo()
    print(obj.start)
    print(obj.end)
    
    

    将方法改造为属性,即调用方法时通常不使用()进行调用。

    • 编写时:
      • 方法上方写上@property
      • 方法参数只有一个self
    • 调用时:
      • 无序加括号,使用 对象.方法
    • 应用场景:
      • 对于简单的方法,当无需传参,且有返回值时,可以使用@property
    • 属性也具有共有和私之分。与变量和方法类似

    注意:类中私有的成员,在继承的子类中依旧不能被使用。

    2.组合(建模)

    2.1 对象的嵌套

    # -*- coding: utf-8 -*-
    '''
    @Time    : 2022/1/23 14:02
    @Author  : ziqingbaojian
    @File    : 04.组合建模.py
    '''
    
    class School:
        def __init__(self,name,addres):
            self.name=name
            self.addres=addres
    
    obj1=School("亚洲舰队",'自然选择号')
    obj2=School("亚洲舰队",'蓝色空间号')
    
    
    class Teacher:
        def __init__(self,name,age,salary):
            self.name=name
            self.age=age
            self.__salary=salary
            self.school=None
    t1=Teacher("章北海",30,10000)
    t2=Teacher("褚岩",20,30000)
    t1.school=obj1
    t2.school=obj2
    # 查看舰长所在的飞船,嵌套查看
    print(t1.school.name)
    print(t1.school.addres)
    

    2.2 主动调用其他类的成员

    class Base:
        def f1(self):
            print("5个功能")
    
    
    class Foo(object):
        def f1(self):
            Base.f1(self)
            print("3个功能功能")
            
    
    • 通过类名.实例方法()需要进行手动传参,传入self.

    • obj=Base()
      Base.f1(obj)# 手动传参
      

    2.3 继承调用

    class Base:
        def f1(self):
            print("5个功能")
    
    
    class Foo:
        def f1(self):
            super().f1()
            print("3个功能")
    
    class Info(Foo,Base):
        pass
    
    obj=Info()
    obj.f1()
    # 正确执行
    
    # obj=Foo()
    # obj.f1()报错,因为类中的 super() 表示的是当前继承顺序的下一个。并不是单单的只当前类的父类
    
    • super() 表示的是当前继承顺序的下一个。并不是单单的只当前类的父类

    3.特殊成员

    3.1 常见的双下滑线方法

    # -*- coding: utf-8 -*-
    '''
    @Time    : 2022/1/23 20:41
    @Author  : ziqingbaojian
    @File    : 06.特殊成员.py
    '''
    class Foo:
        # 初始化方法  类名()自动执行
        def __init__(self,name,age):
            print("对象初始化开始")
            self.name=name
            self.age=age
        # 对象() 自动执行
        def __call__(self, *args, **kwargs):
            print(args,kwargs)
    
        # 对象[xxx]自动执行
        def __getitem__(self, item):
            print(item)
            return 1
    
        # 对象[xxx]=11自动执行
        def __setitem__(self, key, value):
            print(key,value)
            # 本方法没返回值
    
        def __delitem__(self, key):
            print(1)
    
        # 实现对象加对象的运算
        def __add__(self, other):
            return self.age+other.age
    
    
        def __enter__(self):
            print("可以使用 with 上下文管理,返回值被 as 后面的值接收")
            return 123
    
        def __exit__(self, exc_type, exc_val, exc_tb):
            print(456)
    
    obj1=Foo("啊哈",20)
    obj1(1,23,3,k1="12")
    res=obj1['123']
    print(res)
    obj1['k1']="v1"
    obj1.__delitem__('123')
    list
    with obj1 as f:
        print(f)
        print("执行中")
    

    image-20220123210008557

    image-20220123202514799

    3.2 构造方法

    class Foo:
        def __init__(self,name):
            self.name=name
            print(2)
        def __new__(cls, *args, **kwargs):
            '''
            返回一个空的对象的供 init 进行初始化赋值
            :param args:
            :param kwargs:
            '''
            print(1)
            return object.__new__(cls)
    
    obj=Foo('0')
    

    image-20220123203842467

    说明:

    __init__一般称做初始化方法,__new__是真正创建对象的方法。是两个方法组成了类似与其他语言中的构造方法。

    3.3 常见特殊方法的使用

    1. __dict__方法
    • class Foo:
          def __init__(self,name,age):
              self.name=name
              self.age=age
      
      obj=Foo('章北海','230')
      print(obj.__dict__)#将实例变量以字典的形式返回
      
    • image-20220123211055754

    • 补充:

      • image-20220123211850447
      • 类.__dict__,会返回包括函数在内的成员信息,使用较少。
    1. __str__方法
    • class Foo:
          def __init__(self,name,age):
              self.name=name
              self.age=age
          def __str__(self):
              return "打印对象我就执行"
      obj=Foo('章北海','230')
      print(obj)
      
    • image-20220123211259108

    • 类似与 Java中的toString()方法。

    • 补充__repr__方法

      • image-20220123211520197
      • __str__内部调用了__repr__。当类中没有__str__,但是有__repr__,打印对象时 就会执行。一般使用__str__方法较多

    4.类的约束

    4.1 主动抛出异常

    class Foo:
        def send(self):
            # 如果抛出异常,则子类如果要调用则必须重写该方法
            raise NotImplemented(".send() must be overrideen")
        def func(self):
            print("正常执行")
    class Bar(Foo):
        pass
    obj=Bar()
    obj.func()
    obj.send()
    

    image-20220126204449752

    image-20220126204644594

    4.2 抽象类和抽象方法

    • 补充:

      • Python 语言中不包含接口的数据类型,但是包含抽象类,和抽象方法。
      • Java 中包含抽象类和抽象方法,且接口中的方法必须是抽象方法。
    • from abc import ABCMeta,abstractmethod
      
      
      class Foo(metaclass=ABCMeta):
      
          def func(self):
              print(123)
      
          @abstractmethod
          def send(self):
              pass
      
      
      class Bar(Foo):
          def send(self):
              print("Hello world")
      obj= Bar()
      obj.send()
      
    • image-20220126210226974

    • 说明:在 Python 语言中一般会使用第一种方式NotImplemented异常进行处理,而不定义相关的抽象类,抽象类与抽象方法不常用。

    5.多继承的补充

    • 默认:先找左边的再找右面的父类。
    class A(object):
        pass
    
    class B(object):
        def f1(self):
            print("B.f1")
    
    class C(A,B):
        pass
    
    obj=C()
    obj.f1()
    

    5.1 经典类和新式类

    • python2.2

      • 经典类:
      • 新式类:如果自己或自己的前辈只要有人继承 object,那么此类就是新式类。
    • python3 中全部都是新式类。

    • 区别:查找流程不同。

      • 经典类:一条到走到黑;深度优先
      • 新式类:采用 C3 算法。
    • 补充:

      查看继承关系。

      # 语法:类.__mro__
      print(E.__mro__)
      

      image-20220126212700559

      • 注意事项:super是遵循__mro__执行顺序。
      • Python2 中不包含__mro__方法。

    5.2 C3 算法

    image-20220126214450397

    • 简单新式类(记忆),复杂的时候使用C3算法。
      • image-20220126214315246
  • 相关阅读:
    指定HTML标签属性 |Specifying HTML Attributes| 在视图中生成输出URL |高级路由特性 | 精通ASP-NET-MVC-5-弗瑞曼
    传递额外的值 Passing Extra Values |在视图中生成输出URL | 高级路由特性 | 精通ASP-NET-MVC-5-弗瑞曼
    以其他控制器为目标 在视图中生成输出URL
    数组与指针(数组中所有元素的和)
    OC中的指针
    UIScrollView创建相册
    开发之UI篇
    TabBarController
    适配ipone5
    NSDate 哪些事
  • 原文地址:https://www.cnblogs.com/Blogwj123/p/15848245.html
Copyright © 2020-2023  润新知