Python是否允许访问某些实现细节? [英] Does Python allow access to some of the implementation details?

查看:52
本文介绍了Python是否允许访问某些实现细节?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

让我们考虑一下这篇帖子最后给出的测试源代码。


问题是Python是否允许以某种方式访问​​
的字节
表示计算机内存中的长整数或整数?

或者Python是否隐藏了这样的实现细节,那就是

无法归结为它们是什么?


下面的测试代码显示,使用n& 0x01时,从整数值n

中提取位比使用n%2和我想它是

,因为%2试图处理整个整数,其中& 0x01处理

只有它的最后两个字节(我来这是因为速度

& 0x01和%2操作之间的差异取决于

值n的大小。如果有可能''告诉''%2操作只能在整数表示的一个短路上运行

,那么

可能没有速度差异。有没有办法有效地执行此操作

在Python中使用指针和重铸时可能在C中?


我在Python 2.4.2上和Microsoft Windows,我感兴趣的是与这个Python版本相关的
细节(限制

问题的范围)。


Claudio


这里代码:


导入时间


#i = 2 * * 25964951 - 1

i = 123456789 ** 123

lstBitsModulo = []

start = time.clock()

而i:

i = i>> 1

lstBitsModulo.append(i%2)

speedModulo = time.clock() -start


#i = 2 ** 25964951 - 1

i = 123456789 ** 123

lstBitsBitwiseAnd = []

start = time.clock()

而i:

i = i>> 1

lstBitsBitwiseAnd.append( i& 0x01)

speedBitwiseAnd = time.clock() - 开始


打印

如果lstBitsBitwiseAnd == lstBitsModulo:
print''BitwiseAnd =%f''%(speedBitwiseAnd,)

print''Modulo =%f''%(speedModulo,)

print#两个列表都是长整数值列表

print lstBitsBitwiseAnd [0:3]

print lstBitsModulo [0:3]

解决方案

>下面的测试代码显示,使用n& 0x01时,从使用n& 0x01的整数值中提取位比使用n%2时更快,我认为它是因为%2试图处理整个整数,其中& 0x01只处理它的最后两个字节(我来这是因为& 0x01和%2操作之间的速度差异取决于它的大小。
价值n是)




我怀疑原因是&处理较少的数据。原因是%有效地是一个分区,而&是一个逻辑操作。这总是比分裂更快_ />



当然你是正确的,当一个人的bfiddling _could_优化

知道只有某个数字的某些字节才会引起关注。但是我很担心python会在这里进行任何优化。但是,我肯定不知道



问候,


Diez


我不知道如何直接访问

long的内部结构,但你可以加速你的例子。


首先,是命令的顺序

i = i>> 1
lstBitsBitwiseAnd.append(i& 0x01)



你想要什么?第一个低位被丢弃,因为你已经先完成了这个班次。并附加一个额外的0。


如果你想获得long的二进制表示,请尝试

i .__ hex __()。这将创建一个带有十六进制表示的字符串。

从十六进制到二进制的转换留给读者练习。 :-)


ca **** @ comcast.net 写道:

我不知道如何直接访问
的内部结构,但你可以加快你的榜样。

首先是命令的顺序

i = i>> 1
lstBitsBitwiseAnd.append(i& 0x01)



你想要什么?第一个低位被丢弃,因为你已经先完成了这个班次。并附加一个额外的0。

如果你想获得long的二进制表示,请尝试使用
i .__ hex __()。这将创建一个带有十六进制表示的字符串。
从十六进制到二进制的转换留给读者练习。 : - )



你是对的,如果你想从

整数值中取出所有位,这是不正确的。我没有注意到正确的顺序,因为我的

唯一的目的是检查什么是更快的模除法或按位 - 和

所以结果这个顺序没关系。


i .__ hex __()的想法非常非常接近我最初的要求

for。遗憾的是,它通常被认为不比使用+ b $ b转换+按位的速度更快 - 后者似乎优于

小长整数和整数(参见附加代码显示中断甚至

,对于需要超过16到104位数的整数,对于我机器上的多个测试,需要超过
)。


克劳迪奥


