前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >开源图书《Python完全自学教程》8.2简单的类

开源图书《Python完全自学教程》8.2简单的类

作者头像
老齐
发布2022-07-06 16:10:23
2240
发布2022-07-06 16:10:23
举报
文章被收录于专栏:老齐教室

8.2 简单的类

请读者务必注意,本书讲述的是 Python 3 中类的创建方法,与 Python 2 相比,两个版本在定义类的时候稍有差别,如果看到了 Python 2 写的代码,注意区分。

8.2.1 创建类

打开你已经熟练使用的 IDE,用真正的 Python 程序实现8.1.2节中的“大侠”。

代码语言:javascript
复制
#coding:utf-8
"""
filename: superman.py
"""

class SuperMan:                      # (1)
    '''                              # (2)
    A class of superman
    '''
    def __init__(self, name):        # (3)
        self.name = name             # (4)
        self.gender = 1              # (5)
        self.single = False    
        self.illness = False
    def nine_negative_kungfu(self):  # (6)
        return "Ya! You have to die."

下面结合代码和图8-2-1,学习简单的、常见的类如何定义。

图8-2-1 简单类的结构

注释(1)逻辑行是类的头部,其组成部分是:

  • class 是定义类的关键词;
  • SuperMan 是这个类的名称。通常,类名称中每个单词的首字母要大写,如果是多个单词组合,单词之间不插入其它符号。切记,“代码通常是给人看的”,类的名称也尽可能本着“望文生义”的原则命名。
  • 类的名称后面紧跟着是英文半角状态下的冒号 “ : ”。注意,与定义函数不同,这里没有圆括号。在8.5节会介绍什么时候用到圆括号。

从注释(2)的逻辑行开始是类的代码块,依然是用四个空格的缩进表示代码块。

注释(2)的三引号以及后面的配对三引号,这之间是关于当前类的帮助文档,不是必须的。在通常的工程项目中,都要写,原因依然是“代码通常是给人看的”。

注释(3)和(6)定义了类的方法。它们都是由 def 这个关键词定义的,其实就是函数,只不过写在类里面罢了(8.4.1节会将类与方法给予比较)。习惯上,把写在类里面或者实例对象所具有的由 def 所定义的对象,叫做方法(Method)。

以类 SuperMan 中的方法 nine_negative_kungfu() 为例,其参数有特别的要求,第一个参数必须是 self ,而且它必须要有——至少要有一个名为self 的参数。另外,并非强制使用 self 参数名称,可以用别的名称,但使用 self 是惯例。这里所讲的规定和惯例,除了8.4.2和8.4.3节中所介绍的“类方法”和“静态方法”之外,对类的其他方法都适用——看来类的方法也不单纯。

既然方法和函数本质一样,那么方法的名称命名及其内部代码书写规范,就与函数一样了,此处不赘述,读者可以复习第7章关于函数的知识。

比较注释(3)和注释(6)两个逻辑行,所定义的方法虽然本质一样,但形式和命名还有差别。

注意方法名称“ __init__() ”的写法,是以双下划线开始和结尾。除了这个方法之外,在后续学习中,还会看到很多其他以双下划线开头和结尾的方法名称,Python 语言中将这些方法统称为特殊方法(Special Method),或者称为魔法方法(Magic Method,第9章中会介绍更多这类方法)。根据英文知识容易知晓,__init__() 方法的名称中的 “init” 来自单词 “initial” 。当用类创建实例的时候,首先访问这个方法(如果它存在的话),通过这个方法让实例具有其中所规定的属性。比如注释(4)的逻辑行:

  • self 表示实例化时创建的实例对象(8.2.2节会详细介绍);
  • self.name 表示实例对象具有名称为name 的属性;
  • self.name = name 表示实例对象的 name 属性(左侧的 name )的值是实例化时参数 name 的实参(引用对象)。注意,符号 = 左侧所表示的实例属性的名称和右侧的参数(变量)名称不是非要求一样的。也可以使用注释(5)所示的那样,直接给实例属性赋值。

由于 __init__() 方法是在创建实例开始就被调用,再结合“initial”这个单词,于是将这个方法称为“初始化方法”。

请读者注意,在有的中文资料中,把 __init__() 方法称为“构造方法”。本书作者认为这种命名易引起混乱,误导读者。因为在 Python 的类中,真正具有“构造”作用的方法是 __new__() 方法,不是 __init__() 。因此本书使用“初始化方法”与 __init__() 对应,而“构造方法”则是 __new__() 的中文名称(参阅第9章9.4节)。

