zoukankan      html  css  js  c++  java
  • python笔记--4--面向对象

    面向对象
      Python中对象的概念很广泛,Python中的一切内容都可以称为对象,除了数字、字符串、列表、元组、字典、集合、range对象、zip对象等等,函数也是对象,类也是对象。
      在Python中,可以使用内置方法isinstance()来测试一个对象是否为某个类的实例。
        >>> isinstance(car, Car)
        True
        >>> isinstance(car, str)
        False
      在Python中比较特殊的是,可以动态地为类和对象增加成员,这一点是和很多面向对象程序设计语言不同的,也是Python动态类型特点的一种重要体现。

      

      私有成员

      Python并没有对私有成员提供严格的访问保护机制。
      在定义类的成员时,如果成员名以两个下划线“__”开头则表示是私有成员。在内部,python使用一种name mangling技术,将__membername替换成_classname__membername,所以你在外部使用原来的私有成员的名字时,会提示找不到。
      私有成员在类的外部不能直接访问,Python的私有成员并不是真正意义上的私有,需要通过调用对象的公有成员方法来访问,也可以通过Python支持的特殊方式来访问。

      在Python中,以下划线开头的变量名和方法名有特殊的含义,尤其是在类的定义中。用下划线作为变量名和方法名前缀和后缀来表示类的特殊成员:
        _xxx:受保护成员,不能用'from module import *'导入;
        __xxx__:系统定义的特殊成员;
        __xxx:私有成员,只有类对象自己能访问,子类对象不能直接访问到这个成员,但在对象外部可以通过“对象名._类名__xxx”这样的特殊方式来访问。

      方法

      在类中定义的方法可以粗略分为四大类:公有方法、私有方法、静态方法类方法
        公有方法、私有方法都属于对象,私有方法的名字以两个下划线“__”开始,每个对象都有自己的公有方法和私有方法,在这两类方法中可以访问属于类和对象的成员;
        公有方法通过对象名直接调用,私有方法不能通过对象名直接调用,只能在属于对象的方法中通过self调用或在外部通过Python支持的特殊方式来调用。
        如果通过类名来调用属于对象的公有方法,需要显式为该方法的self参数传递一个对象名,用来明确指定访问哪个对象的数据成员。
        静态方法和类方法都可以通过类名和对象名调用,但不能直接访问属于对象的成员,只能访问属于类的成员。
        静态方法可以没有参数。
        一般将cls作为类方法的第一个参数名称,但也可以使用其他的名字作为参数,并且在调用类方法时不需要为该参数传递值。

    class Root:
        __total = 0               # 私有成员变量
    
        def __init__(self, v):    # 构造方法
            self.__value = v
            Root.__total += 1     # 类中成员属性属于类,需要用 类名. 来调用
    
        def show(self):           # 普通实例方法
            print('self.__value:', self.__value)
            print('Root.__total:', Root.__total)
    
        @classmethod              # 装饰器,声明类方法
        def classShowTotal(cls):  # 类方法
            print(cls.__total)
    
        @staticmethod             # 装饰器,声明静态方法
        def staticShowTotal():    # 静态方法
            print(Root.__total)
    
    
    r = Root(3)
    r.classShowTotal()              # 通过对象来调用类方法
    r.staticShowTotal()             # 通过对象来调用静态方法
    r.show()
    rr = Root(5)
    Root.classShowTotal()           # 通过类名调用类方法
    Root.staticShowTotal()          # 通过类名调用静态方法
    rr.show()
    '''
    1
    1
    self.__value: 3
    Root.__total: 1
    2
    2
    self.__value: 5
    Root.__total: 2
    '''

      @property把方法编程可调用的属性

    class Student(object):
        '''测试property装饰器'''
    
        @property
        def birth(self):
            # 此为getter方法
            return self._birth
    
        @birth.setter
        def birth(self, value):
            # 此为setter方法
            self._birth = value
    
        @birth.deleter
        def birth(self):
            print('调用birth的deleter方法')
            del self._birth
    
        @property
        def age(self):
            # 没有为age设置setter方法,因此age是一个只读属性
            return 2018 - self._birth
    
    
    s = Student()
    s.birth = 1997          # 加上@property装饰器后,birth和age都变成属性了,age没有定义setter方法,因此为只读属性
    print(s.birth)
    # 1997
    print(s.age)
    # 21
    del s.birth
    # 调用birth的deleter方法

    python类的特殊方法

    方法

    功能说明

    __new__()

    类的静态方法,用于确定是否要创建对象

    __init__()

    构造方法,创建对象时自动调用

    __del__()

    析构方法,释放对象时自动调用

    __add__()

    +

    __sub__()

    -

    __mul__()

    *

    __truediv__()

    /

    __floordiv__()

    //

    __mod__()

    %

    __pow__()

    **

    __eq__()、 __ne__()、__lt__()、 __le__()、__gt__()、 __ge__()

    ==、 !=、<、 <=、>、 >=

    __lshift__()、__rshift__()

    <<、>>

    __and__()、__or__()、__invert__()、__xor__()

    &、|、~、^

    __iadd__()、__isub__()

    +=、-=,很多其他运算符也有与之对应的复合赋值运算符

    __pos__()

    一元运算符+,正号

    __neg__()

    一元运算符-,负号

    __contains__ ()

    与成员测试运算符in对应

    __radd__()、__rsub__

    反射加法、反射减法,一般与普通加法和减法具有相同的功能,但操作数的位置或顺序相反,很多其他运算符也有与之对应的反射运算符

    __abs__()

    与内置函数abs()对应

    __bool__()

    与内置函数bool()对应,要求该方法必须返回True或False

    __bytes__()

    与内置函数bytes()对应

    __complex__()

    与内置函数complex()对应,要求该方法必须返回复数

    __dir__()

    与内置函数dir()对应

    __divmod__()

    与内置函数divmod()对应

    __float__()

    与内置函数float()对应,要求该该方法必须返回实数

    __hash__()

    与内置函数hash()对应

    __int__()

    与内置函数int()对应,要求该方法必须返回整数

    __len__()

    与内置函数len()对应

    __next__()

    与内置函数next()对应

    __reduce__()

    提供对reduce()函数的支持

    __reversed__()

    与内置函数reversed()对应

    __round__()

    对内置函数round()对应

    __str__()

    与内置函数str()对应,要求该方法必须返回str类型的数据

    __repr__()

    打印、转换,要求该方法必须返回str类型的数据

    __getitem__()

    按照索引获取值

    __setitem__()

    按照索引赋值

    __delattr__()

    删除对象的指定属性

    __getattr__()

    获取对象指定属性的值,对应成员访问运算符“.”

    __getattribute__()

    获取对象指定属性的值,如果同时定义了该方法与__getattr__(),那么__getattr__()将不会被调用,除非在__getattribute__()中显式调用__getattr__()或者抛出AttributeError异常

    __setattr__()

    设置对象指定属性的值

    __base__

    该类的基类

    __class__

    返回对象所属的类

    __dict__

    对象所包含的属性与值的字典

    __subclasses__()

    返回该类的所有子类

    __call__()

    包含该特殊方法的类的实例可以像函数一样调用

    __get__()

    定义了这三个特殊方法中任何一个的类称作描述符(descriptor),描述符对象一般作为其他类的属性来使用,这三个方法分别在获取属性、修改属性值或删除属性时被调用

    __set__()

    __delete__()

                                                                                                                                                              

    继承
      继承是为代码复用和设计复用而设计的,是面向对象程序设计的重要特性之一。设计一个新类时,如果可以继承一个已有的设计良好的类然后进行二次开发,无疑会大幅度减少开发工作量。
      在继承关系中,已有的、设计好的类称为父类或基类,新设计的类称为子类或派生类。派生类可以继承父类的公有成员,但是不能继承其私有成员。如果需要在派生类中调用基类的方法,可以使用内置函数super()或者通过“基类名.方法名()”的方式来实现这一目的。
      Python支持多继承,如果父类中有相同的方法名,而在子类中使用时没有指定父类名,则Python解释器将从左向右按顺序进行搜索。

    class A(object):
        def __init__(self):
            self.__private()
            self.public()
    
        def __private(self):
            print('__private() method in A')
    
        def public(self):
            print('public() method in A')
    
    
    class B(A):
        '''
        注意,类B没有定义构造函数,会调用父类A的构造函数,私有方法使用父类A的,普通公开方法使用的是自己的
        '''
        def __private(self):
            print('__private() method in B')
    
        def public(self):
            print('public() method in B')
    
    
    class C(A):
        '''
        显式定义了构造函数,直接调用自己定义的构造函数,而不是调用父类的构造函数。
        私有方法和普通公开方法都是使用自己的。
        '''
        def __init__(self):         # 显式定义构造函数
            self.__private()
            self.public()
    
        def __private(self):
            print('__private() method in C')
    
        def public(self):
            print('public() method in C')
    
    
    b = B()
    c = C()
    '''
    __private() method in A
    public() method in B
    __private() method in C
    public() method in C
    '''

    多态
      所谓多态(polymorphism),是指基类的同一个方法在不同派生类对象中具有不同的表现和行为。派生类继承了基类行为和属性之后,还会增加某些特定的行为和属性,同时还可能会对继承来的某些行为进行一定的改变,这都是多态的表现形式。
      Python大多数运算符可以作用于多种不同类型的操作数,并且对于不同类型的操作数往往有不同的表现,这本身就是多态,是通过特殊方法与运算符重载实现的。

    class Animal(object):      # 定义基类
        def show(self):
            print('I am an animal.')
    
    
    class Cat(Animal):         # 派生类,覆盖了基类的show()方法
        def show(self):
            print('I am a cat.')
    
    
    class Dog(Animal):         # 派生类
        def show(self):
            print('I am a dog.')
    
    
    class Tiger(Animal):       # 派生类
        def show(self):
            print('I am a tiger.')
    
    
    class Test(Animal):        # 派生类,没有覆盖基类的show()方法
        pass
    
    
    x = [item() for item in (Animal, Cat, Dog, Tiger, Test)]
    for item in x:        # 遍历基类和派生类对象并调用show()方法
        item.show()
    '''
    I am an animal.
    I am a cat.
    I am a dog.
    I am a tiger.
    I am an animal.
    '''
  • 相关阅读:
    Java WebService入门实例
    Maven是什么
    for 循环
    2.4 DevOps工程师的故事:构建运行时的严谨性
    2.3.3 构建微服务的入口:Spring Boot控制器
    2.3.2 引导Spring Boot应用程序:编写引导类
    2.1.3 互相交流:定义服务接口
    第2章 使用Spring Boot构建微服务
    第1章 欢迎来到Cloud和Spring
    第一次在博客园开博
  • 原文地址:https://www.cnblogs.com/chuangming/p/8996561.html
Copyright © 2011-2022 走看看