Python(五)


面向对象编程(OOP)

  1. OOP把对象作为程序的基本单元,一个对象包含了数据和操作数据的函数。面向对象的程序设计把计算机程序视为一组对象的集合,而每个对象都可以接收其他对象发过来的消息,并处理这些消息,计算机程序的执行就是一系列消息在各个对象之间传递。

  2. 面向过程的程序设计把计算机程序视为一系列的命令集合,即一组函数的顺序执行。面向过程把函数继续切分为子函数,即把大块函数通过切割成小块函数来降低系统的复杂度。

  3. 在Python中,所有数据类型都可以视为对象,当然也可以自定义对象。自定义的对象数据类型就是面向对象中的类(Class)的概念。

  4. 面向对象的设计思想是抽象出Class,根据Class创建Instance。

    面向对象的抽象程度比函数要高,因为一个Class既包含数据,又包含操作数据的方法。

  5. 数据封装、继承和多态是面向对象的三大特点。

一、类和实例

  1. 以Student类为例,类名通常是大写开头,紧接着是(object),表示该类是从哪个类继承下来的。

    class Student(object):
        pass
    sq = Student()
    sq.name = 'guluyu' # 可以自由地给一个实例变量绑定属性。
  2. 由于类可以起到模板的作用,因此,可以在创建实例的时候,把一些我们认为必须绑定的属性强制填写进去。

    class Student(object):
        def __init__(self, name, score):
            self.name = name
            self.score = score

    __init__方法的第一个参数永远是self,表示创建的实例本身,因此,在__init__方法内部,就可以把各种属性绑定到self,因为self就指向创建的实例本身。

  3. 有了__init__方法,在创建实例的时候,就不能传入空的参数了,必须传入与__init__方法匹配的参数,但self不需要传,Python解释器自己会把实例变量传进去:

    haha = Student('niuwa', 96)
  4. 和普通的函数相比,在类中定义的函数只有一点不同,就是第一个参数永远是实例变量self,并且调用时,不用传递该参数。

  5. 面向对象编程的一个重要特点就是数据封装

    上例中Student类内部拥有数据,要访问这些数据,不必从外面的函数去访问,而是直接在内部定义访问数据的函数,这样就把这些数据封装起来了。

    class Student(object):
        def __init__(self, name, score):
            self.name = name
            self.score = score
            
        def pr_score(self):
            print('%s: %s' % (self.name, self.score))
    
    haha = Student('niuwa', 96)
    haha.pr_score()
  6. 和静态语言不同,Python允许对实例变量绑定任何数据,也就是说,对于两个实例变量,虽然它们都是同一个类的不同实例,但拥有的变量名称都可能不同:

    class Student(object):
        pass
    sq = Student()
    sq.name = 'guluyu'
    ls = Student()
    ls.age = 18

二、访问限制

  1. 如果要让内部属性不被外部访问,可以把属性的名称前加上两个下划线__就变成了一个私有变量(private),只有内部可以访问,外部不能访问。

  2. 如果外部代码要获取内部变量,可以在类中增加get函数,如果想修改可以增加set函数。用这种方法的原因是在方法中可以对参数做检查,避免传入无效的参数。

    class Student(object):
        def __init__(self, name, score):
            self.__name = name
            self.__score = score
            
        def pr_score(self):
            print('%s: %s' % (self.__name, self.__score))
            
        def get_name(self):
            return self.__name
        
        def get_score(self):
            return self.__score
        
        def set_score(self, score):
            if 0 <= score <= 100:
                self.__score = score
            else:
                raise ValueError('bad score')
  3. __xxx__是特殊变量,可以直接访问的,不是private变量。

三、继承和多态

  1. 在OOP程序设计中,当我们定义一个class的时候,可以从某个现有的class继承,新的class称为子类(Subclass),而被继承的class称为基类、父类或超类(Base class、Super class)。

  2. 子类获得了父类的全部功能,子类也可以增加方法。

    class Animal(object):
        def run(self):
            print('Animal is running...')
    class Dog(Animal):
        pass
    class Cat(Animal):
        def   
    dog = Dog()
    dog.run() # Animal is running...
    cat = Cat()
    cat.run() # Cat is running...
  3. 继承的另一个好处:多态

  4. 在继承关系中,如果一个实例的数据类型是某个子类,那它的数据类型也可以被看做是父类。但是,反过来就不行。

    def run_twice(animal): # 编写一个函数,这个函数接受一个Animal类型的变量
        animal.run()
        animal.run()
    run_twice(Animal())
    run_twice(Dog())
    run_twice(Cat()) 
    run_twice(cat) # Cat is running...
  5. 新增一个Animal的子类,不必对run_twice()做任何修改,实际上,任何依赖Animal作为参数的函数或者方法都可以不加修改地正常运行。

  6. 调用方只管调用,不管细节,而当我们新增一种Animal的子类时,只要确保run()方法编写正确,不用管原来的代码是如何调用的。这就是著名的开闭原则,即对扩展开放:允许新增Animal子类;对修改封闭:不需要修改依赖Animal类型的run_twice()等函数。

  7. 继承树

    image-20230504113709797
  8. 静态语言和动态语言

    • 对于静态语言(例如Java)来说,如果需要传入Animal类型,则传入的对象必须是Animal类型或者它的子类,否则,将无法调用run()方法。

    • 对于Python这样的动态语言来说,则不一定需要传入Animal类型。只需要保证传入的对象有一个run()方法就可以了。

    动态语言的“鸭子类型”,它并不要求严格的继承体系,一个对象只要“看起来像鸭子,走起路来像鸭子”,那它就可以被看做是鸭子。

四、获取对象信息

  1. type()函数返回对应的Class类型。

  2. 要判断class的类型,可以使用isinstance()函数。

  3. 如果要获得一个对象的所有属性和方法,可以使用dir()函数,它返回一个包含字符串的list。

    type(123)
    type(abs)
    type('ab') == type('c')
    import types
    type(lambda x:x) == types.LambdaType
    a = Animal()
    isinstance(a, Animal)
    isinstance([1,2,3], (list,tuple)) # 判断一个变量是否是某些类型中的一种
    dir('ABC')
  4. 优先使用isinstance()判断类型。

五、实例属性和类属性

  1. 实例属性优先级比类属性高,不要对实例属性和类属性使用相同的名字,因为相同名称的实例属性将屏蔽掉类属性,但是当你删除实例属性后,再使用相同的名称,访问到的将是类属性。
  2. 实例属性属于各个实例所有,互不干扰。
  3. 类属性属于类所有,所有实例共享一个属性。

文章作者: nusqx
文章链接: https://nusqx.top
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 nusqx !
评论
  目录