还要提示读者注意,“初始化方法”的最后不要写 return 语句(如果非要写,就写 return None )。

注释(6)所定义的是一个普通方法(相对“特殊方法”而言的“普通”,名称的命名上不用双下划线开头和结尾),除了参数列表中的 self 参数有前述规定和惯例之外,其他方面与第7章学过的函数没有差别。

创建了 SuperMan 类之后,就可以用它创建实例——形象地说,“类是实例的工厂”,用它可以塑造无限多个“超人”。

8.2.2 实例

承接8.2.1所创建的 superman.py 文件中的 SuperMan 类,将它实例化,如下述代码:

代码语言:javascript
复制
#coding:utf-8
"""
filename: superman.py
"""

class SuperMan:                
    '''                        
    A class of superman
    '''
    def __init__(self, name):  
        self.name = name       
        self.gender = 1              
        self.single = False    
        self.illness = False
    def nine_negative_kungfu(self):  
        return "Ya! You have to die."

zhangsan = SuperMan("zhangsan")                           # (7)
print("superman's name is:", zhangsan.name)               # (8)
print("superman is:(0-female, 1-male) ",zhangsan.gender)  # (9)

result = zhangsan.nine_negative_kungfu()                  # (10)
print("If superman play nine negative kungfu, the result is:")
print(result)

程序中注释(7)的语句即依据 SuperMan 类创建一个实例,或说成“实例化”。所生成的实例是一个对象,或称为“实例对象”,并用变量 zhangsan 引用此对象。

在第7章7.3.1节曾借函数说明了对象后面紧跟圆括号的作用,可概括为“名称引用对象,圆括号才是执行”。对于类 SuperMan 而言,它也是一个对象——类也是对象,Python 中万物皆对象。例如:

代码语言:javascript
复制
>>> class Foo:
...     def __init__(self):
...         self.f = 'foo'
...
>>> Foo                 # (11)
<class '__main__.Foo'>
>>> type(Foo)
<class 'type'>
>>> id(Foo)
140693620290736

定义一个比较简单的类 Foo ——Foo 是类的名称。观察注释(11)及后续的操作,结合已学知识,可以总结出,与函数的名称引用函数对象雷同,类的名称也引用了类对象。

既然如此,如果要在后面增加一个圆括号,就应该表示“执行类”了。“类是实例的工厂”、“类是实例的蓝图”,执行类,就意味着产生实例。

代码语言:javascript
复制
>>> fo = Foo()
>>> fo
<__main__.Foo object at 0x7ff5c9622700>
>>> type(fo)
<class '__main__.Foo'>

由操作结果可知,Foo() 是一个实例对象。

再回到注释(7),执行类 SuperMan ,从而得到实例对象。注意,后面的圆括号中要有参数。这是因为 SuperMan 类的初始化方法的参数(形参)除了 self 之外,还有一个 name ,那么实例化(或者说“创建实例”)的时候,要为参数 name 传一个对象引用(实参)。

在实例化的时候,不需要给初始化方法中的 self 参数传对象引用。注释(7)执行之后,Python 解释器以“隐式传递”的方式,令 self 引用刚刚所创立的实例(参阅8.3.3节)。

在执行注释(7)即创建实例时,首先要调用类 SuperMan 里面所定义的初始化方法,执行其内部程序。本例中,创建了实例对象的一些属性并完成赋值。例如实例的 name 属性值是 'zhangsan'gender 属性值是 1 。注释(8)和(9)中,读取了所创建的实例 zhangsan 的两个属性 zhangsan.namezhangsan.gender 的值。

注释(10)的 zhangsan.nine_negative_kungfu() 表示调用了实例 zhangsannine_negative_kungfu() 方法,调用方式和函数一样。但是要注意参数,在类 SuperMan 中,每个方法的第一参数是 self ,通过实例调用方法的时候,不需要在圆括号中为 self 提供对象引用,这是因为 Python 解释器以“隐式传递”的方式向 self 参数传了 zhangsan 这个实例对象的引用(严格说法是变量 zhangsan 引用的实例对象,参阅8.3.3节)。

很容易理解,以注释(7)的方式,通过修改形参 name 的值,还可以创建无数个 SuperMan 类的实例,这些实例之间的差别在于其 name 属性的值不同。此即“类是实例工厂”的含义,工厂可以根据一个生产模型生产出很多产品,例如汽车制造厂生产汽车。

构建简单的类之后,下面要对其重要组成部分——属性和方法——分别进行详细说明。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2022-06-16,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 老齐教室 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 8.2 简单的类
    • 8.2.1 创建类
      • 8.2.2 实例
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档