理解Python中的类与实例


Posted in Python onApril 27, 2015

面向对象最重要的概念就是类(Class)和实例(Instance),必须牢记类是抽象的模板,比如Student类,而实例是根据类创建出来的一个个具体的“对象”,每个对象都拥有相同的方法,但各自的数据可能不同。

仍以Student类为例,在Python中,定义类是通过class关键字:

class Student(object):
  pass

class后面紧接着是类名,即Student,类名通常是大写开头的单词,紧接着是(object),表示该类是从哪个类继承下来的,继承的概念我们后面再讲,通常,如果没有合适的继承类,就使用object类,这是所有类最终都会继承的类。

定义好了Student类,就可以根据Student类创建出Student的实例,创建实例是通过类名+()实现的:

>>> bart = Student()
>>> bart
<__main__.Student object at 0x10a67a590>
>>> Student
<class '__main__.Student'>

可以看到,变量bart指向的就是一个Student的object,后面的0x10a67a590是内存地址,每个object的地址都不一样,而Student本身则是一个类。

可以自由地给一个实例变量绑定属性,比如,给实例bart绑定一个name属性:

>>> bart.name = 'Bart Simpson'
>>> bart.name
'Bart Simpson'

由于类可以起到模板的作用,因此,可以在创建实例的时候,把一些我们认为必须绑定的属性强制填写进去。通过定义一个特殊的__init__方法,在创建实例的时候,就把name,score等属性绑上去:

class Student(object):

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

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

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

>>> bart = Student('Bart Simpson', 59)
>>> bart.name
'Bart Simpson'
>>> bart.score
59

和普通的函数相比,在类中定义的函数只有一点不同,就是第一个参数永远是实例变量self,并且,调用时,不用传递该参数。除此之外,类的方法和普通函数没有什么区别,所以,你仍然可以用默认参数、可变参数和关键字参数。
数据封装

面向对象编程的一个重要特点就是数据封装。在上面的Student类中,每个实例就拥有各自的name和score这些数据。我们可以通过函数来访问这些数据,比如打印一个学生的成绩:

>>> def print_score(std):
...   print '%s: %s' % (std.name, std.score)
...
>>> print_score(bart)
Bart Simpson: 59

但是,既然Student实例本身就拥有这些数据,要访问这些数据,就没有必要从外面的函数去访问,可以直接在Student类的内部定义访问数据的函数,这样,就把“数据”给封装起来了。这些封装数据的函数是和Student类本身是关联起来的,我们称之为类的方法:

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)

要定义一个方法,除了第一个参数是self外,其他和普通函数一样。要调用一个方法,只需要在实例变量上直接调用,除了self不用传递,其他参数正常传入:

>>> bart.print_score()
Bart Simpson: 59

这样一来,我们从外部看Student类,就只需要知道,创建实例需要给出name和score,而如何打印,都是在Student类的内部定义的,这些数据和逻辑被“封装”起来了,调用很容易,但却不用知道内部实现的细节。

封装的另一个好处是可以给Student类增加新的方法,比如get_grade:

class Student(object):
  ...

  def get_grade(self):
    if self.score >= 90:
      return 'A'
    elif self.score >= 60:
      return 'B'
    else:
      return 'C'

同样的,get_grade方法可以直接在实例变量上调用,不需要知道内部实现细节:

>>> bart.get_grade()
'C'

小结

类是创建实例的模板,而实例则是一个一个具体的对象,各个实例拥有的数据都互相独立,互不影响;

方法就是与实例绑定的函数,和普通函数不同,方法可以直接访问实例的数据;

通过在实例上调用方法,我们就直接操作了对象内部的数据,但无需知道方法内部的实现细节。

和静态语言不同,Python允许对实例变量绑定任何数据,也就是说,对于两个实例变量,虽然它们都是同一个类的不同实例,但拥有的变量名称都可能不同:

>>> bart = Student('Bart Simpson', 59)
>>> lisa = Student('Lisa Simpson', 87)
>>> bart.age = 8
>>> bart.age
8
>>> lisa.age
Traceback (most recent call last):
 File "<stdin>", line 1, in <module>