导入时间


dctLstOfBitsVsCharOfNibble = {}

#dctLstOfBitsVsCharOfNibble是一个带有键的字典。

字符

#表示半字节的十六进制值的字符串和一个值为
列表的值

半字节的位数,其中最低位存储在

列表的索引0处。

#ie

dctLstOfBitsVsCharOfNibble = {

''0'':[0,0,0,0],

''1'':[0,0,0, 1],

''2'':[0,0,1,0],

''3'':[0,0,1,1] ,

''4'':[0,1,0,0],

''5'':[0,1,0,1],

'' 6'':[0,1,1,0],

''7'':[0,1,1,1],

''8' ':[1,0,0,0],

''9'':[1,0,0,1],

''A'': [1,0,1,0],

''B'':[1,0,1,1],

''C'':[1 ,1,0,0],

''D'':[1,1,0,1],

''E'':[1,1] ,1,0],

''F'':[1,1,1,1]

}

#字典可以也可以生成例如使用以下代码:

#dctLstOfBitsVsCharOfNibble = {}

#for intNibbleValue in range(0,16):

#lstBitReprOfCurrNibble = []

#对于范围(0,4)中的indxOfBit:

#lstBitReprOfCurrNibble.append(intNibbleValue>> indx OfBit& 0x01)

## :for

#lstBitReprOfCurrNibble.reverse()



dctLstOfBitsVsCharOfNibble [''%X''%(intNibbleValue,)] = lstBitReprOfCurrNibble

##:for


NoOf32bitChunksOfInteger = 0

n = 0

lstBitsBitwiseAnd = []

lstBitsModulo = []

lstBitsViaHex = []

timeBitwiseAnd = -1

timeModulo = -1

timeBitsViaHex = -1


而timeBitwiseAnd< = timeBitsViaHex:


n =(n<< 32)+ 0x12345678

NoOf32bitChunksOfInteger + = 1

i = n

lstBitsModulo = []

start = time.clock ()

而我:

lstBitsModulo.append(i%2)

i = i>> 1

timeModulo = time.clock() - start


i = n

lstBitsBitwiseAnd = []

start = time.clock()

while i:

lstBitsBitwiseAnd.append(i& 0x01)

i = i>> 1

timeBitwiseAnd = time.clock() - start


i = n

#lstBitsViaHex = []

start = time.clock()

strHexOf_i = i .__ hex __()[2:]

如果strHexOf_i [-1] ==''L'':

strHexOf_i = strHexOf_i [0:-1]

#:if

intNoOfLeadingZeroBits = 0

lstBitsOfFirstNibble = dctLstOfBitsVsCharOfNibble [strHexOf_i [0]]

而不是lstBitsOfFirstNibble [ intNoOfLeadingZeroBits]和

intNoOfLeadingZeroBits< 4:

intNoOfLeadingZeroBits + = 1

#:while

if intNoOfLeadingZeroBits == 4:

lstBitsViaHex = [ ]

else:

lstBitsViaHex = lstBitsOfFirstNibble [intNoOfLeadingZeroBits:]

#:if

for indxToStrHexOf_i in range( 1,len(strHexOf_i)):

lstBitsViaHex + =

dctLstOfBitsVsCharOfNibble [strHexOf_i [indxToStrHexOf_i]]

#:for

lstBitsViaHex.reverse()

timeBitsViaHex = time.clock() - 开始

#:而


如果是lstBitsBitwiseAnd == lstBitsModulo和lstBitsBitwiseAnd ==

lstBitsViaHex:

print

print''从整数中提取位的秒数,%i为十六位数

时:''%(NoOf32bitChunksOfInteger * 8,)

打印

打印''循环播放i>> 1; i& 0x01 = %f''%(timeBitwiseAnd,)

打印''循环播放i>> 1; i %% 2 =%f''%(timeModulo,)

打印''使用i .__ hex __()repr。 =%f''%(timeBitsViaHex,)

打印

打印''对于长整数我有十六进制数字''

打印''> %i''%(NoOf32bitChunksOfInteger * 8,)

print''使用i .__ hex __()进行位提取比使用

