Discuss / Python / 通过MethodType(方法,实例)绑定方法 和 通过函数set_name_(self, name)绑定实例的4种情况对比

通过MethodType(方法,实例)绑定方法 和 通过函数set_name_(self, name)绑定实例的4种情况对比

Topic source

对于类定义:

from types import MethodType
class Student(object):
    passdef set_name(self, name):
    self.name = name
#1 方案1a - 通过MethodType(方法,实例)绑定方法到实例,每次修改实例的属性值, 只影响本次修改实例的属性值,不影响类的属性及其他实例的属性值
s1 = Student()
s1.__dict__     #在绑定方法前,实例s1的dict为空{}
s1.f1 = MethodType(set_name, s1)        #通过MethodType绑定f1方法到实例s1
s1.__dict__     #在绑定方法后,实例s1的dict变为{'f1': <bound method set_name of <__main__.Student object at 0x地址>>}
s1.__dict__['f1'] == s1.f1      #无论s1实例是通过dict方式调用函数f1, 还是直接调用其实都一样
s1.f1('name_1')
s1.name     #输出'name_1'
#2 方案1b - 通过MethodType(方法,实例)绑定方法到类,任何1次修改类或实例的属性值, 都会影响类及所有实例的属性值
s1 = Student()
s2 = Student()
Student.f2 = MethodType(set_name_function, Student)     #通过MethodType绑定f2方法到类Student
s1.__dir__()        #Student类的实例s1, s2等都会自动继承方法f2
s1.f2('name_1') == s1.f2('name_1') == Student.f2('name_1')      #实际上无论是Student类,还是实例S1,S2调用的命令都是一样的
s1.f2('name_2')
s1.name     #所有Student类的实例及Student类本身的属性都会改变成一样的‘name_2’
s2.name     #输出'name_2'
Student.name        #输出'name_2'
#3 方案2a - 通过函数set_name_(self, name)绑定实例来修改实例的属性值,每次修改只影其函数self所对应的实例
s1 = Student()
s2 = Student()
s1.__dict__
s1.f3 = set_name       #通过函数直接指向实例s1,此处实际上不是绑定方法,只是传统的函数方法
s1.__dict__     #指向函数后,实例s1的dict变为{'f3': <function __main__.set_name(self, name)>},此处和方案1a不同,f3是function不是bound method
s1.f3('name_1')     #输出错误代码,set_name() missing 1 required positional argument: 'name'
s1.f3(self=s1, name='name_1') == set_name(self=s1, name='name_1')      #按照函数定义添加变量,在实例上运行函数f3和独立运行函数没区别
s1.name     #输出'name_1'
s1.f3(self=s2, name='name_2')       #也可以在实例s1上通过函数f3为实例s2修改属性,就是传统的函数方式
s2.name     #输出'name_2'
#4 方案2b - 通过函数set_name(self, name)来修改实例的属性值,如果使用类调用函数则修全部属性值,如果使用实例调用函数则仅修改实例的属性值
s1 = Student()
s2 = Student()
Student.f4 = set_name       #通过函数直接指向类Student,此处实际上不是绑定方法,只是传统的函数方法
Student.__dict__        #指向函数后,类Student的dict增加了'f4': <function __main__.set_name(self, name)>,此处f4是function不是bound method
s1.__dir__()        #类添加函数后,该类下的实例都会自动指向该函数后,也就是实例具备了该函数功能
Student.f4(Student, 'name_1')       #如果在类上调用函数f4,则修改类及实例全部数值
Student.name        #输出'name_1'
s1.name     #输出'name_1'
s2.name     #输出'name_1'

s1.f4('name_2')     #如果在实例上调用函数f4,只修改该实例的属性值
s1.name     #输出'name_2'
Student.name        #不变,输出'name_1'
s2.name     #不变,输出'name_1'

  • 1

Reply