在 class 中定义的实例方法其实也是属性,它实际上是一个函数对象:
class Person(object):
def __init__(self, name, grade):
self.name = name
self.grade = grade
def get_grade(self):
return 'A'
p1 = Person('Bob', 90)
print(p1.get_grade())
结果为: A
若最后一行为
print(p1.get_grade)
则输出为:
<bound method Person.get_grade of <main.Person object at
0x00000000029CEE48>>
也就是说,p1.get_grade 返回的是一个函数对象,但这个函数是一个绑定到实例的函数,p1.get_grade() 才是方法调用。
因为方法也是一个属性,所以,它也可以动态地添加到实例上,只是需要用 types.MethodType() 把一个函数变为一个方法:
import types
def fn_get_grade(self):
if self.score >= 80:
return 'A'
if self.score >= 60:
return 'B'
return 'C'
class Person(object):
def __init__(self, name, score):
self.name = name
self.score = score
p1 = Person('Bob', 90)
p1.get_grade = types.MethodType(fn_get_grade, p1) #跟2版本相比变成两个参数,即去掉了后面的所属类参数
print(p1.get_grade())
结果为: A
若最后三行为 :
p2 = Person(‘Alice’, 65)
print p2.get_grade()
则输出为:
ERROR: AttributeError: ‘Person’ object has no attribute ‘get_grade’
因为p2实例并没有绑定get_grade
任务:
由于属性可以是普通的值对象,如 str,int 等,也可以是方法,还可以是函数,通过看下面代码的运行结果,回答p1.get_grade 为什么是函数而不是方法:
class Person(object):
def __init__(self, name, score):
self.name = name
self.score = score
self.get_grade = lambda: 'A'
p1 = Person('Bob', 90)
print(p1.get_grade)
print(p1.get_grade())
结果为:
<function Person.init.. at 0x0000000002A16620>
A
分析:
直接把 lambda 函数赋值给 self.get_grade 和绑定方法有所不同,函数调用不需要传入 self,但是方法调用需要传入 self。
大家加油!
学习链接:https://www.imooc.com/code/6178