Python类的常用魔法方法

2023-05-16

文章目录

  • 一. `__init__()`
  • 二. `__str__()`
  • 三. `__del__()`
  • 四. `__repr__()`
  • 五. 使用案例

一. __init__()

# 在Python类中,有一类方法,这类方法以 两个下划线开头和结尾,并且在满足某个特定条件的情况下会自动调用,这类方法称为魔法方法
"""
__init__()
调用时机: 在创建对象之后,会立即调用
作用:
    1. 用来给对象添加属性,给对象添加一个初始值(构造函数)
    2. 代码的业务需求,每创建一个对象,都需要执行的代码可以写在__init__中
"""


class Dog(object):
    def __init__(self, name):
        print('我是__init__方法,我被调用了')
        # 对象.属性名 = 属性值 ,直接在类中代码定义属性,之后创建对象时,如果不修改属性值,那么所有对象的属性值都是一样的
        # self.name = '小狗'
        self.name = name


# 创建对象,每次创建都会执行__init__方法的代码
# Dog()  # 这里对象已经创建,只不过没有使用变量保存,后续代码无法使用

dog = Dog('大黄')
print(dog.name)

dog1 = Dog('小白')
print(dog1.name)

# 注意点: 如果__init__方法中,有除了self之外的形参,那么在创建对象时,需要给额外的形参传递实参值,否则会报错  类名(实参值)

二. __str__()

"""
__str__()
调用时机:
    1. print(对象),会自动调用__str__方法,打印输出的结果是__str__方法的返回值
    2. str(对象) 类型转换,将自定义对象转换为字符串的时候,会自动调用
应用:
    1. 打印对象的时候,输出一些属性信息
    2. 需要将对象转换为字符串类型的时候
注意点:
    方法必须返回一个字符串,此方法通常只有 self 一个参数
"""


class Dog(object):
    def __init__(self, name, age):
        # 添加属性
        self.name = name
        self.age = age

    def __str__(self):
        print('我是__str__,我被调用了')  # 实际代码不写这种的,只用写return即可
        # 必须返回一个字符串,否则会报错
        return f"小狗的名字是{self.name},年龄是{self.age}"


# 创建对象
dog = Dog('大黄', 2)
print(dog)  # 没有定义 __str__ 方法时,print(对象)时,默认输出对象的引用地址

str_dog = str(dog)  # 没有定义 __str__ 方法时,进行类型转换,赋值的也是引用地址
print(str_dog)

三. __del__()

"""
__del__()
析构函数
调用时机:
    对象在内存中被销毁删除的时候会自动调用__del__方法
    1. 程序代码运行结束,在程序运行过程中,创建的所有对象和变量都会被删除销毁
    2. 使用  del变量  删除变量,将这个对象的引用计数变为0,然后就会自动调用__del__方法
应用场景:
    对象被删除销毁的时候,要书写的代码可以写在__del__方法中,一般很少使用

引用计数: 是Python内存管理的一种机制,是指一块内存,有多少个变量在引用,有一个变量引用计数就是1,三个变量就是3
    1. 当一个变量,引用一块内存的时候,引用计数加1
    2. 当删除一个变量或者这个变量不再引用这块内存时,引用计数减1
    3. 当内存的引用计数变为0时,这块内存被删除,内存中的数据会被销毁
    例如:
    my_list = [1, 2]   # 1
    my_list1 = my_list   # 2
    del my_list   # 1
    def my_list1   # 2
"""


class Dog(object):
    def __init__(self, name, age):
        # 添加属性
        self.name = name
        self.age = age

    def __str__(self):
        return f"小狗的名字是{self.name},年龄是{self.age}"

    def __del__(self):
        print(f"我是__del__方法,我被调用了,{self.name}销毁了.....")


# 创建一个对象,每有一个对象就会调用一次,程序结束,会调用__del__方法
#dog = Dog('小黄',2)
#dog1 = Dog('小白',3)

