getattr 方法解析
생성일: 2025년 1월 18일
생성일: 2025년 1월 18일
class Demo(object):
def run(self, name, age):
return f"My name is {name}, age is {age}!"
aa = getattr(Demo, 'run')
print(aa)
bb = getattr(Demo(), 'run')
print(bb)
cc = getattr(Demo, 'run')(1, "dgw", "26")
print(cc)
dd = getattr(Demo(), 'run')("dgw", "26")
print(dd)
分别是什么意思?
下面我们逐行分析下这段代码做了什么,以及打印出来的结果分别代表了哪些含义。示例代码如下(做了些简化):
pythonclass Demo(object): def run(self, name, age): return f"My name is {name}, age is {age}!" aa = getattr(Demo, 'run') print(aa) bb = getattr(Demo(), 'run') print(bb) cc = getattr(Demo, 'run')(1, "dgw", "26") print(cc) dd = getattr(Demo(), 'run')("dgw", "26") print(dd)
aa = getattr(Demo, 'run')Demo.run 在 Python 3 中是一个「函数对象」(可以理解为没有绑定实例的函数),在 Python 2 里会显示为 unbound method,但在 Python 3 里仅仅是一个 function。aa 相当于拿到了 Demo 类里定义的 run 这个函数本身,但它没有和任何具体的实例绑定。print(aa) 输出时,通常会看到类似:
这说明它是一个函数对象。text<function Demo.run at 0x7f1234567890>
bb = getattr(Demo(), 'run')Demo() 先生成了一个 Demo 的实例。getattr(Demo(), 'run') 则相当于从实例上获取 run 方法。self 的方法,称为 bound method。bb 会是一个「绑定到 Demo() 这个对象」的函数引用。print(bb) 时会看到类似:
这说明它是绑定到某个具体对象的可调用方法。text<bound method Demo.run of <__main__.Demo object at 0x7f1234567890>>
cc = getattr(Demo, 'run')(1, "dgw", "26")getattr(Demo, 'run') 和第 1 步一样,得到的仍然是类上的函数对象(没有绑定实例)。(1, "dgw", "26")。def run(self, name, age): ... 的本质,是 run 函数的第一个参数要接收实例对象(即 self)。如果我们直接通过类拿到函数本身来调用,那么需要手动去提供 self。self = 1name = "dgw"age = "26"self 来操作属性(也没做其它类型检查),所以这个“1”作为 self 不会触发报错,依然可以正常返回字符串——只要里面不引用 self 的其他方法/属性就行。python"My name is dgw, age is 26!"
dd = getattr(Demo(), 'run')("dgw", "26")Demo() 生成一个 Demo 实例;getattr(Demo(), 'run') 相当于拿到这个实例已经绑定好的 run 方法(就跟上面 bb 一样)。self 以外的参数即可:
name = "dgw"age = "26"python"My name is dgw, age is 26!"
aa = getattr(Demo, 'run')
aa 只是一个函数引用。bb = getattr(Demo(), 'run')
cc = getattr(Demo, 'run')(1, "dgw", "26")
(self, name, age)。虽然看起来怪异,但因为函数内部没用 self 做特殊操作,所以不会报错,返回相同的字符串。dd = getattr(Demo(), 'run')("dgw", "26")
name 和 age 就可以调用,返回"My name is dgw, age is 26!"。这样就能清晰区分为什么会有“unbound function(或function)” 和 “bound method” 的区别,以及传参为什么会不一样。