i>> 1; i& 0x01。''

打印

打印''Modulo除法(%)总是慢于按位和

(&)。 ''


Let''s consider a test source code given at the very end of this posting.

The question is if Python allows somehow access to the bytes of the
representation of a long integer or integer in computers memory?
Or does Python hide such implementation details that deep, that there is
no way to get down to them?

The test code below shows, that extracting bits from an integer value n
is faster when using n&0x01 than when using n%2 and I suppose it is
because %2 tries to handle the entire integer, where &0x01 processes
only the last two bytes of it (I come to this because the speed
difference between &0x01 and %2 operations depends on how large the
value n is). If it were possible to ''tell'' the %2 operation to operate
only on one short of the integer number representation there will be
probably no difference in speed. Is there a way to do this efficiently
in Python like it is possible in C when using pointers and recasting?

As I am on Python 2.4.2 and Microsoft Windows, I am interested in
details related to this Python version (to limit the scope of the
question).

Claudio

Here the code:

import time

# i = 2**25964951 - 1
i = 123456789**123
lstBitsModulo = []
start = time.clock()
while i:
i=i>>1
lstBitsModulo.append(i%2)
speedModulo = time.clock()-start

# i = 2**25964951 - 1
i = 123456789**123
lstBitsBitwiseAnd = []
start = time.clock()
while i:
i=i>>1
lstBitsBitwiseAnd.append(i&0x01)
speedBitwiseAnd = time.clock()-start

print
if lstBitsBitwiseAnd == lstBitsModulo :
print ''BitwiseAnd = %f ''%(speedBitwiseAnd,)
print ''Modulo = %f ''%(speedModulo,)

print # both lists are lists of long integer values
print lstBitsBitwiseAnd[0:3]
print lstBitsModulo[0:3]

解决方案

> The test code below shows, that extracting bits from an integer value n

is faster when using n&0x01 than when using n%2 and I suppose it is
because %2 tries to handle the entire integer, where &0x01 processes
only the last two bytes of it (I come to this because the speed
difference between &0x01 and %2 operations depends on how large the
value n is)



I doubt that the reason is in & handling less data. The reason is that % is
effectively a division, whereas & is a logical operation. Which have always
been _way_ faster than divisions.

Of course you are right that the bitfiddling _could_ be optimized when one
knows that only certain bytes of a number would be of interest. But I
seriously doubt that python does any optimization here. However, I don''t
know for sure.

Regards,

Diez


I don''t know of a way to directly access the internal structure of a
long, but you can speed up your example.

First, is the order of the commands

i=i>>1
lstBitsBitwiseAnd.append(i&0x01)



what you intend? The first low order bit is discarded because you''ve
done the shift first. And an extra 0 is appended.

If you are trying to get the binary representation of a long, try
i.__hex__(). This will create a string with the hex representation.
Conversion from hex to binary is left as an exercise for the reader. :-)


ca****@comcast.net wrote:

I don''t know of a way to directly access the internal structure of a
long, but you can speed up your example.

First, is the order of the commands

i=i>>1
lstBitsBitwiseAnd.append(i&0x01)


what you intend? The first low order bit is discarded because you''ve
done the shift first. And an extra 0 is appended.

If you are trying to get the binary representation of a long, try
i.__hex__(). This will create a string with the hex representation.
Conversion from hex to binary is left as an exercise for the reader. :-)


You are right, it is not correct if you want to get all bits out of an
integer value. I haven''t payed attention to the proper order, because my
only intent was to check what is faster modulo-division or bitwise-and,
so for the outcome of this the order does not matter.

The i.__hex__() idea is very, very near to what I have originally asked
for. It''s a pity, that it can''t be generally considered faster than
usage of shifting+bitwise-and where the latter seem to be superior for
small long integers and integers (see attached code showing a break even
for integers which require more than appr. 16 up to 104 digits according
to multiple tests on my machine).

Claudio

import time