# 引用计数为0会立即调用
dog = Dog('小花',4)   # 此时dog变量引用了对象,引用计数为1
dog2 = dog  # 此时dog2变量和dog变量都指向了对象,引用计数为2
print('第一次删除之前')
del dog # dog 变量不能使用,小花引用计数变为1
print('第一次删除之后')
print('第二次删除之前')
del dog2 # dog2 变量不能使用,小花引用计数变为0,会立即调用__del__方法
print('第二次删除之后')

四. __repr__()

"""
__repr__()
调用时机:
    将对象存入列表(容器)中,直接打印列表
注意点:
    1. 方法必须返回一个字符串,此方法通常只有 self 一个参数
    2. 和__str__不同的就是,__str__是在打印对象时输出,而__repr__是把对象放在列表(容器)中,然后打印列表输出的
"""

my_list = ['hello', 'python', 'cpp']  # 列表中存储了三个字符串对象

# 因为字符串也是对象,但是使用print时,并没有打印内存地址
print(my_list)


class Dog(object):
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def __str__(self):
        return f'{self.name},{self.age}'

    def __repr__(self):
        """
        repr方法和str方法非常类似, 也是必须返回一个字符串
        """
        return f'{self.name}'


my_list1 = [Dog("大黄", 2), Dog("小白", 4), Dog("小花", 6)]
# 但是自己定义后,打印列表,输出的是引用地址,这个时候,使用__repr__,在直接打印列表的时候,就会输出__repr__方法返回的字符串
print(my_list1)

dog = Dog("大黄", 2)
print(dog)

五. 使用案例

  • 烤地瓜
# -*- coding: utf-8 -*-
# Niko create
"""
烤地瓜规则:
1. 地瓜有自己的状态,默认是生的,地瓜可以进行烧烤
2. 地瓜有自己烧烤的总时间,由每次烧烤的时间累加得出
3. 地瓜烧烤时,需要提供本次烧烤的时间
4. 地瓜烧烤时,地瓜状态随着烧烤总时间的变化而变化,0-3生的,3-6半生不熟.6-8熟了,>=8烤糊了
5. 输出地瓜信息时,可以显示地瓜的状态和烧烤的总时间


封装的小套路:
1. 根据文字的描述信息,确定对象,对象有什么,就是属性
2. 根据文字的描述信息,对象能干什么,就是方法
3. 根据文字的描述信息,确定方法怎么书写
"""


class Potato(object):
    def __init__(self):
        self.status = '生的'
        self.total_time = 0
        self.name_list = [] # 保存调料的列表

    def cook(self, time):
        # 计算总时间
        self.total_time += time
        # 修改地瓜的状态
        if self.total_time < 3:
            self.status = '生的'
        elif self.total_time < 6:
            self.status = '半生不熟'
        elif self.total_time < 8:
            self.status = '熟了'
        else:
            self.status = '烤糊了'

    def __str__(self):
        # 字符串,join(列表),将字符串添加到列表中的每个元素之间,组成新的字符串
        buf_list = ','.join(self.name_list)
        if self.name_list:
            return f'地瓜的状态为{self.status}>>>>烧烤总时间为{self.total_time}>>>>调料有{buf_list}'
        else:
            return f'地瓜的状态为{self.status}>>>>烧烤总时间为{self.total_time}>>>>没有添加调料'

    def add(self, name):
        self.name_list.append(name)


potato = Potato()
print(potato)
potato.add('油')
potato.cook(4)
potato.add('辣椒面')
print(potato)
potato.cook(3)
potato.add('孜然粉')
print(potato)
  • 搬家具
# -*- coding: utf-8 -*-
# Niko create
"""
搬家具规则:
1. 家具分不同的类型,并且占用不同的面积
2. 输出家具信息时,显示家具的类型和家具的占用面积
_____________________
3. 房子有自己的地址和占用面积
4. 房子可以添加家具,如果房子的剩余面积可以容纳家具,则提示家具添加成,否则提示失败
5. 输出房子信息时,可以显示房子的地址,占用面积,剩余面积
"""


