为什么Python自定义类的方法调用时会自动传入实例作为参数?
问题原因
这不是Python 3.9版本的bug,是Python面向对象语法的固有设计:类的实例方法被调用时,会自动将当前调用方法的实例对象作为第一个参数传入方法,这个规则从Python早期版本就一直存在,你之前没遇到大概率是之前写实例方法时都规范预留了第一个参数接收实例(约定俗成命名为self),没有感知到这个机制。
你现有代码的错误点如下:
- 所有实例方法都没有预留第一个参数接收自动传入的实例,导致你定义的参数列表和实际传入的参数数量不匹配
__str__方法无参数定义,实际调用时会因为自动传入实例导致参数数量不符报错;同时方法内直接访问name/weapon等变量属于访问局部变量,无法读取到绑定在实例上的属性- 实例化时笔误:你定义的类名为
cat_test_class,但实例化代码写的是cat(),运行会提示类不存在 test(*args)没有预留实例接收参数,导致args的第一个元素永远是实例对象,和你手动传入的参数混在一起try_dis(args)的args实际接收到的就是自动传入的实例,所以返回值就是实例本身,和你测试3的结果完全吻合
修复方案
方案1:保留实例方法特性,规范添加self参数
修复后的完整类代码如下:
class cat_test_class(): def __init__(self, hat=None, gear=None, weapon=None, name="Kit"): # self接收自动传入的实例,属性绑定到self上才能被其他实例方法访问 self.hat = hat self.gear = gear self.weapon = weapon self.name = name def __str__(self): # 访问实例属性需要加self前缀 return f"{self.name}'s equipment:\nWeapon = {self.weapon}\nGear = {self.gear}\nHat = {self.hat}" def test(self, *args): # self接收实例,后续args才是你手动传入的参数 print(f"# of args: {len(args)} \n {args}") def try_dis(self): # 按需返回实例属性或整个实例即可 return self
修复后的测试效果:
- 调用
kitteh = cat_test_class(hat="Platypus Controller",gear="Book of Wumbology",weapon="Bun Sword")可正常实例化 - 调用
kitteh.test("banana",26,"Mpaw3 player")会输出参数数量为3,对应你传入的三个参数 - 调用
print(kitteh)会直接输出你定义的装备信息字符串
方案2:不需要访问实例属性时,设为静态方法
如果某个方法不需要用到实例的任何属性,不想接收自动传入的self参数,可以添加@staticmethod装饰器声明为静态方法:
class cat_test_class(): # ... 其他方法不变 @staticmethod def static_test(*args): print(f"# of args: {len(args)} \n {args}")
此时调用kitteh.static_test("banana",26,"Mpaw3 player")不会自动传入实例,参数数量为3,和普通函数行为完全一致。
内容的提问来源于stack exchange,提问作者Zach .N
相关产品推荐
相关产品推荐

