1. 程式人生 > >python中MethodType的用法詳解

python中MethodType的用法詳解

 

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