# 定义家具类
class Furniture(object):
    def __init__(self, name, area):
        # 类型
        self.name = name
        # 面积
        self.area = area

    def __str__(self):
        return f'家具类型{self.name}>>>>占用面积{self.area}'


class House(object):
    def __init__(self, address, area):
        self.address = address
        self.h_area = area
        self.furniture_list = []
        self.free_area = area  # 房子的剩余面积

    def add_furniture(self, obj_furniture):
        """
        此方法用来添加家具
        obj_furniture 需要是一个对象
        """
        if self.free_area >= obj_furniture.area:
            self.furniture_list.append(obj_furniture.name)
            # 修改剩余面积
            self.free_area -= obj_furniture.area
            print(f'家具{obj_furniture.name}添加成功')
        else:
            print('添加失败,面积不够')


    def __str__(self):
        # 自定义家具类,将该类的对象添加到列表(容器)中,直接打印列表,显示的是 自定义对象的引用地址
        # furniture_list = [obj.name for obj in obj_furniture]
        # 上面直接在列表添加时,使用obj_furniture.name,就无需上面的列表推导式
        furniture_list = ",".join(self.furniture_list)
        if furniture_list:
            return f'房子的地址是{self.address}>>>>占用面积{self.h_area}>>>>剩余面积{self.free_area}>>>>家具有{furniture_list}'
        else:
            return f'房子的地址是{self.address}>>>>占用面积{self.h_area}>>>>剩余面积{self.free_area}>>>>没有家具'


# 创建家具对象
bad = Furniture('沙发',15)
computer = Furniture('i9-14750F-GTX4090',5)
table = Furniture('桌子',2)

# 创建房子对象
zhang_house = House('海淀',20)

# 添加家具,输出已经添加好的家具和剩余面积
zhang_house.add_furniture(bad)
zhang_house.add_furniture(computer)
zhang_house.add_furniture(table)
print(zhang_house.free_area)
print(zhang_house.furniture_list)

# 输出家具和房子的信息
print(bad)
print(computer)
print(table)
print(zhang_house)
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Python类的常用魔法方法 的相关文章

