Python 面向对象高级编程 — 定制类一、整体思路铺垫Python 里以 **xxx**特殊方法 / 魔法方法本节核心给普通类添加魔法方法让自定义对象用起来像列表、字符串、函数一样灵活下面逐个讲解常用魔法方法作用、代码实例、理解思路、配套练习。二、1.__str__和__repr__控制对象打印内容1. 作用__str__给用户看print(对象)时自动执行自定义打印文本。__repr__给程序员调试看直接输入对象名回车时自动执行。不定义这两个方法打印对象只会显示内存地址看不懂内容。2. 基础思路不写魔法方法打印对象 → 输出内存地址不友好只写__str__print()正常显示直接写对象名还是地址偷懒写法__repr__ __str__让两个方法共用一套代码3. 完整实例# 定义学生类 class Student: def __init__(self, name, age):#__init__ 是类的【初始化函数 / 构造方法】专门用来创建对象的时 #候自动给对象绑定属性、初始化数据。 self.name name self.age age # 给 print() 使用 def __str__(self): return f学生姓名{self.name}年龄{self.age} # 调试使用和 __str__ 共用代码 __repr__ __str__ # 测试 s Student(小明, 18) print(s) # 触发 __str__ s # 交互式终端直接写对象触发 __repr__4. 练习题题目定义一个Book类属性有书名、作者。实现__str__和__repr__打印格式为书名Python入门作者廖雪峰。##代码✅️ # 题目**定义一个 Book 类属性有书名、作者。实现 __str__ 和 __repr__打印格式为书名Python入门作者廖雪峰。 class Book: def __init__(self,book_title,book_author): self._book_title book_title self._book_author book_author def __str__(self): return f书名{self._book_title}作者{self._book_author} __repr__ __str__ book1Book(python入门,廖雪峰) print(book1)##代码 豆包 class Book: def __init__(self, title, author): self.title title self.author author def __str__(self): return f书名{self.title}作者{self.author} __repr__ __str__ b Book(Python入门, 廖雪峰) print(b)分割线理解__str__一、一句话搞懂__str__到底干嘛的str就是自定义「打印对象时显示什么文字」默认情况下你打印一个对象Python 不知道你想看到什么只能给你一串看不懂的内存地址写了__str__告诉 Python打印这个对象时输出我指定的通俗易懂内容二、没有str的后果反面例子class Student(object): def __init__(self, name): self.name name s Student(小明) print(s)__main__.Student object at 0x...✅ 问题全是机器地址人类完全看不懂对象存了什么数据三、加了str之后正面例子class Student(object): def __init__(self, name): self.name name # 专门给 print() 用的自定义打印内容 def __str__(self): return f学生{self.name} s Student(小明) print(s)学生小明✅ 效果打印对象直接显示关键数据清晰易懂四、核心精髓必记触发时机只要你执行print(对象)自动触发__str__作用美化、自定义对象的打印结果返回值必须返回字符串只给用户看面向使用者的友好展示五、顺带区分你容易混淆的点__str__→print(对象)用给普通用户看__repr__→ 终端直接敲对象名用给程序员调试看日常写代码只学str就够用 90% 的场景分割线理解print与__str__print () 函数的内部逻辑自带了一个固定步骤打印对象前先自动执行对象的str方法。通俗大白话类比print是老板__str__是员工老板print要输出内容固定流程必须先喊员工__str__不是员工权力比老板大是老板的规则里必须调用这个员工。分割线三、2.__iter____next__让对象支持 for 循环1. 作用普通自定义对象不能直接放在 for 变量 in 对象实现这两个方法就能像列表、元组一样被for__iter__返回迭代对象一般返回自身self__next__每次循环取出下一个值循环结束抛出StopIteration异常分割线理解iter 大白话比喻for循环 自动拿东西的机器__iter__告诉 Python我这个对象可以被循环遍历没有__iter__for有了__iter__for2. 思路以斐波那契数列1,1,2,3,5,8…为例初始化两个变量保存数列前两位__iter__返回自己告诉 Python 这是可迭代对象__next__计算下一个数设置终止条件超范围就停止循环3. 完整实例class Fib: def __init__(self): # 初始化斐波那契前两个数 self.a, self.b 0, 1 # 返回迭代对象 def __iter__(self): return self # 取出循环的下一个值 def __next__(self): # 计算下一个数 self.a, self.b self.b, self.a self.b # 终止条件数值大于100就停止循环 if self.a 100: raise StopIteration() return self.a # 遍历自定义对象 for num in Fib(): print(num, end )4. 练习题题目创建一个Count类实现for循环遍历依次输出 1~20 的数字。##代码✅️ # 题目**创建一个 Count 类实现 for 循环遍历依次输出 1~20 的数字。 class Count: def __init__(self): self.count 0 def __str__(self): return str(self.count) # 少写了iter for循环不认识 def __iter__(self): return self def __next__(self): self.count 1 if self.count 20:#不是大于等于20 会漏掉20应该是大于20 raise StopIteration return self.count for i in Count(): print(i)#代码 豆包 class Count: def __init__(self): self.num 0 def __iter__(self): return self def __next__(self): self.num 1 if self.num 20: raise StopIteration() return self.num for i in Count(): print(i, end )四、3.__getitem__让对象支持下标 / 切片取值1. 作用实现后对象可以像列表一样用对象[索引]取单个元素用对象[起始:结束]做切片分割线理解__getitem__ 大白话比喻列表list能list[0]取值你的对象本来不行写了__getitem__→你的对象瞬间拥有了列表的下标功能分割线切片的规则规则1 包前不包后 [起始:结束] 是取下标 ≥起始 且 下标 结束包前不包后。 [0,5],取 列表[0]-列表[5] 即 列表[0] 列表[1] 列表[2] 列表[3] 列表[4] 因为包前不包后 所以不包含列表[5]规则2 开头不写默认从 0 开始 [:5] [0:5] 意思从最开头取到 5规则3 结尾不写默认取到最后 [2:] 意思从 2 开始取到完规则4 两个都不写就是全部 [:] 意思取所有数字切片的例子c[0:5]→ 取0~4c[:5]→ 取 开头~4c[2:]→ 取2 ~最后c[:]→ 取全部2. 思路__getitem__(self, n)里的参数n分两种情况n是整数代表索引按位置取值n是切片对象 (slice)代表[x:y]切片遍历拼接列表返回3. 完整实例斐波那契数列升级版class Fib: def __getitem__(self, n): # 情况1传入整数索引 if isinstance(n, int): ##isinstance( 要判断的变量 , 类型 ) a, b 1, 1 for _ in range(n): a, b b, a b return a # 情况2传入切片 if isinstance(n, slice):##isinstance( 要判断的变量 , 类型 ) start n.start stop n.stop # 切片没写起始默认从0开始 if start is None: start 0 a, b 1, 1 res [] for x in range(stop): if x start: res.append(a) a, b b, a b return res # 测试 f Fib() print(f[0]) # 索引取值 print(f[1:6]) # 切片取值4. 练习题题目改造上面的Count类实现__getitem__支持下标取值和切片模拟 1~30 的数字序列。##代码 ✅️ # # 题目**创建一个 Count 类实现 for 循环遍历依次输出 1~20 的数字。 # 题目**改造上面的 Count 类实现 __getitem__支持下标取值和切片模拟 1~30 的数字序列。 class Count: def __init__(self): self.count 0 def __str__(self): return str(self.count) # 少写了iter for循环不认识 def __iter__(self): return self def __next__(self): self.count 1 if self.count 20: # 不是大于等于20 会漏掉20应该是大于20 raise StopIteration return self.count # 新增下标取值 ## 注释 __getitem__ 就是专门处理下标取值 切片取值的方法 def __getitem__(self, item):## item可能是下标 也可能是切片 ##取整数 if isinstance(item, int): return item1 ##取切片 if isinstance(item, slice): #slice 切片 startitem.start or 0 # 结束位置没写就用 30模拟1~30 stopitem.stop or 30 # 结束位置没写就用 30模拟1~30 result[] ## 创建一个列表 for i in range(start,stop): # 循环生成一段数字 result.append(i1) return result # 测试输出 1~20 for num in Count(): print(num)#代码 豆包 class Count: def __getitem__(self, n): if isinstance(n, int): # 索引从0开始对应数字1 return n 1 if isinstance(n, slice): start n.start if n.start else 0 stop n.stop res [] for i in range(start, stop): res.append(i 1) return res c Count() print(c[5]) print(c[2:8])注释#注释1下标从 0 开始 → 通过公式 n 1 → 生成数字 1~3#注释2切片 从一堆数字里截取【一段】出来下标取值拿一个数字 →c[5]切片拿一整段数字 →c[0:5]五、4.__getattr__动态处理不存在的属性1. 作用当你调用对象不存在的属性 / 方法时Python 会自动执行__getattr__不会直接报错可以动态返回内容。注意已有属性不会触发只处理不存在的属性。2. 思路正常属性直接使用不进这个方法访问不存在属性 → 进入__getattr__(self, 属性名)判断属性名返回对应值 / 函数不匹配就主动抛AttributeError模拟原生报错分割线理解getattr__一句话总结当你访问一个 “不存在的属性” 时Python 会自动调用getattr方法。## 例子 class Person: def __init__(self): self.name 小明 # 访问不存在的属性时自动触发这里 def __getattr__(self, item): return f你访问的 {item} 属性不存在 p Person() print(p.name) # 正常 print(p.age) # 不存在 → 自动走 __getattr__ print(p.abc) # 不存在 → 自动走 __getattr__3. 基础实例class Student: def __init__(self): self.name 小红 # 处理不存在的属性 def __getattr__(self, attr): # 判断属性名 if attr score: return 95 if attr age: # 返回函数 return lambda: 20 # 不匹配的属性抛出标准错误 raise AttributeError(f没有属性{attr}) # 测试 s Student() print(s.name) # 已有属性正常使用 print(s.score) # 不存在属性触发 __getattr__ print(s.age()) # 调用返回的函数 # print(s.height) # 会报错4. 进阶实战链式调用 URL利用__getattr__实现 API 路径拼接这是实际开发常用场景class Chain: def __init__(self, path): self._path path def __getattr__(self, name): # 拼接路径返回新对象实现链式调用 return Chain(f{self._path}/{name}) def __str__(self): return self._path __repr__ __str__ # 链式调用拼接URL print(Chain().user.info.address) # 输出/user/info/address5. 练习题题目定义Person类已有属性name。当访问不存在的gender返回女访问height返回函数返回 165其他属性正常报错。##代码 # 题目**定义 Person 类已有属性 name。当访问不存在的 gender 返回 女访问 height 返回函数返回 165其他属性正常报错。 class Person: def __init__(self, name): self.name name def __getattr__(self, item): if item gender: return 女 if item height: # return 165 错误点❌️访问 height 返回函数返回 165我返回了字符串‘165’ def func(): return 165 return func # else: #其他属性 # return f{item}属性不存在 raise AttributeError(f{item}属性不存在) p Person(xiaoming) print(p.name) print(p.gender) print(p.height())#代码 豆包 class Person: def __init__(self): self.name 丽丽 def __getattr__(self, attr): if attr gender: return 女 if attr height: return lambda: 165 raise AttributeError(f无属性 {attr}) p Person() print(p.name) print(p.gender) print(p.height())六、5.__call__让对象像函数一样直接调用1. 作用普通对象只能调用对象.方法()定义 后可以直接写 把。搭配callable()函数判断一个东西是否能被()调用可调用对象。2. 思路在类中定义def __call__(self, 可选参数)实例化对象后直接对象(参数)就会触发该方法分割线理解__call__call让一个对象能像函数一样加括号 () 调用你创建了一个对象本来只能这样用p Person() p.属性 p.方法()但有了__call__你可以直接把对象当函数用p() # 加括号就能跑这就是 __call__ 的作用3. 完整实例#代码 豆包 class Student: def __init__(self, name): self.name name # 对象被直接调用时执行 def __call__(self, msg你好): print(f我是{self.name}{msg}) # 测试 s Student(小华) s() # 无参调用 s(加油学习) # 传参调用 # 判断是否为可调用对象 print(callable(s)) # True 对象可调用 print(callable([1,2]))# False 列表不能被()调用4. 练习题题目定义Dog类初始化传入狗狗名字。实现__call__调用dog()时输出狗狗名字 汪汪叫。# 题目**定义 Dog 类初始化传入狗狗名字。实现 __call__调用 dog() 时输出 狗狗名字 汪汪叫。 class Dog: def __init__(self, name,): self.name name def __call__(self,msg汪汪叫): print(f{self.name}{msg}) dog1 Dog(小白) dog1()class Dog: def __init__(self, dog_name): self.dog_name dog_name def __call__(self): print(f{self.dog_name}汪汪叫) d Dog(旺财) d()分割线print用法一句话死记print (函数 / 方法 () ) → 只打印它 return 回来的内容如果这个方法没有写 returnPython 就默认返回None所以 print 就打印 None七、整体知识点总结小白速记表格魔法方法核心作用使用场景__str__/__repr__自定义对象打印内容print(对象)、调试查看对象__iter____next__让对象支持 for 循环自定义可遍历序列__getitem__支持下标、切片取值模仿列表取值操作__getattr__动态处理不存在的属性链式调用、动态接口封装__call__对象像函数一样调用把对象当成函数使用核心逻辑魔法方法不用手动调用Python 在对应场景自动触发以此扩展类的功能。
python学习笔记 | 11.4、面向对象高级编程-定制类
发布时间:2026/6/3 19:04:37
Python 面向对象高级编程 — 定制类一、整体思路铺垫Python 里以 **xxx**特殊方法 / 魔法方法本节核心给普通类添加魔法方法让自定义对象用起来像列表、字符串、函数一样灵活下面逐个讲解常用魔法方法作用、代码实例、理解思路、配套练习。二、1.__str__和__repr__控制对象打印内容1. 作用__str__给用户看print(对象)时自动执行自定义打印文本。__repr__给程序员调试看直接输入对象名回车时自动执行。不定义这两个方法打印对象只会显示内存地址看不懂内容。2. 基础思路不写魔法方法打印对象 → 输出内存地址不友好只写__str__print()正常显示直接写对象名还是地址偷懒写法__repr__ __str__让两个方法共用一套代码3. 完整实例# 定义学生类 class Student: def __init__(self, name, age):#__init__ 是类的【初始化函数 / 构造方法】专门用来创建对象的时 #候自动给对象绑定属性、初始化数据。 self.name name self.age age # 给 print() 使用 def __str__(self): return f学生姓名{self.name}年龄{self.age} # 调试使用和 __str__ 共用代码 __repr__ __str__ # 测试 s Student(小明, 18) print(s) # 触发 __str__ s # 交互式终端直接写对象触发 __repr__4. 练习题题目定义一个Book类属性有书名、作者。实现__str__和__repr__打印格式为书名Python入门作者廖雪峰。##代码✅️ # 题目**定义一个 Book 类属性有书名、作者。实现 __str__ 和 __repr__打印格式为书名Python入门作者廖雪峰。 class Book: def __init__(self,book_title,book_author): self._book_title book_title self._book_author book_author def __str__(self): return f书名{self._book_title}作者{self._book_author} __repr__ __str__ book1Book(python入门,廖雪峰) print(book1)##代码 豆包 class Book: def __init__(self, title, author): self.title title self.author author def __str__(self): return f书名{self.title}作者{self.author} __repr__ __str__ b Book(Python入门, 廖雪峰) print(b)分割线理解__str__一、一句话搞懂__str__到底干嘛的str就是自定义「打印对象时显示什么文字」默认情况下你打印一个对象Python 不知道你想看到什么只能给你一串看不懂的内存地址写了__str__告诉 Python打印这个对象时输出我指定的通俗易懂内容二、没有str的后果反面例子class Student(object): def __init__(self, name): self.name name s Student(小明) print(s)__main__.Student object at 0x...✅ 问题全是机器地址人类完全看不懂对象存了什么数据三、加了str之后正面例子class Student(object): def __init__(self, name): self.name name # 专门给 print() 用的自定义打印内容 def __str__(self): return f学生{self.name} s Student(小明) print(s)学生小明✅ 效果打印对象直接显示关键数据清晰易懂四、核心精髓必记触发时机只要你执行print(对象)自动触发__str__作用美化、自定义对象的打印结果返回值必须返回字符串只给用户看面向使用者的友好展示五、顺带区分你容易混淆的点__str__→print(对象)用给普通用户看__repr__→ 终端直接敲对象名用给程序员调试看日常写代码只学str就够用 90% 的场景分割线理解print与__str__print () 函数的内部逻辑自带了一个固定步骤打印对象前先自动执行对象的str方法。通俗大白话类比print是老板__str__是员工老板print要输出内容固定流程必须先喊员工__str__不是员工权力比老板大是老板的规则里必须调用这个员工。分割线三、2.__iter____next__让对象支持 for 循环1. 作用普通自定义对象不能直接放在 for 变量 in 对象实现这两个方法就能像列表、元组一样被for__iter__返回迭代对象一般返回自身self__next__每次循环取出下一个值循环结束抛出StopIteration异常分割线理解iter 大白话比喻for循环 自动拿东西的机器__iter__告诉 Python我这个对象可以被循环遍历没有__iter__for有了__iter__for2. 思路以斐波那契数列1,1,2,3,5,8…为例初始化两个变量保存数列前两位__iter__返回自己告诉 Python 这是可迭代对象__next__计算下一个数设置终止条件超范围就停止循环3. 完整实例class Fib: def __init__(self): # 初始化斐波那契前两个数 self.a, self.b 0, 1 # 返回迭代对象 def __iter__(self): return self # 取出循环的下一个值 def __next__(self): # 计算下一个数 self.a, self.b self.b, self.a self.b # 终止条件数值大于100就停止循环 if self.a 100: raise StopIteration() return self.a # 遍历自定义对象 for num in Fib(): print(num, end )4. 练习题题目创建一个Count类实现for循环遍历依次输出 1~20 的数字。##代码✅️ # 题目**创建一个 Count 类实现 for 循环遍历依次输出 1~20 的数字。 class Count: def __init__(self): self.count 0 def __str__(self): return str(self.count) # 少写了iter for循环不认识 def __iter__(self): return self def __next__(self): self.count 1 if self.count 20:#不是大于等于20 会漏掉20应该是大于20 raise StopIteration return self.count for i in Count(): print(i)#代码 豆包 class Count: def __init__(self): self.num 0 def __iter__(self): return self def __next__(self): self.num 1 if self.num 20: raise StopIteration() return self.num for i in Count(): print(i, end )四、3.__getitem__让对象支持下标 / 切片取值1. 作用实现后对象可以像列表一样用对象[索引]取单个元素用对象[起始:结束]做切片分割线理解__getitem__ 大白话比喻列表list能list[0]取值你的对象本来不行写了__getitem__→你的对象瞬间拥有了列表的下标功能分割线切片的规则规则1 包前不包后 [起始:结束] 是取下标 ≥起始 且 下标 结束包前不包后。 [0,5],取 列表[0]-列表[5] 即 列表[0] 列表[1] 列表[2] 列表[3] 列表[4] 因为包前不包后 所以不包含列表[5]规则2 开头不写默认从 0 开始 [:5] [0:5] 意思从最开头取到 5规则3 结尾不写默认取到最后 [2:] 意思从 2 开始取到完规则4 两个都不写就是全部 [:] 意思取所有数字切片的例子c[0:5]→ 取0~4c[:5]→ 取 开头~4c[2:]→ 取2 ~最后c[:]→ 取全部2. 思路__getitem__(self, n)里的参数n分两种情况n是整数代表索引按位置取值n是切片对象 (slice)代表[x:y]切片遍历拼接列表返回3. 完整实例斐波那契数列升级版class Fib: def __getitem__(self, n): # 情况1传入整数索引 if isinstance(n, int): ##isinstance( 要判断的变量 , 类型 ) a, b 1, 1 for _ in range(n): a, b b, a b return a # 情况2传入切片 if isinstance(n, slice):##isinstance( 要判断的变量 , 类型 ) start n.start stop n.stop # 切片没写起始默认从0开始 if start is None: start 0 a, b 1, 1 res [] for x in range(stop): if x start: res.append(a) a, b b, a b return res # 测试 f Fib() print(f[0]) # 索引取值 print(f[1:6]) # 切片取值4. 练习题题目改造上面的Count类实现__getitem__支持下标取值和切片模拟 1~30 的数字序列。##代码 ✅️ # # 题目**创建一个 Count 类实现 for 循环遍历依次输出 1~20 的数字。 # 题目**改造上面的 Count 类实现 __getitem__支持下标取值和切片模拟 1~30 的数字序列。 class Count: def __init__(self): self.count 0 def __str__(self): return str(self.count) # 少写了iter for循环不认识 def __iter__(self): return self def __next__(self): self.count 1 if self.count 20: # 不是大于等于20 会漏掉20应该是大于20 raise StopIteration return self.count # 新增下标取值 ## 注释 __getitem__ 就是专门处理下标取值 切片取值的方法 def __getitem__(self, item):## item可能是下标 也可能是切片 ##取整数 if isinstance(item, int): return item1 ##取切片 if isinstance(item, slice): #slice 切片 startitem.start or 0 # 结束位置没写就用 30模拟1~30 stopitem.stop or 30 # 结束位置没写就用 30模拟1~30 result[] ## 创建一个列表 for i in range(start,stop): # 循环生成一段数字 result.append(i1) return result # 测试输出 1~20 for num in Count(): print(num)#代码 豆包 class Count: def __getitem__(self, n): if isinstance(n, int): # 索引从0开始对应数字1 return n 1 if isinstance(n, slice): start n.start if n.start else 0 stop n.stop res [] for i in range(start, stop): res.append(i 1) return res c Count() print(c[5]) print(c[2:8])注释#注释1下标从 0 开始 → 通过公式 n 1 → 生成数字 1~3#注释2切片 从一堆数字里截取【一段】出来下标取值拿一个数字 →c[5]切片拿一整段数字 →c[0:5]五、4.__getattr__动态处理不存在的属性1. 作用当你调用对象不存在的属性 / 方法时Python 会自动执行__getattr__不会直接报错可以动态返回内容。注意已有属性不会触发只处理不存在的属性。2. 思路正常属性直接使用不进这个方法访问不存在属性 → 进入__getattr__(self, 属性名)判断属性名返回对应值 / 函数不匹配就主动抛AttributeError模拟原生报错分割线理解getattr__一句话总结当你访问一个 “不存在的属性” 时Python 会自动调用getattr方法。## 例子 class Person: def __init__(self): self.name 小明 # 访问不存在的属性时自动触发这里 def __getattr__(self, item): return f你访问的 {item} 属性不存在 p Person() print(p.name) # 正常 print(p.age) # 不存在 → 自动走 __getattr__ print(p.abc) # 不存在 → 自动走 __getattr__3. 基础实例class Student: def __init__(self): self.name 小红 # 处理不存在的属性 def __getattr__(self, attr): # 判断属性名 if attr score: return 95 if attr age: # 返回函数 return lambda: 20 # 不匹配的属性抛出标准错误 raise AttributeError(f没有属性{attr}) # 测试 s Student() print(s.name) # 已有属性正常使用 print(s.score) # 不存在属性触发 __getattr__ print(s.age()) # 调用返回的函数 # print(s.height) # 会报错4. 进阶实战链式调用 URL利用__getattr__实现 API 路径拼接这是实际开发常用场景class Chain: def __init__(self, path): self._path path def __getattr__(self, name): # 拼接路径返回新对象实现链式调用 return Chain(f{self._path}/{name}) def __str__(self): return self._path __repr__ __str__ # 链式调用拼接URL print(Chain().user.info.address) # 输出/user/info/address5. 练习题题目定义Person类已有属性name。当访问不存在的gender返回女访问height返回函数返回 165其他属性正常报错。##代码 # 题目**定义 Person 类已有属性 name。当访问不存在的 gender 返回 女访问 height 返回函数返回 165其他属性正常报错。 class Person: def __init__(self, name): self.name name def __getattr__(self, item): if item gender: return 女 if item height: # return 165 错误点❌️访问 height 返回函数返回 165我返回了字符串‘165’ def func(): return 165 return func # else: #其他属性 # return f{item}属性不存在 raise AttributeError(f{item}属性不存在) p Person(xiaoming) print(p.name) print(p.gender) print(p.height())#代码 豆包 class Person: def __init__(self): self.name 丽丽 def __getattr__(self, attr): if attr gender: return 女 if attr height: return lambda: 165 raise AttributeError(f无属性 {attr}) p Person() print(p.name) print(p.gender) print(p.height())六、5.__call__让对象像函数一样直接调用1. 作用普通对象只能调用对象.方法()定义 后可以直接写 把。搭配callable()函数判断一个东西是否能被()调用可调用对象。2. 思路在类中定义def __call__(self, 可选参数)实例化对象后直接对象(参数)就会触发该方法分割线理解__call__call让一个对象能像函数一样加括号 () 调用你创建了一个对象本来只能这样用p Person() p.属性 p.方法()但有了__call__你可以直接把对象当函数用p() # 加括号就能跑这就是 __call__ 的作用3. 完整实例#代码 豆包 class Student: def __init__(self, name): self.name name # 对象被直接调用时执行 def __call__(self, msg你好): print(f我是{self.name}{msg}) # 测试 s Student(小华) s() # 无参调用 s(加油学习) # 传参调用 # 判断是否为可调用对象 print(callable(s)) # True 对象可调用 print(callable([1,2]))# False 列表不能被()调用4. 练习题题目定义Dog类初始化传入狗狗名字。实现__call__调用dog()时输出狗狗名字 汪汪叫。# 题目**定义 Dog 类初始化传入狗狗名字。实现 __call__调用 dog() 时输出 狗狗名字 汪汪叫。 class Dog: def __init__(self, name,): self.name name def __call__(self,msg汪汪叫): print(f{self.name}{msg}) dog1 Dog(小白) dog1()class Dog: def __init__(self, dog_name): self.dog_name dog_name def __call__(self): print(f{self.dog_name}汪汪叫) d Dog(旺财) d()分割线print用法一句话死记print (函数 / 方法 () ) → 只打印它 return 回来的内容如果这个方法没有写 returnPython 就默认返回None所以 print 就打印 None七、整体知识点总结小白速记表格魔法方法核心作用使用场景__str__/__repr__自定义对象打印内容print(对象)、调试查看对象__iter____next__让对象支持 for 循环自定义可遍历序列__getitem__支持下标、切片取值模仿列表取值操作__getattr__动态处理不存在的属性链式调用、动态接口封装__call__对象像函数一样调用把对象当成函数使用核心逻辑魔法方法不用手动调用Python 在对应场景自动触发以此扩展类的功能。