dctLstOfBitsVsCharOfNibble = {}
# dctLstOfBitsVsCharOfNibble is a dictionary with a key beeing one
character
# string representing hexadecimal value of a nibble and a value beeing a
list
# of bits of the nibble where the lowest bit is stored at index 0 of the
list.
# i.e.
dctLstOfBitsVsCharOfNibble = {
''0'':[0, 0, 0, 0],
''1'':[0, 0, 0, 1],
''2'':[0, 0, 1, 0],
''3'':[0, 0, 1, 1],
''4'':[0, 1, 0, 0],
''5'':[0, 1, 0, 1],
''6'':[0, 1, 1, 0],
''7'':[0, 1, 1, 1],
''8'':[1, 0, 0, 0],
''9'':[1, 0, 0, 1],
''A'':[1, 0, 1, 0],
''B'':[1, 0, 1, 1],
''C'':[1, 1, 0, 0],
''D'':[1, 1, 0, 1],
''E'':[1, 1, 1, 0],
''F'':[1, 1, 1, 1]
}
# The dictionary can also be generated e.g. using following code:
# dctLstOfBitsVsCharOfNibble = {}
# for intNibbleValue in range(0, 16):
# lstBitReprOfCurrNibble=[]
# for indxOfBit in range(0,4):
# lstBitReprOfCurrNibble.append(intNibbleValue>>indx OfBit&0x01)
# #:for
# lstBitReprOfCurrNibble.reverse()
#
dctLstOfBitsVsCharOfNibble[''%X''%(intNibbleValue,)]=lstBitReprOfCurrNibble
# #:for

NoOf32bitChunksOfInteger = 0
n = 0
lstBitsBitwiseAnd = []
lstBitsModulo = []
lstBitsViaHex = []
timeBitwiseAnd = -1
timeModulo = -1
timeBitsViaHex = -1

while timeBitwiseAnd <= timeBitsViaHex:

n = (n<<32) + 0x12345678
NoOf32bitChunksOfInteger += 1

i = n
lstBitsModulo = []
start = time.clock()
while i:
lstBitsModulo.append(i%2)
i=i>>1
timeModulo = time.clock()-start

i = n
lstBitsBitwiseAnd = []
start = time.clock()
while i:
lstBitsBitwiseAnd.append(i&0x01)
i=i>>1
timeBitwiseAnd = time.clock()-start

i = n
# lstBitsViaHex = []
start = time.clock()
strHexOf_i = i.__hex__()[2:]
if strHexOf_i[-1]==''L'':
strHexOf_i=strHexOf_i[0:-1]
#:if
intNoOfLeadingZeroBits = 0
lstBitsOfFirstNibble = dctLstOfBitsVsCharOfNibble[strHexOf_i[0]]
while not lstBitsOfFirstNibble[intNoOfLeadingZeroBits] and
intNoOfLeadingZeroBits < 4:
intNoOfLeadingZeroBits += 1
#:while
if intNoOfLeadingZeroBits == 4:
lstBitsViaHex = []
else:
lstBitsViaHex = lstBitsOfFirstNibble[intNoOfLeadingZeroBits:]
#:if
for indxToStrHexOf_i in range(1,len(strHexOf_i)):
lstBitsViaHex +=
dctLstOfBitsVsCharOfNibble[strHexOf_i[indxToStrHexOf_i]]
#:for
lstBitsViaHex.reverse()
timeBitsViaHex = time.clock()-start
#:while

if lstBitsBitwiseAnd == lstBitsModulo and lstBitsBitwiseAnd ==
lstBitsViaHex:
print
print '' Seconds for bit extraction from integer with %i hex-digits
when: ''%(NoOf32bitChunksOfInteger*8,)
print
print '' looping over i>>1;i&0x01 = %f ''%(timeBitwiseAnd,)
print '' looping over i>>1;i%%2 = %f ''%(timeModulo,)
print '' using i.__hex__() repr. = %f ''%(timeBitsViaHex,)
print
print '' For long integers i with number of hexadecimal digits ''
print '' > %i ''%(NoOf32bitChunksOfInteger*8,)
print '' bits extraction with i.__hex__() is faster then with
i>>1;i&0x01 .''
print
print '' Modulo division (%) is always much slower than bitwise and
(&). ''


这篇关于Python是否允许访问某些实现细节?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