习题答案
作业一,代码如下:
a = "0b1010011010"
print(int(a, 2))
结果为 “666”。
作业二:
- abs() 函数的返回值没有被重新赋值给 a
- int() 函数默认向下取整而不是四舍五入
- 没有使用 return 关键字返回结果
作业三,代码如下:
def ConvertAllToHex(a):
result = []
for i in a:
try:
result.append(hex(i))
except TypeError:
result.append(None)
return result
类与对象概念
简单来说,类是一张蓝图,而对象则是通过这张蓝图生产出的产品。
你可以设计一张蓝图叫做“螺栓图纸”,然后照着它去生产出很多螺栓。
你也可以在这张蓝图上略加改动,比如将螺纹的深度增大,变成一张新的蓝图。
同样的,也可以设计一张蓝图叫做“简书文章”,在此基础上生产出很多文章对象。
第一个类
在 Python 中,使用关键字 class 定义类。
让我们来尝试着做一个文章的蓝图:
class Article():
pass
类的名字是 Article,后面的括号在这里可以省略,但为了更深入地学习类的特点,建议保留。pass 在这里用作占位符,不然 Python 会认为你定义了一个类,但代码块里面是空的,从而报错。
这是一个空类,没有什么实际意义,让我们来定义几个属性。
属性是什么呢?文章的标题、内容、点赞量等等。
这些是文章对象的属性,而不是类的属性,所以我们不能在类里面直接定义,需要先创建一个方法。
方法是什么呢?发布文章、更新文章、对文章点赞等等。
这里我们要先创建一个叫做__init__
的方法,必须是这个名字,字母两边分别加上两个下划线。
在类里面,定义方法也使用 def 关键字。换句话说,def 在类中,定义的东西就叫方法,反之则叫做函数,想起来这个名词了吗?
class Article():
def __init__(self):
self.title = "Python 类与对象"
self.content = "类是一张蓝图,而对象则是生产出来的产品"
self.likes_count = 20
等等,self 是啥?在类中,我们定义的所有方法,第一个参数都必须是 self。其实其它名字也可以,但按照惯例,用 self 最合适。
这个变量的值是对象本身。如果你创建了一个对象 a,那么它的值就是 a 这个对象。
在英语中,self 的含义是”我自己“。
如果你不指定参数 self,定义变量的时候,Python 就不知道这个变量是属于哪个对象的了。
这个 self 的专业叫法是“指针”,但 Python 弱化了这一概念,我们可以忽略这一点。
在方法内操作对象的属性时,前面要加 self 和一个英文句点,其它语法与定义变量相同。
刚才我们创建的这个方法会在对象被创建时自动运行,不需要我们手动调用,是不是很 amazing?我们把这类方法叫做”魔法方法“。
你看到的所有双下划线包裹的方法都是魔法方法,它们会在合适的时机被自动调用。
这个__init__
方法还有一个名字叫做“构造方法”,顾名思义,告诉 Python 怎么创建新对象用的。
接下来我们将扩充这个类,增加对文章的操作。
class Article():
def __init__(self):
self.title = "Python 类与对象"
self.content = "类是一张蓝图,而对象则是生产出来的产品"
self.likes_count = 20
def update(self, title, content):
self.title = title
self.content = content
def likeit(self):
self.likes_count += 1
我们又定义了两个方法,用来对文章的内容进行更新,以及点赞。
现在,是时候把它变成现实了。
来个对象
创建一个对象:
article1 = Article()
这里的括号是不能省略的。
我们把从类创建对象的操作叫做“实例化”,因为对象是类的一个“实际的例子”,是不是很简单粗暴?
现在我们想看看这篇文章的内容,怎么做呢?
print(article1.content)
在对象后面加上一个点,再写上要访问的属性名称,就可以获取到它的属性了。
对象的属性可以直接更改,像这样:
article1.title = "类与对象真不错"
print(article1.title)
不过我们还是用规范的方式修改文章吧,调用它的 update 方法:
article1.update("类与对象真不错", "让我们来试试调用方法")
print(article1.title)
print(article1.content)
是不是有什么东西消失了?self 参数呢?其实 Python 会自动为我们搞定这个问题,不需要我们操心,当 self 不存在就好。
写的不错,给自己点个赞:
article1.likeit()
print(article1.likes_count)
但是,如果有人不讲武德:
article1.likes_count = 0
print(article1.likes_count)
怎么办?
私有方法和私有属性
点赞量是我们自己的,不能被别人随便改。
还好,Python 在设计之初就考虑到了这个问题,只需要在属性或者方法的前面加上两个下划线,就可以将其设为私有。
class SafeArticle():
def __init__(self):
self.title = "Python 类与对象"
self.content = "类是一张蓝图,而对象则是生产出来的产品"
self.__likes_count = 20
def update(self, title, content):
self.title = title
self.content = content
def likeit(self):
self.__likes_count += 1
def __delete(self):
self.title = ""
self.content = ""
self.__likes_count = 0
实例化:
article2 = SafeArticle()
不讲武德的人又来了,这次更狠:
article2.delete()
AttributeError: 'SafeArticle' object has no attribute 'delete'
有备而来,我们给防出去了,不错。
如果你不想这么强硬,只希望告诉一些君子“这是个私有属性 / 私有方法,别去碰它”,可以只加一个下划线。Python 不会禁止对它的访问,但编程规范会告诉其它人不要使用它。
其实 Python 中没有绝对的私有,所谓双下划线的私有只是把属性 / 方法改了个名,但强烈不建议大家去访问对象的私有部分,不然可能会带来一些很难解决的问题。这里也不会给出具体的操作方法,有兴趣的小伙伴自己去查阅资料。
在创建对象时传参
这个文章类我们已经做的差不多了,剩下的工作也就是增加更多的属性和方法,但用户开始不乐意了:
为什么不能在发布文章时就指定标题和内容?非要发布之后再更新?是不是在浪费我的更新次数?
好,我们来解决这个问题:
class GoodArticle():
def __init__(self, title, content):
self.title = title
self.content = content
self.__likes_count = 20
def update(self, title, content):
self.title = title
self.content = content
def likeit(self):
self.__likes_count += 1
def __delete(self):
self.title = ""
self.content = ""
self.__likes_count = 0
其实就是给构造方法加了几个参数,在后面设置对象属性的时候,将对应的属性设置好。
article3 = GoodArticle("非常不错的用户体验", "用户给你的程序设计点了个超赞")
print(article3.title)
print(article3.content)
完美。
面向对象三大特性
封装
顾名思义,把一些东西打包起来。
如果不使用类与对象,就要把文章的一系列属性作为变量定义在程序中,把方法变成函数,在函数里对变量进行操作。
这样没办法实现私有,也不能直接初始化文章的内容。
而且,当你的文章数量多起来时,这样就显得很麻烦了,每加一篇文章都需要添加很多对应的变量。
而对象就是把属性和方法装在了一个箱子里,你可以决定箱子里哪些东西可以看,哪些不能看,而且不同箱子里可以有相同的东西,也就是多个对象里可以有相同的属性名。
像这种把互相关联的东西打包在一起,使其成为一个整体的思想,称为封装。
多态
简单来说,就是多个对象有相同的属性或方法。
比如我们有一个“帖子”类,和我们的“文章”类一起,分别创建两个对象。
帖子和文章都有相同的属性,比如标题和内容,也都有相同的方法,比如点赞、评论和私有的删除。
同样的,所有电器都有“功率”这一属性,也都有“通电”方法;所有食物都有“卡路里”这一属性,也都有“食用”方法。
如果我们在设计类的时候做到了多态,只要掌握一个类实例化的对象所具有的属性和方法,就可以使用其它类实例化的对象来得到相似的结果。
第三个特性叫做“继承”,我们后文再讲。
课后习题
作业一:构造方法是什么意思?它的方法名是什么?它和“魔法方法”有什么关系?
作业二:假如有一个对象,它有三个属性,分别是add
、_update_status
和__reload
,请问这三个属性在私有性方面有什么异同?
作业三:请编写一个帖子类,使用字符串存储标题和内容,使用列表存储评论,使用两个整数分别存储点赞量和评论量,并实现以下操作对应的方法:
- 点赞帖子
- 取消点赞
- 添加评论
- 删除评论
- 删除帖子(私有)
要求帖子对象在创建时可以直接指定标题和内容,点赞量和评论量默认为 0,评论列表为空。
不需要考虑对用户身份与权限的校验问题。
网友评论