网页
资讯
视频
图片
知道
文库
贴吧
地图
采购
进入贴吧
全吧搜索
吧内搜索
搜贴
搜人
进吧
搜标签
日
一
二
三
四
五
六
签到排名:今日本吧第
个签到,
本吧因你更精彩,明天继续来努力!
本吧签到人数:0
一键签到
成为超级会员,使用一键签到
一键签到
本月漏签
0
次!
0
成为超级会员,赠送8张补签卡
如何使用?
点击日历上漏签日期,即可进行
补签
。
连续签到:
天 累计签到:
天
0
超级会员单次开通12个月以上,赠送连续签到卡3张
使用连续签到卡
03月28日
漏签
0
天
linux吧
关注:
493,905
贴子:
2,566,556
看贴
图片
吧主推荐
视频
游戏
23
回复贴,共
1
页
<<返回linux吧
>0< 加载中...
又发现一个问题
只看楼主
收藏
回复
七奈kiss
----xrw-
14
该楼层疑似违规已被系统折叠
隐藏此楼
查看此楼
貌似PyNumber_InPlaceAdd没效果啊,把一个pyintobject2加给另一个pyintobject1,结果pyintobj1的值还是原先的值。。。。
PyNumber_Add就没问题。。。。
a126285
----xr-x
13
该楼层疑似违规已被系统折叠
隐藏此楼
查看此楼
稍微看了下ref,提到这函数等价于o1 += o2。楼主提到它不管用,我想是不是因为ref写的有问题
从实现角度看,PyNumber_InPlaceAdd需要修改首参数引用的对象,若它(首参数引用对象)是immutable,则无法修改它(不然就打破其mutable特性了)
到达未来(海南)元宇宙..
体验真人互动协作,Web3数字化生活,加入虚实相连的乌托邦世界——成为永久居民,了解区块链的应用
2025-03-28 15:39
广告
立即查看
a126285
----xr-x
13
该楼层疑似违规已被系统折叠
隐藏此楼
查看此楼
大概看了下2.7.7和3.3.5的代码,大致是这样的:
PyNumber_InPlaceAdd:优先把+当做 “数值” 相加,查找首参obj的->ob_type->tp_as_number methods table,没细研究,大概就是类似实现 “数值类行为的meta methods”。查找nb_inplace_add method,找不到的话,会找nb_add method,找到任意一个就使用它。若都未找到(即未实现)的话,会尝试把+当做seq concat处理,即查找首参obj的ob_type->tp_as_sequence —— 类似 “序列类行为的meta methods” 的玩意,类似的,顺序找sq_inplace_concat和sq_concat俩methods,找到就用,都找不到的话,函数就失败了,返回Py_NotImplemented
这样就和我之前的猜测类似,由具体的obj实现实际的操作,我们继续看各种类型的相关函数的实现,我搜了下,int type、long type、float type,都未提供nb_inplace_add,但实现了nb_add
2.7.7和3.3.5类似,只是3.3.5没有int type了
所以,结论是,当调用PyNumber_InPlaceAdd,参数是int obj、long obj或float obj时,实际调用等价于PyNumber_Add
a126285
----xr-x
13
该楼层疑似违规已被系统折叠
隐藏此楼
查看此楼
弄完手上的事儿,翻了下代码。还有值得说一说的状况
python的脚本中的o1 = o1 + o2对应到opcode是大约是:
LOAD_FAST(o1)
LOAD_FAST(o2)
BINARY_ADD
STORE_FAST(o1)
而o1 += o2,大约对应:
LOAD_FAST(o1)
LOAD_FAST(o2)
INPLACE_ADD
STORE_FAST(o1)
可见,唯一的不同在于BINARY_ADD和INPLACE_ADD的区别,INPLACE_ADD实际执行大约是:
x = PyNumber_InPlaceAdd(o1, o2);
其中x是结果,可见,就算是inplace_add,python解释器还是使用新的对象来接收结果,这里存在 “x和o1是一个对象” 和 “x和o1不是一个对象” 两种情况(由o1自身的__iadd__ method决定),这也是它相对于BINARY_ADD的区别。btw:也由此可见o1 += o2性能总不低于o1 = o1 + o2
再来看o1.__iadd__被实现的情况
当o1 immutable时,PyNumber_InPlaceAdd(o1, o2)调用不可能改变o1,否则o1的mutability就被破坏了。若令x = PyNumber_InPlaceAdd(o1, o2)则能得到正确的结果
当o1 mutable时,PyNumber_InPlaceAdd(o1, o2)调用一般应选择直接修改o1(原则上应该)。当令x = PyNumber_InPlaceAdd(o1, o2)时,x和o1理应得到同一个对象(当__iadd__直接修改o1时,应如此)
而脚本中的o1 += o2,由于上面提到,解释器用x接受返回值,并store在o1中(绑定新对象),因此,都能正确执行
由此,我们看到,PyNumber_InPlaceAdd的正确用法,不应该期待它修改o1,而应该通过接收其返回值获得结果。有人想问,那这样岂不是和普通binary add一样了?并非如此,PyNumber_InPlaceAdd给o1提供了一个优化的机会,当诸多条件满足时(主要是mutability),它可以有机会优化
以上不能保证正确,有兴趣可以自行研究确认
a126285
----xr-x
13
该楼层疑似违规已被系统折叠
隐藏此楼
查看此楼
还有个可能隐藏的错误也值得注意
不可以这样调用:
o1 = PyNumber_InPlaceAdd(o1, o2);
而应该
x = PyNumber_InPlaceAdd(o1, o2);
Py_DECREF(o1);
o1 = x;
发现py c api很烦,obj的 “所有权” 需要特别注意
登录百度账号
扫二维码下载贴吧客户端
下载贴吧APP
看高清直播、视频!
贴吧页面意见反馈
违规贴吧举报反馈通道
贴吧违规信息处理公示