前言
本篇记录了温习Python基础知识时针对类和实例的方法创建时遇到的问题
一、问题描述
Python是一种动态语言,在定义了class并且创建了一个class的实例之后,可以对该实例绑定任何的属性和方法。同样也可以对类进行属性和方法的绑定。但在运用不同方法对类或实例进行绑定时,遇到了一些小坑。主要是针对types
模块里MethodType
函数的理解、不同绑定方法原理解释。
二、实验实例及解释
1.公共代码
代码如下(示例):
class Student(object): #创建的类
pass
def set_age(self, age): #需要绑定的方法
self.age = age
2.使用MethodType(function, self)
给实例绑定方法
代码如下(示例):
from types import MethodType
s = Student() #创建一个实例
s.set_age = MethodType(set_age, s) #给实例绑定方法
s.set_age(25) #调用方法
s.age #返回25
但如果我们对类绑定方法呢?先同样使用MethodType
Student.set_age = MethodType(set_age, Student)
s1 = Student()
s2 = Student()
s3 = Student()
s1.set_age(25)
s2.set_age(15)
s1.age #返回15
s2.age #返回15
s3.age #返回15
出现了问题!此时三个实例的age属性都是15.原因在于,MethodType
的第二个参数是针对实例进行绑定方法的。此时Student不仅可以看作是s的class,可以看作是object的一个实例。MethodType
为Student这个实例绑上了一个方法,这个方法也可以被其子类的实例使用,但是创建了一个link指向外部的方法,在其实例调用时修改的都是同一内存。也就是说,我们以为修改的age属性,都是在修改Student的一个属性(Student.age),s这些实例的属性也是指向这个内存的。
3.直接把方法绑定到类
代码如下(示例):
Student.set_age = set_age
s1 = Student()
s2 = Student()
s3 = Student()
s1.set_age(25)
s2.set_age(15)
s1.age #返回25
s2.age #返回15
s3.age #AttributeError: 'Student' object has no attribute 'age'
此时,等价于创建Student这个class时内部定义了方法。
4. 扩展:类本身有设置age属性的方法
代码如下(示例):
class Student(object):
def set_age_self(self,age):
self.age = age
pass
def set_age(self, age):
self.age = age
s1 = Student()
s2 = Student()
s3 = Student()
Student.set_age = MethodType(set_age, Student)
s1.set_age_self(25)
s2.set_age(15)
s1.age #返回25
s2.age #返回15
s3.age #返回15
Student.age #返回15
可见,类内部定义的方法指向和通过MethodType
绑定的方法指向不是同一个位置!
s2.set_age_self(35)
s1.age #返回25
s2.age #返回35
s3.age #返回15
Student.age #返回15
总结
本文章记录了对类进行绑定方法遇到的一些问题。总而言之,MethodType
是对实例进行绑定方法,真正要对类绑定一个其实例都能使用(分别被各个实例分别互不干扰使用)的方法时,要么在内部直接定义,要么在外部直接定义。