我正在尝试计算python中文件的shannon熵。
所以,我编写了以下代码来实现这一目标。 但它并没有像预期的那样发挥作用。
我认为一切正确,但fsize变量已被清除。
我不明白为什么,因为它具有全球范围。
你能举手或解释吗?
由于
from __future__ import division
import sys
import os
import math
def get_chunks(file_size, chunk_size = 4096):
chunk_start = 0
while chunk_start + chunk_size < file_size:
yield(chunk_start, chunk_size)
chunk_start += chunk_size
final_chunk_size = file_size - chunk_start
yield(chunk_start, final_chunk_size)
def read_file_chunked(file_path):
file_size = os.path.getsize(file_path)
fsize = file_size # <------------------------------this var
print('File size: {}'.format(file_size))
with open(file_path,'rb') as file_:
progress = 0
for chunk_start, chunk_size in get_chunks(file_size):
file_chunk = file_.read(chunk_size)
# byte count
for b in file_chunk:
freqs[ord(b)]+=1
progress += len(file_chunk)
print '{0} of {1} bytes read ({2}%)'.format( progress, file_size, int(progress / file_size * 100))
#calculate the frequency of each byte
for idx, f in enumerate(freqs):
freqs[idx] = float(f / file_size)
print
freqs = [0] * 256
fsize = 0 #<------------------ this var
if len(sys.argv) != 2:
print "Usage entropy [file]"
sys.exit()
if __name__ == '__main__':
read_file_chunked(sys.argv[1])
# print byte frequencies
for idx,f in enumerate(freqs):
print hex(idx),f
# calculate Shannon entropy
ent = 0.0
for f in freqs:
if f > 0:
ent += f * math.log(f,2)
ent = -ent
print 'Shannon entropy ( min bits per byte-character )'
print ent
print
print 'Min possible file size assuming max compression efficiency'
print (ent * fsize), ' in bits' #------------------- here fsize is 0
print (ent * fsize) / 8, ' in bytes' #-------------- here fsize is 0
答案 0 :(得分:2)
在fsize
中分配给read_file_chunked
会创建一个新的局部变量,该函数在函数返回时被删除。为了分配全局变量fsize
,请明确声明它:
def read_file_chunked(file_path):
global fsize
file_size = os.path.getsize(file_path)
fsize = file_size # <------------------------------this var
或者,让read_file_chunked
返回文件大小。
答案 1 :(得分:2)
在read_file_chunked
函数中,您要在函数范围内创建新变量fsize
,根本不需要修改全局变量。请考虑以下演示:
>>> x = 0
>>> def foo():
... x = 1
...
>>> foo()
>>> x
0
使用global
关键字使您的代码按照您的意图运行所缺少的是:
>>> x = 0
>>> def foo():
... global x
... x = 1
...
>>> foo()
>>> x
1
话虽如此,我质疑你对全局变量的使用。为什么不从你的职能中return
fsize
?