python中MethodType的用法詳解
阿新 • • 發佈:2018-12-25
MethodType可以把外部函式(方法)繫結到類或類的例項中
而python2跟python3中MethodType的用法不盡相同,下面是它們的區別:
python2:
公共部分:
class Student(object):
pass
def set_name(self, name):
self.name = name
(1)把方法繫結到類的例項中:
s1 = Student() s2 = Student() s3 = Student() #將方法繫結到s1和s2例項中 s1.set_name = MethodType(set_name, s1, Student) s2.set_name = MethodType(set_name, s2, Student) #使用剛繫結的方法 s1.set_name('s1') s2.set_name('s2') #輸出 print(s1.name)#s1 print(s2.name)#s2 print(s3.name)#報錯:'Student' object has no attribute 'name'
(2)把方法繫結到類中(無None引數)
s1 = Student()
s2 = Student()
s3 = Student()
#將方法繫結到類中(沒有None引數)
Student.set_name = MethodType(set_name,Student)
s1.set_name('s1')
s2.set_name('s2')
#輸出
print(s1.name)#s2
print(s2.name)#s2
print(s3.name)#s2
MethodType把方法繫結在類上並且沒有None引數時,通過該類建立的例項的該方法都會指向相同的區域,相當於Java或C++中的static方法,導致後面s2例項的值會覆蓋前面s1例項的值,即使s3沒有使用該方法也會帶上s2值。
(3)把方法繫結到類中(有第二個引數None)
s1 = Student()
s2 = Student()
s3 = Student()
#將方法繫結到類上(注意第二個引數多了None)
Student.set_name = MethodType(set_name,None,Student)
s1.set_name('s1')
s2.set_name('s2')
#輸出
print(s1.name)#s1
print(s2.name)#s2
print(s3.name)#報錯:'Student' object has no attribute 'name'
MethodType把方法繫結在類上且有第二個None引數時,相當於沒指定給哪個例項繫結此方法,則預設為該類的全部例項都繫結上此方法。這種情況下和繫結到例項上效果一樣,通過該類建立的例項會指向各自不同的區域,各個例項之間的方法和name屬性互不干擾。
python3:
公共部分:
class Student(object):
pass
def set_name(self, name):
self.name = name
(1)把方法繫結到類的例項中:
s1 = Student()
s2 = Student()
s3 = Student()
#分別給s1和s2例項繫結此方法
s1.set_name = MethodType(set_name, s1)#跟2版本相比變成兩個引數,即去掉了後面的所屬類引數
s2.set_name = MethodType(set_name, s2)
s1.set_name('s1')
s2.set_name('s2')
print(s1.name)#s1
print(s2.name)#s2
print(s3.name)#報錯:AttributeError: 'Student' object has no attribute 'name'
注意:與python2相比MethodType()只接收兩個引數,即去掉了所屬類的引數。也就沒有為全部例項繫結該方法的情況了
(2)把方法繫結到類中(情況只有一種了,如上面python2的沒有None引數)
s1 = Student()
s2 = Student()
s3 = Student()
#將方法繫結到類上
Student.set_name = MethodType(set_name,Student)
s1.set_name('s1')
s2.set_name('s2')
print(s1.name)#s2
print(s2.name)#s2
print(s3.name)#s2
如果類本身也有其它設定name屬性的方法呢?
把公共部分改成如下:
class Student(object):
def set_name_self(self,name):
self.name = name
pass
def set_name(self, name):
self.name = name
即增加了類本身的設定name屬性的方法set_name_self
s1 = Student()
s2 = Student()
s3 = Student()
#將方法繫結到類中
Student.set_name = MethodType(set_name,Student)
s1.set_name_self('s1_self')
s2.set_name('s2')
s2.set_name_self('s2_self')
print(s1.name)#s1_self
print(s2.name)#s2_self
print(s3.name)#s2
s1先呼叫類本身的方法賦值's1_self',後s2呼叫的set_name並沒有覆蓋掉s1中name屬性的值,而s2的set_name_self把s2第一次呼叫的set_name為name屬性設定的值給覆蓋掉了,s3沒有為name設值,而因為s2.set_name方法是類方法,因而s3的name也是s2