随机推荐

  • Centos7下httpd最新版本安装或者更新至最新版本

    查找Centos上软件库里的httpd版本 yum info httpd yum info httpd 已加载插件 xff1a fastestmirror Loading mirror speeds from cached hostfile
  • 修改git远程仓库地址

    由于git仓库的地址发生了变化 xff0c 需要修改仓库地址才能push 查看本地工程git仓库关联的远程仓库地址 xff1a span class token function git span remote v 删除本地关联的远程仓库地
  • INSTALL_FAILED_NO_MATCHING_ABIS 的解决办法

    在Android模拟器上安装apk的时候出现 xfeff xfeff INSTALL FAILED NO MATCHING ABIS 这个错误提示的解决办法 是由于使用了native libraries 该native libraries
  • IntelliJ IDEA 控制台中文乱码

    1 预热 刚刚接触IntelliJ IDEA几天 xff0c 在易用性方面的确比Eclipse好很多 xff0c 比较智能 xff0c 各种插件 工具都已经集成 xff0c 和Mac OS X类似 开箱即用 但是还是老大难问题 中文乱码 x
  • unable to start the monitor on 4454 ,an other instance is problaly using the same port

    在打开idea studio后 xff0c 再打开android studio xff0c 或者反过来 xff0c 打开项目的时候就会报 xff1a unable to start the monitor on 4454 xff0c an
  • windows中为cmd设置代理

    在CMD环境下设置代理可能不是很常用 xff0c 但是某些情况下还是可能会用到 xff0c 比如有些资源网站被墙了 xff0c 此时你如果想访问这些资源时 xff0c 只能通过代理来访问相应的资源 xff0c 而你需要在CMD环境下下载墙外
  • version `GLIBCXX_3.4.21' not found 解决办法

    在安装cmake3 5 1运行 bootstrap的时候出现如下提示 xff1a gmake cmake 是最新的 span class hljs header usr soft cmake 3 5 1 Bootstrap cmk cmak
  • Oracle死锁查询及处理

    一 数据库死锁的现象 程序在执行的过程中 xff0c 点击确定或保存按钮 xff0c 程序没有响应 xff0c 也没有出现报错 二 死锁的原理 当对于数据库某个表的某一列做更新或删除等操作 xff0c 执行完毕后该条语句不提 交 xff0c
  • Ubuntu 18.04添加中文输入法

    找到设置 xff1a 点击 Manager Installed Languages 出现下图提示 xff1a Keyboard input method system 里面有Ibus XIM fcitx none 三种输入架构 xff0c
  • KEIL问题【打开文件太多造成任何按钮都不可点】【Keil4 编译时出现RL-ARM is not allowed with this license 】【 局部变量仿真显示not in scope】

    SYD8801是一款低功耗高性能蓝牙低功耗SOC xff0c 集成了高性能2 4GHz射频收发机 32位ARM Cortex M0处理器 128kB Flash存储器 以及丰富的数字接口 SYD8801片上集成了Balun无需阻抗匹配网络
  • Django(2)模板、标签

    文章目录 一 使用Django模板修改页面二 Django模板标签 变量 列表 字典 过滤器1 default2 length3 filesizeformat4 date5 truncatechars6 safe if else标签 for
  • Django(3)模型

    文章目录 一 Django 模型 ORM二 数据库配置三 定义模型 xff08 创建数据表 xff09 四 数据库基本操作 插入数据 获取数据 xff08 1 xff09 查询所有的数据行 xff08 2 xff09 where条件查询 x
  • Django(4)表单

    文章目录 一 概述二 GET方法三 POST方法四 Request对象五 QueryDict对象 此文章参考菜鸟教程 xff1a Django 表单 菜鸟教程 runoob com Django版本 xff1a span class tok
  • Django(5)视图

    文章目录 一 视图概述二 请求对象HttpRequest xff08 1 xff09 GET xff08 2 xff09 POST xff08 3 xff09 body xff08 4 xff09 path xff08 5 xff09 me
  • Django(6)路由

    文章目录 一 路由概述二 正则路径中的分组 xff08 1 xff09 正则路径中的无名分组 xff08 2 xff09 正则路径中的有名分组 xff08 3 xff09 路由分发 三 反向解析 xff08 使用reverse xff09
  • Django(7)Admin管理工具

    文章目录 一 概述二 使用管理工具 xff08 1 xff09 激活管理工具 xff08 2 xff09 使用管理工具 xff08 3 xff09 复杂模型 xff08 4 xff09 自定义表单 xff08 5 xff09 内联 xff0
  • Django(8)ORM单表实例

    文章目录 一 Django ORM 单表实例创建新模型 二 数据库操作 xff08 1 xff09 添加数据 xff08 2 xff09 查找数据 filter exclude get order by reverse count firs
  • Django(9)ORM多表实例

    文章目录 一 Django ORM 多表实例创建模型插入数据 二 ORM 插入数据一对多 外键 ForeignKey多对多 xff08 Many ToManyField xff09 xff1a 在第三张表添加数据 三 关联管理器 对象调用1
  • Django(10)ORM聚合查询

    文章目录 一 聚合查询 aggregate 二 分组查询 annotate 三 F 查询四 Q 查询 此文章参考菜鸟教程 xff1a Django ORM 多表实例 xff08 聚合与分组查询 xff09 菜鸟教程 runoob com D
  • Python类的常用魔法方法

    文章目录 一 96 init 96 二 96 str 96 三 96 del 96 四 96 repr 96 五 使用案例 一 init span class token comment 在Python类中 有一类方法 这类方法以 两个下划