Bound Method and Unbound Method - 绑定方法 与 非绑定方法
Bound Method and Unbound Method
通常有两种方法对类的方法(instance.method)/属性(class.attribute)进行引用, 一种称做 Bound Method,
即通过类的类的实例对象进行引用(instance.foo)。引用区别于调用, 引用为 instance.foo 返回的是方法对象
(PyFunctionObject/PyMethodObject); 而调用返回的是方法的运行结果。另一种引用形式叫做 Unboud Method,
是直接通过类进行属性引用, 即 class.foo 的形式进行引用。
在 python 中, Bound Method 和 Unbound Method 的本质区别在于 是否存在类的 instance 对象绑定到
PyFunctionObject 中(这里用 '中' 是想说明 PyFunctionObject 是一个结构体,我把它想象成一个容器的形象)。
因此, 在对 Unbound Method 进行调用的时候必须显式地传一个实例对象, 比如 class.UnboundMethod(instance),
所以说在类中所定义函数的第一个位置参数 self 代表是调用该函数的实例。 然而, 对 python 虚拟机来说, 无论是对
Bound Method 还是对 Unbound Method 进行调用, 其中本质上是一样的,都是调用带位置参数的普通函数。
其中的区别在于, 当调用 Bound Method 的时候,虚拟机自主完成了 instance 和 PyFunctionObject 的绑定;
而调用 Unbound Method 的时候虚拟机无法做绑定的动过,因而调用 Unbound Method 的时候需要显式地传入所属类的 instance.
对于通过 Bound Method 调用成员函数来说,每一次函数调用都会触发一次绑定过程。原因在于每次进行引用的时候都会重新获得
PyFunctionObject(description),进而新的 PyMethodObject 对象。
例子,
class A(object):
def foo(self):
print "haha - " + self.foo.__name__ print (A.__dict__) # abc = A() print (A.foo) # print(A.foo.im_self) # print (abc.foo) # print (abc.foo.im_self,abc.foo.im_func, #
abc.foo.im_class,abc.foo.__name__) abc.foo() #
try:
print A.foo() #
except TypeError as e:
print e A.foo(abc) #7
通过 dis 模块获取到示例代码的部分字节码,
31 LOAD_NAME 1 (A)
34 LOAD_ATTR 3 (foo)
37 PRINT_ITEM 其中关键在 '34 LOAD_ATTR' 指令一行, LOAD_ATTR 指令最终会调用 type_getattro。
而 type_getattro 会在 class A 对象的 tp_dict (__dict__ 属性) 中找到 function foo 对应的 PyFunctionObject.
因为 PyFunctionObject 是一个 descriptor,所以它会调用其 __get__ 函数. 最终,虽然 A.foo(class.foo, Unbound Method)
也得到了一个 PyMethodObject, 但是其中 im_self 属性却是 None. 示例代码的打印输出,
Output,
{... 'foo': <function foo at 0x00000000033A2D68>, '__weakref__': <attribute '__weakref__' of 'A' objects>, ...}
#1 type_getattro 会在 class A 对象的 tp_dict (__dict__ 属性) 中找到 function foo 对应的 PyFunctionObject.
<unbound method A.foo> #2 通过类的引用(class.foo) 为 Unbound Method
None #3 虽然 A.foo(class.foo, Unbound Method)也得到了一个 PyMethodObject, 但是其中 im_self 属性却是 None.
<bound method A.foo of <__main__.A object at 0x000000000330AE80>> #4 通过实例的引用(instance.foo) 为 Bound Method
(<__main__.A object at 0x000000000330AE80>, <function foo at 0x00000000033A2D68>, <class '__main__.A'>, 'foo')
#5 abc.foo(instance.foo, Bound Method)得到的 PyMethodObject 中 im_self 和 im_func 属性分别是 __main__.A 实例对象 和 foo 函数对象.
haha - foo #6 通过实例调用 foo
unbound method foo() must be called with A instance as first argument (got nothing instead) #7 Unbound Method 的调用需要显式地传入实例 instance 对象.
haha - foo
Bound Method and Unbound Method - 绑定方法 与 非绑定方法的更多相关文章
- Day 5-5 绑定方法与非绑定方法
绑定方法与非绑定方法: 在类内部定义的绑定方法,分两大类: classmehtod是给类用的,即绑定到类,类在使用时会将类本身当做参数传给类方法的第一个参数(即便是对象来调用也会将类当作第一个参数传入 ...
- Learning-Python【25】:绑定方法与非绑定方法
类中定义函数分为了两大类,绑定方法与非绑定方法,它们有一些特殊之处: 1.绑定方法特殊之处:绑定给谁就应该由谁来调用,谁来调用就会将谁当做第一个参数自动传入 绑定给对象的方法:这个在面向对象第一篇第六 ...
- Python面向对象之封装、property特性、绑定方法与非绑定方法
一.封装 ''' 1.什么封装 封:属性对外是隐藏的,但对内是开放的(对内是开放的是因为在类定义阶段这种隐藏已经发生改变) 装:申请一个名称空间,往里装入一系列名字/属性 2.为什么要封装 封装数据属 ...
- 全面解析python类的绑定方法与非绑定方法
类中的方法有两类: 绑定方法 非绑定方法 一.绑定方法 1.对象的绑定方法 首先我们明确一个知识点,凡是类中的方法或函数,默认情况下都是绑定给对象使用的.下面,我们通过实例,来慢慢解析绑定方法的应用. ...
- Python开发基础-Day21多态与多态性、绑定方法和非绑定方法
多态与多态性 多态 多态并不是一个新的知识 多态是指一类事物有多种形态,在类里就是指一个抽象类有多个子类,因而多态的概念依赖于继承 举个栗子:动物有多种形态,人.狗.猫.猪等,python的序列数据类 ...
- python基础之多态与多态性、绑定方法和非绑定方法
多态与多态性 多态 多态并不是一个新的知识 多态是指一类事物有多种形态,在类里就是指一个抽象类有多个子类,因而多态的概念依赖于继承 举个栗子:动物有多种形态,人.狗.猫.猪等,python的序列数据类 ...
- Python虚拟机类机制之绑定方法和非绑定方法(七)
Bound Method和Unbound Method 在Python中,当对作为属性的函数进行引用时,会有两种形式,一种称为Bound Method,这种形式是通过类的实例对象进行属性引用,而另一种 ...
- Python--多态与多态性、绑定方法与非绑定方法
多态与多态性 多态 多态指的是一类事物有多种形态,(一个抽象类有多个子类,因而多态的概念依赖于继承) 1. 序列类型有多种形态:字符串,列表,元组. s='hello' l=[,,] t=('a',' ...
- Day7 子类调用父类的方法supper 绑定方法与非绑定方法
supper:可以利用supper来重用父类的方法,可以不用指名道姓的调用了. class OldboyPeople: school = 'oldboy' def __init__(self,name ...
随机推荐
- 【转】推荐给初级Java程序员的3本进阶书
ImportNew 注: 原作者在这篇文章中介绍3本不错的技术书籍.作者认为这些书籍对新手或者学生而言尤其有帮助.通过一些基础性的教程入门后,我们可以使用Java做基础性的编程.然而,当我们需要从初级 ...
- 结巴分词 java 高性能实现,是 huaban jieba 速度的 2倍
Segment Segment 是基于结巴分词词库实现的更加灵活,高性能的 java 分词实现. 变更日志 创作目的 分词是做 NLP 相关工作,非常基础的一项功能. jieba-analysis 作 ...
- 解决el-tree lazy懒加载时,连续勾选前两个子节点后第二次进入默认选中时,将父节点也勾选的问题
在用到el-tree的懒加载和默认勾选功能时,若第一次勾选前几个连续节点,第二次进入默认勾选时,由于el-tree子节点尚未完全加载(只加载出来前几个),默认勾选已经开始(已加载出来的子节点被默认勾选 ...
- SpringSecurity 初始化流程源码
SpringSecurity 初始化流程源码 本篇主要讲解 SpringSecurity初始化流程的源码部分,包括核心的 springSecurityFilterChain 是如何创建的,以及在介绍哪 ...
- Python判断一个字符串是否包含某个指定的字符串
成员操作符 in str = "string test string test" find1 = "str" find2 = "test" ...
- HTTP图解笔记(六)—— 第6章 HTTP首部
前言 为啥第一章直接跳到第六章呢,因为...博主当初看书的时候挑着看..只看了第一章和第六章┗( ▔, ▔ )┛ HTTP图解对于不熟悉HTTP的小伙伴来说是很好的书籍,建议入手! 一. HTTP报文 ...
- Docker学习(九)Volumn容器间共享数据
Docker学习(九)Volumn容器间共享数据 volume是什么 volume在英文中是容量的意思, 在docker中是数据卷的意思,是用来保存数据的容器 为什么要进行数据共享 在集群中有多台to ...
- python 注册登录(文件操作)
name = input("请注册用户:") password = input("请注册密码:") with open(file="user" ...
- python sys.modules 和 sys.path 及 __name__
1.sys.modules 存放已经缓存的模块 值是dict 2.sys.path 搜索路径 值是list 3.if __name__= __main__ 可以看成python的程序入口,如果直接执行 ...
- SpringCloud Zipkin
原文地址:https://blog.csdn.net/z8414/article/details/78600646 Zipkin是一个链路跟踪工具,可以用来监控微服务集群中调用链路的通畅情况 前提:S ...