AttributeError: 'Student' object has no attribute 'age'
Python 相关文章推荐
Python操作CouchDB数据库简单示例
Mar 10 Python
Python实现的中国剩余定理算法示例
Aug 05 Python
利用Django-environ如何区分不同环境
Aug 26 Python
python实现简单日期工具类
Apr 24 Python
python opencv minAreaRect 生成最小外接矩形的方法
Jul 01 Python
在python中,使用scatter绘制散点图的实例
Jul 03 Python
python3实现绘制二维点图
Dec 04 Python
浅谈PyQt5中异步刷新UI和Python多线程总结
Dec 13 Python
关于Pytorch的MLP模块实现方式
Jan 07 Python
Python2与Python3的区别详解
Feb 09 Python
Python3实现英文字母转换哥特式字体实例代码
Sep 01 Python
python基于win32api实现键盘输入
Dec 09 Python
简述Python中的面向对象编程的概念
Apr 27 #Python
介绍Python中的__future__模块
Apr 27 #Python
在Python中使用第三方模块的教程
Apr 27 #Python
在Python中使用模块的教程
Apr 27 #Python
详细介绍Python中的偏函数
Apr 27 #Python
举例讲解Python中装饰器的用法
Apr 27 #Python
Python中的匿名函数使用简介
Apr 27 #Python
You might like
smtp邮件发送一例
2006/10/09 PHP
php字符串截取中文截取2,单字节截取模式
2007/12/10 PHP
phpStudy2016 配置多个域名期间遇到的问题小结
2017/10/19 PHP
解决laravel 出现ajax请求419(unknown status)的问题
2019/09/03 PHP
javascript css styleFloat和cssFloat
2010/03/15 Javascript
jQuery scroll事件实现监控滚动条分页示例
2014/04/04 Javascript
js使用split函数按照多个字符对字符串进行分割的方法
2015/03/20 Javascript
最佳的JavaScript错误处理实践
2016/07/16 Javascript
微信小程序 缓存(本地缓存、异步缓存、同步缓存)详解
2017/01/17 Javascript
JavaScript省市级联下拉菜单实例
2017/02/14 Javascript
js获取浏览器和屏幕的各种宽度高度
2017/02/22 Javascript
实例详解BootStrap的动态模态框及静态模态框
2018/08/13 Javascript
H5 js点击按钮复制文本到粘贴板
2020/11/19 Javascript
[01:31:03]DOTA2完美盛典全回顾 见证十五项大奖花落谁家
2017/11/28 DOTA
[41:17]VG vs Optic 2018国际邀请赛小组赛BO2 第二场 8.19
2018/08/21 DOTA
[03:24][TI9纪实] Dota奶爸
2019/08/22 DOTA
用Python实现一个简单的线程池
2015/04/07 Python
自己编程中遇到的Python错误和解决方法汇总整理
2015/06/03 Python
python获取当前用户的主目录路径方法(推荐)
2017/01/12 Python
python实现kNN算法
2017/12/20 Python
Pycharm 实现下一个文件引用另外一个文件的方法
2019/01/17 Python
Python scrapy爬取小说代码案例详解
2020/07/09 Python
Python爬虫教程知识点总结
2020/10/19 Python
CSS3的 fit-content实现水平居中
2017/09/07 HTML / CSS
俄罗斯优惠券网站:BIGLION
2017/05/21 全球购物
SCHIESSER荷兰官方网站:德国内衣专家
2020/10/09 全球购物
个人函授自我鉴定
2014/03/25 职场文书
药品业务员岗位职责
2014/04/17 职场文书
电子信息工程专业自荐书
2014/06/24 职场文书
在职员工证明书
2014/09/19 职场文书
班主任高考寄语
2015/02/26 职场文书
2015年公司后勤管理工作总结
2015/05/13 职场文书
员工旷工检讨书
2015/08/15 职场文书
2016入党积极分子考察评语
2015/12/01 职场文书
Java面试题冲刺第十九天--数据库(4)
2021/08/07 Java/Android
详解Redis的三种常用的缓存读写策略步骤
2022/05/06 Redis