跳至主要內容

面向对象编程一:类和实例

yczha大约 5 分钟python基础python语法python

Python基础系列内容为学习廖雪峰老师Python3教程的记录,廖雪峰老师官网地址:廖雪峰Python3教程open in new window

  • 面向对象编程简介:面向对象编程Object Oriented Programming简称OOP,是一种区别于面向过程编程的新的编程思想。OOP把对象作为程序的基本单元,一个对象包含了数据和操作数据的函数。

    Python中的所有数据类型都可以视为对象,也可以自定义对象。自定义的对象数据类型就是面向对象中的类class概念。

    示例:使用面向对象程序设计思想设计一个存储学生信息(姓名和成绩)的表为了显示区别,我们首先使用面向过程的程序来构造:

    stu1={'name':'Alex','score':98}
    stu2={'name':'Bob','score':89}
    ...
    

    然后使用函数来处理学生信息

    def print_score(stu):
        print('%s:%s' %(stu['name'],stu['score']))
    

    上面的代码简单演示了面向过程设计的存储数据到使用数据过程。接着我们用面向对象的程序设计思想来实现。

    首先,我们来考虑如何存储数据:我们把学生视为一个对象,那么姓名和成绩就是这个对象的两个属性,使用数据就属于对象的一个方法,我们把上面的内容转为代码就是:

    class Student(object):
        def __init__(self,name,score):
            self.name=name
            self.score=score
            
        def print_score(self):
            print('%s:%s' %(self.name,self.score))
    

    上面的代码中我们构造了一个Student类(对象),还构造了一个对象的方法(Method)print_score,现在我们就可以来实例化(Instance)对象

    bart=Student('Bart',67)
    lisa=Student('Lisa',88)
    

    调用对象的方法

    bart.print_score()
    lisa.print_score()
    

    我们来运行测试:

    >>> from stu import Student
    >>> bart=Student('Bart',67)
    >>> lisa=Student('Lisa',88)
    >>> bart.print_score()
    Bart:67
    >>> lisa.print_score()
    Lisa:88
    >>>
    

    这样,我们就完成了面向对象程序设计的第一个程序。由上可见,这种程序设计思想抽象程度要高于函数,因为它既包括了数据,又包括了操作数据的方法。

  • 类和实例:面向对象最重要的概念就是类(Class)和实例(Instance)。类是抽象的模板,而实例则是根据类创建出来的一个个具体的对象。

    类定义的一般格式,以前面创建的Student类为例

    class Student(object):
        pass
    

    上面Student代表类名,object代表继承的类,这里可以是继承不同的类,如果没有继承类,则使用所有类的公有继承类objectpass里写类的内容,这就是创建类的一般格式。

  • 实例化类的一般格式,以student类为例

    bart=Student('Bart',67)
    

    给类传入数据以后,类就被实例化为一个个对象,比如上面的bart就属于一个对象,该对象包括了namescore两个属性,还有一个print_score()方法。

    可以给一个实例自由的绑定属性,比如,为bart实例添加一个gender属性

    >>> bart.gender='male'
    >>> bart.gender
    'male'
    

    而有一些属性我们认为是必备的,这就可以通过一个特殊的__init__方法强制填入,比如前面的

    def __init__(self,name,score):
            self.name=name
            self.score=score
    

    注意这里的__init__是前后各两个下划线。

    另外,__init__方法的第一个参数永远是self,表示创建的实例本身。在实例化对象时,注意要传入与__init__方法相对应的参数,但是self不用传入。

  • 数据封装

    面向对象编程的一个重要特点就是数据封装。我们还是通过前面定义的Student类来看。对于面向过程的程序设计,当我们完成了数据的存储后,要实现对数据的操作,我们通常会定义一个方法,比如

    def print_score(stu):
            print('%s:%s' %(stu.name,stu.score))
    

    这样,方法和数据就是独立的,但是使用类的概念后,我们直接把这个方法封装进入类里,这样,调用这个类的方法只需这样:

    stu.print_score()
    

    可见,我们只关心操作对象的方法,而不关心其内部是如何实现的,这就是封装的优势所在。

    注意,在类内部写方法时,也需要把第一个参数置为self,至于其他的参数等都和普通函数完全一样,在调用时也同样不用传入self参数。

  • 访问限制:Python通过在变量前添加两个下划线来把变量申明为私有private,比如,前面的Student,你现在在外部仍可以修改内部代码

    >>> bart=Student('Bart',99)
    >>> bart.score=78
    >>> bart.score
    78
    >>>
    

    现在我们给类的namescore属性添加__,让外部不可访问

    class Student(object):
    	def __init__(self,name,score):
    		self.__name=name
    		self.__score=score
    	def print_score(self):
    		print('%s:%s' %(self.__name,self.__score))
    

    现在我们再来尝试从外部访问

    >>> bart=Student('Bart',99)
    >>> bart.__name
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    AttributeError: 'Student' object has no attribute '__name'
    

    发现,程序报错了,可见,通过添加__,程序把变量相应申明为私有了,这时,我们通过在程序内部提供公有的函数(public)来让外部使用

    def getName(self):
    		return self.__name
    def setName(self,name):
    		self.__name=name
    

    这样,我们就把内部的变量完全封装了。

    >>> bart=Student('Bart',99)
    >>> bart.setName('BART')
    >>> bart.getName()
    'BART'