9 func() 10 endtime = time.time() # 记录程序运行结束时间 11 print(endtime-start) # 打印程序运行时间 12 timer...9 func() 10 endtime = time.time() # 记录程序运行结束时间 11 print(endtime-start) # 打印程序运行时间 12 func...9 print(endtime-start) # 打印程序运行时间 10 return inner 11 @timer 12 # 被装饰函数 13 def func(): 14...(endtime-start) # 打印程序运行时间 10 return str 11 return inner 12 @timer 13 # 被装饰函数 14 def func...print(endtime-start) # 打印程序运行时间 10 return str 11 return inner 12 @timer 13 # 被装饰函数 14 def
我们来看下结果是几 哦豁,答案是12字节。 怎么回事?为什么是12呢?...所以多态时的函数调用就不是在编译期间就能确定要调用的函数了,而是在运行期间通对象里的虚函数指针找到虚表,然后确定要调用的具体函数。 那现在我们回过头来看多态的两个条件?为什么是它们两个?...那第二个为什么必须是父类的指针或引用去调用虚函数呢? 因为父类的指针和引用是不是既可以指向子类对象,也可以指向父类对象啊,我们之前学过,它支持赋值转换(切片)嘛。...但是int*解引用是个int,而形参本质是个函数指针,所以我们可以再强转一个 这样。 那我们运行试一下: 可以,我们看到Derive类对象里面就是有三个虚函数地址的。...我们看到,现在第一个位置确实不是之前的0了,大家看这个值转化成10进制是几? fffffffc,内存中是补码,转换为10进制是-4。 那这个数是干嘛的呢?
fn 是对象 a 调用的,所以打印的值就是 a 中的 name 的值。...function () { console.log(this.name); // windowsName } } var f = a.fn; f(); 这里你可能会有疑问,为什么不是...this 的指向并不是在创建的时候就可以确定的,在 es5 中,永远是this 永远指向最后调用它的那个对象。...中,首先设置 var _this = this;,这里的 this 是调用 func2 的对象 a,为了防止在 func2 中的 setTimeout 被 window 调用而导致的在 setTimeout...]) thisArg:在 fun 函数运行时指定的 this 值。
需要使用关键字的方式来指定参数 2. args指定的为传给target函数的位置参数,是一个元组形式,必须有逗号 参数介绍: 1 group参数未使用,值始终为None 2 target表示调用对象,... name为子进程的名称 方法介绍 1 p.start():启动进程,并调用该子进程中的p.run() 2 p.run():进程启动时运行的方法,正是它去调用target指定的函数,我们自定义类的类中一定要实现该方法...id号 time.sleep(10) # 延迟10秒 print(os.getppid()) # 打印父进程id号 p = Process(target=process1) # 实例化一个对象...id号, getppid父进程id号 time.sleep(10) # 延迟10秒 print(os.getpid()) # 打印进程id号 if __name__ == '__main...为什么会打印两次进程id号?
我们运行看看: 多态调用:运行时,到指定对象的虚表中找虚函数来调用(指向基类调用基类的虚函数,指向子类调用子类的虚函数) 普通调用:编译时,调用对象是哪个类型,就调用它的函数。...0; i< 100000 ; i++) { Person* p2 = new Student; delete p2; } return 0; } 如果我们在Student中申请一个空间,而析构的时候却不能调用其析构函数俩把申请的空间...在内存窗口里存在4个函数指针,接下来我们来验证一下他们是不是对应的虚函数。 虚函数表本质是一个函数指针数组! 那么如何定义一个函数指针和函数指针数组呢?...也很特别) typedef void(*VFPTR)(); VFPTR p1; VFPTR p2[10]; 那么如果我们想要打印出虚表,我们可以设置一个函数: //因为是函数指针数组,所以传参是函数指针的指针...所以应该是: 12 (B类) + 12(C类) + 8(A类的int)+ 4(D类的int) = 36 那为什么A会有一个虚表指针,而不是D类有!?
本文我将尝试说清楚为什么需要现装饰器、什么是装饰器、以及如何写一个简单的装饰器,但要彻底理解装饰器还要从函数开始说起,下面是有关函数的四个重要的概念,希望大家可以明白。...func2 >>> func2(func1,3,4) 函数 func2 正在执行 函数 func1 正在执行 7 可以看到,先执行func2,在func2接收到fun1后,再次执行func1并返回。...说明func2只能在func1中被调用!....func2(b)> >>> func3(2) 函数 func2 正在执行 3 从上面的运行结果可以看到,当执行func1(1)后,返回的是func2的地址,并赋给func3,之后执行...至此,我想你应该明白为什么需要现装饰器、什么是装饰器、以及如何写一个简单的装饰器,当你再次看到装饰器时,脑海中浮现的概念应该不仅仅是@。
为什么? 运行结果: 12 我们通过定义一个基类 Base 的对象,通过监视窗口来看看是什么情况: Base b; 咦,很奇怪是不是?...: A::fun() B::fun() 下图分别对三种情况进行解析: 接下来我们再来思考一个问题:为什么一定要求说要用父类的指针或引用去调用虚函数,而不是父类的对象?...void PrintVFT(VFunc* ptr) //这里ptr是个存函数指针的数组指针 { // 依次取虚表中的虚函数指针打印并调用。...void PrintVFT(VFunc* ptr) //这里ptr是个存函数指针的数组指针 { // 依次取虚表中的虚函数指针打印并调用。...,为了让其加上相隔的字节数,所以我们得将 &d 转化为 char*。
获取函数的堆栈跟踪信息 使用JavaScript框架,会引入大量代码。 创建视图并触发事件,最后你想了解函数调用的过程。...想象一下,要查看第24行 car实例调用函数 funcZ的整个堆栈跟踪信息: var car; var func1 = function() { func2(); } var func2 = function...可以看到 func1 调用 func2, func2 调用 func4。 Func4 创建了一个 Car 的实例,然后调用函数 car.funcX,依此类推。...(注意:这个函数和 console.debug函数不是同一个东西。)...观察特定函数的调用及参数 在Chrome控制台中,可以观察特定的函数。每次调用该函数,就会打印出传入的参数。
) ,如果没有发生多态的话,那么就会去看调用者的类型而不是去看指向对象的类型,从而导致指向对象没有被析构,造成内存泄露。...,而没有重写就失去了意义,最好的方法其实是让编译器对没重写的虚函数进行报错,但是之前在这方面没有去严格地限制说不重写就会报错,所以这边做了一个妥协就是你可以通过增加override来帮助你检查,防止你写漏...动态绑定又称后期绑定(晚绑定),是在程序运行期间,根据具体拿到的类型确定程序的具体行为,调用具体的函数,也称为动态多态(运行时)。...在某些函数必须出现在代码段(常量区)的时候,inline会妥协并失去作用 5. 静态成员可以是虚函数吗?...如果是父类指针对象或者是引用对象,则调用的普通函数快,因为构成多态,运行时调用虚函数需要到虚函数表中去查找。 10. 虚函数表是在什么阶段生成的,存在哪的?
那么大家想想为什么有人扫的红包又大又新鲜8块、10块…,而有人扫的红包都是1毛,5毛…。...,其实覆盖是底层实现上的理解,而重写是语义上的理解,我们在后面也会对其讲解 虚函数 虚函数:即被virtual修饰的类成员函数称为虚函数。...再通过下面的汇编代码分析,看出满足多态以后的函数调用,不是在编译时确定的,是运行起来以后到对象的中取找的。不满足多态的函数调用时编译时确认好的。...那么我们如何查看d的虚表呢?下面我们使用代码打印出虚表中的函数。...endl; } private: int b; }; typedef void(*VFPTR) (); void PrintVTable(VFPTR vTable[]) { // 依次取虚表中的虚函数指针打印并调用
10然后打印6,其实这里就是涉及到变量作用域的问题 当Python编译函数的的定义体的时候,它判断b是局部变量,毕竟在函数中有b = 9表示给b赋值了,所以python会从本地环境获取b,当我们调用方法执行的时候...,定义体会获取并打印变量a的值,但是当尝试获取b的值的时候发现b没有绑定值,所以要想让上述代码运行还可以把b设置为全局变量,或者把b赋值放到调用之前 函数对象的作用域 python中一切皆对象,同其他对象一样...,函数对象也有其使用的范围即函数对象的作用域。...x print(func2(5)) func1() print(func2(5)) 这个例子中我们在def func1函数内可以调用fun2,但是我们在外面是无法调用到func2的,所以结果为看到如下...avg(10)的时候make_averager函数已经返回了,而它的本地作用域也一去不复返,但这里其实series是自由变量,是指未在本地作用域绑定的变量 我们可以通过print(dir(avg)),看到如下结果
6 7 def func2(): 8 print(b) 9 # print(a) 10 11 func1() 12 func2() 上面这段代码虽然简单...,却可以很好的说明了函数作用域的问题,如上,如果注释掉函数func2的print(a)这一句,程序可以正常运行,但是如果加上这一句就出错,出错的原因是a没有定义,为什么b在两个函数中都可以引用,而a只能在...而b属于全局名称空间,属于全局变量,因此其可被func1和func2调用。...x = n 7 n += 1 8 return x 9 10 return func2 11 12 13 c = func1...func1里嵌套了一个函数func2,func2调用了func1的内部变量。
获取函数的堆栈跟踪信息 使用JavaScript框架,会引入大量代码。 创建视图并触发事件,最后你想了解函数调用的过程。...想象一下,要查看第24行car实例调用函数funcZ的整个堆栈跟踪信息: var car;var func1 = function() { func2();}var func2 = function()...可以看到 func1 调用 func2, func2 调用 func4。 Func4 创建了一个 Car 的实例,然后调用函数 car.funcX,依此类推。...(注意:这个函数和console.debug函数不是同一个东西。)...观察特定函数的调用及参数 在Chrome控制台中,可以观察特定的函数。每次调用该函数,就会打印出传入的参数。
把一个函数名当做实参传给另外一个函数(不修改被装饰的函数源代码的情况下为其添加功能) 2.2 返回值中包含函数名 ? 运行结果: ?...把函数内存地址都打印出来了,看到这么多内存地址,有什么想法? 加上小括号就能运行。 上面代码“test2(func2())” 和 “test2(func2)”有什么区别?...加上小括号是函数返回结果,不加是函数内存地址。所以加上小括号就不符合高阶函数定义了。 既然以后有了函数的内存地址,是不是可以赋值给其他变量? ? 好像还没什么用,怎么让他有用呢?...把test2(func2)赋值给func2 ? 这就是高阶函数的第二个好处:返回值中包含函数名(不修改函数的调用方式) ---- 3....别忘记了,第二种方式,高阶函数要加上return,如下 ? 虽然没有修改源代码和调用方式,但是函数加上return,函数就结束了,然并卵。怎么实现呢?
wan() 3.准备开始执行函数 4.打印,今天一起去玩 5.打印,去哪里完 6.打印,我不知道 7.函数执行完毕,本次调用完毕,wan()函数调用完毕 '''...("hahaha") # func2(func1,func) # 我是func2 # 我是func1 # 我是func # hahaha #解释:首先执行func2函数,有两个实参传递给形参,打印我是func2...,然后使用inner()调用 # print(func) # ret = func() # ret() # func()() #先运行func() 然后再返回值上加() 六.函数的嵌套 1.主要遇见()...fun5,打印二哈,接着调用fun1,打印蒋小雨,然后调用fun3的函数,打印张冲 #接着执行下面函数体代码块,调用fun4,打印龙大队,接着调用fun2打印鲁炎 七.命名空间 把存放名字和值的关系的空间叫做命名空间...outer()函数更改为20,然后再调用outer_2函数打印30 # 这样就会出现哪个先调用就执行那个,所以改来改去是很混乱的 # def outer(): # a = 10
另外Func2继承下来后是虚函数,所以放进了虚表,Func1也继承下来了,但是不是虚函 数,所以不会放进虚表。 4....满足多态以后的函数调用,不是在编译时确定的,是运行起来以后到对象的中取找的。不满足多态的函数调用时编译时确认好的。 4.3 动态绑定与静态绑定 1....动态绑定又称后期绑定(晚绑定),是在程序运行期间,根据具体拿到的类型确定程序的具体行为,调用具体的函数,也称为动态多态。...那么我们如何查看d的虚表呢?下面我们使用代码打印出虚表中的函数。...4.虚表指针传递给PrintVTable进行打印虚表 typedef void(*VFPTR) (); void PrintVTable(VFPTR vTable[]) { // 依次取虚表中的虚函数指针打印并调用
(): print("呵呵") print(func) a = func # 把函数当成一个值赋值给另一个变量 a() # 函数调用 func() 函数名可以当做容器类的元素...("我是func2") func2(func) # 把函数func当成参数传递给func2的参数fn....返回None就不是闭包 def func1(): name = "alex" def func2(): print(name) func2() print...None就是闭包 这样写没有问题,但是有个问题就是这个里边的函数只能先执行了func1才能执行func2,我想在外边调用怎么办呢?...我们来看看函数名加括号获取到的是什么? 为什么不会执行呢??不是函数名加括号就是调用这个函数吗? 你想的没有问题,只是因为函数体中出现了yield 咱们可以理解为,生成器是基于函数的形式变成的.
我们看运行结果: 通过运行结果调试窗口我们可以看到,Base 类的大小是 12 字节,比我们预期的 8 字节多了四字节,这 其实是因为 Base 类中还存在一个默认的虚函数表指针 vfPtr,该指针指向一个虚函数表...注意:有的老铁可以认为虚表如果在代码段是不是就不能对其进行覆盖了,其实不是的,子类的虚表是先拷贝父类虚表,然后进行覆盖,覆盖完毕后才存储到代码段中的。...(一个在编译时就确定函数地址,后面运行时直接调用该地址;一个在运行时才去别处取函数的地址进行调用) 拓展思考:为什么父类对象不能实现多态,而必须是父类的指针/引用?...)(); void PrintVTable(VFPTR vTable[]) { // 依次取虚表中的虚函数指针打印并调用,调用可以看出虚表中存的是哪个函数 cout " <...如果虚函数不是多态调用,则一样块;如果虚函数是多态调用,则普通函数访问更快,因为虚函数多态调用需要运行时到虚表中去取虚函数的地址,然后再 call。 虚函数表是在什么阶段生成的,存在哪的?
基类的成员函数Func2被派生类继承下来,由于是虚函数,所以进入虚函数表; 基类的成员函数Func3也被派生类继承下来,由于不是虚函数,所以没有进入虚表。...: 可以看到Person对象和Student对象调用同一个函数Func得到不同的结果,这是因为基类调用函数的传参基类对象,而派生类对象调用函数时的传参是派生类对象中基类的那一部分。...满足多态以后的函数调用,不是在编译时确定的,是运行起来以后到对象的中取找的(动态绑定);不满足多态的函数调用是在编译时就确定的(静态绑定)。...我们可以将这个现象理解为一个Bug,并不是派生类的虚表里没有它自己的虚函数,而是这两个虚函数被监视窗口隐藏了。那么如果我们想查看派生类的虚函数都有那些该如何进行查看呢?...void PrintVTable(VFPTR vTable[]) { // 依次取虚表中的虚函数指针打印并调用。
,如何判断函数调用关系?...若满足多态:看其指向对象的类型,调用这个类型的成员函数 不满足多态:看具体调用者的类型,进行对应的成员函数调用 2.2、虚函数及重写 所以什么是虚函数?...func1(); p2->func1(); delete p1; delete p2; return 0; } 通过汇编代码观察: 注:下图中的函数地址仅供参考,与上图中的调用演示并不是同一次运行...p2->func1(); add(1, 2); add(1.1, 2.2); 简单来说,静态绑定就像函数重载,在编译阶段就确定了不同函数的调用;而动态绑定是虚函数的调用过程,需要 虚表指针+虚表,在程序运行时...、如何使用多态、构成多态的两个必要条件及两个例外该,最后还学习了多继承模式下多态引发的相关问题,探究了其原理。
领取专属 10元无门槛券
手把手带您无忧上云