首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >开源图书《Python完全自学教程》8.3.3关于self

开源图书《Python完全自学教程》8.3.3关于self

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

8.3.3 关于 self

在8.2.1节说明类的基本结构时,特别强调过,若在类里面定义方法,其第一个参数必须是 self,并且是不可或缺的(除了8.4.2和8.4.3节的之外)。当然,也可以不使用这个名称,self 只是 Python 中的惯例。但是,惯例还是要遵守,这样才能让别人也能容易阅读你的代码。

下面写一个专门研究 self 是什么的类。

>>> class P:
...     def __init__(self, name):
...         self.name = name
...         print(self)
...         print(type(self))
...         print(f'id of self:{id(self)}')
...

用类 P 创建实例,会同时执行 __init__() 方法,就能看到上述 print() 函数的执行结果:

>>> a = P('Assembly')
<__main__.P object at 0x7ff5cad34be0>    # (4)
<class '__main__.P'>                     # (5)
id of self:140693646560224               # (6)

由此结果可知:

  • 注释(4)所示的返回值说明 self 引用的对象是类 P 的实例,其内存地址的十六进制形式是 0x7ff5cad34be0
  • 注释(5)所示的返回值说明 self 引用的对象类型是 P (类也是类型);
  • 注释(6)所示的结果说明 self 引用的对象的内存地址的十进制形式是 140693646560224
>>> a
<__main__.P object at 0x7ff5cad34be0>
>>> type(a)
<class '__main__.P'>
>>> id(a)
140693646560224
>>> hex(id(a))
'0x7ff5cad34be0'

以上显示的是实例 a 的有关内容,并将十进制表示的内存地址转换为了十六进制表示。经过对比,可以下结论:selfa 引用了同一个实例对象——类 P 的实例。简化地说:“ self 就是实例对象。”

当创建实例的时候,实例变量作为第一个参数,被 Python 解释器传给了 self ,即8.2.2节所说过的“隐式传递”,所以初始化方法 __init__() 中的 self.name 是实例的属性。如下 a.__dict__ 即查看到实例 a 的属性。

>>> a.__dict__
{'name': 'Assembly'}

重写类 P ,增加一个方法,通过此方法的调用进一步理解 self 的作用。

>>> class P:
...     def __init__(self, name):
...         self.name = name
...     def get_name(self):
...         return self.name
...
>>> a = P('BASIC')
>>> a.get_name()
'BASIC'

结合图8-3-2,理解执行 a.get_name() 时实例对象通过 self “传递”的过程。

图8-3-2 关于 self

创建实例的时,'BASIC' 传给了参数 name (如图示中的①)。实例对象(实例名称所引用)传给了参数 self ,如图示中的②所示。当用执行 a.get_name() 时,实例也被隐式地作为第一个参数传给该方法,如图示中的③和④所示。

总之,读者应该理解,定义类的时候,参数 self 就是预备用来实例化后引用实例的变量(或“参数”)。

下面通过一个练习,理解类在编程实践中的应用。读者或许是在网上购买的本书,通常商家会根据消费者购物的金额多少确定快递费(“包邮区”除外)。假设我们为某网上书店编写程序,要求能够根据图书的单价、消费者购买数量以及快递费,计算买家应支付总金额——为了突出体现当前已经学过的知识,此问题已被简化。

老生常谈,请读者自行尝试后再看下面的代码示例。

#coding:utf-8
'''
filename: bookshop.py
'''

class Book:
    prices = {"A":45.7, "B":56.7, "C":67.8, "D":78.9, "E":90.1}  # 书与单价
    shipping = 5    # 快递费:5元
    
    def __init__(self, book_name, num, free_ship):
        self.book_name = book_name
        self.num = num
        self.free_ship = free_ship    # 免快递费的阈值

    # 计算总价
    def totals(self):
        price = Book.prices.get(self.book_name) 
        if price:
            t = price * self.num
            return (t + Book.shipping) if t < self.free_ship else t
        return "There is NO this book."

if __name__ == "__main__":
    book_a = Book('A', 2, 100)  # 购买两本 'A' ,免快递费的阈值 100   
    a_total = book_a.totals()
    print(a_total)

程序执行结果参考:

% python bookshop.py
96.4
本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2022-06-22,如有侵权请联系 cloudcommunity@tencent.com 删除

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

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

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

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 8.3.3 关于 self
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档