The following Python script works well with Python 2.3 and Python 2.4 (which don't have a built-in definition of all()
:
#! /usr/bin/env python
# vim: set fileencoding=utf-8
# (c) Uwe Kleine-König
# GPLv2
import locale
import sys
f = file(sys.argv[1])
data = f.read()
def len_utf8_char(data):
if not 'all' in dir(__builtins__):
def all(seq):
for i in seq:
if not i:
return False
return True
def check_cont(num):
if all(map(lambda c: ord(c) >= 0x80 and ord(c) <= 0xbf, data[1:num])):
return num
else:
return -1
if ord(data[0]) < 128:
# ASCII char
return 1
elif ord(data[0]) & 0xe0 == 0xc0:
return check_cont(2)
elif ord(data[0]) & 0xf0 == 0xe0:
return check_cont(3)
elif ord(data[0]) & 0xf8 == 0xf0:
return check_cont(4)
elif ord(data[0]) & 0xfc == 0xf8:
return check_cont(5)
elif ord(data[0]) & 0xfe == 0xfc:
return check_cont(6)
i = 0
maxl = 0
while i < len(data):
l = len_utf8_char(data[i:])
if l < 0:
prefenc = locale.getpreferredencoding()
if prefenc not in ('UTF-8', 'ANSI_X3.4-1968'):
print prefenc
else:
print 'ISO-8859-1'
sys.exit(0)
if maxl < l:
maxl = l
i += l
if maxl > 1:
print 'UTF-8'
else:
print 'ANSI_X3.4-1968'
Now with Python 2.5 and later this fails as follows:
$ python2.5 guess-charmap guess-charmap
Traceback (most recent call last):
File "guess-charmap", line 43, in <module>
l = len_utf8_char(data[i:])
File "guess-charmap", line 30, in len_utf8_char
return check_cont(2)
File "guess-charmap", line 21, in check_cont
if all(map(lambda c: ord(c) >= 0x80 and ord(c) <= 0xbf, data[1:num])):
NameError: free variable 'all' referenced before assignment in enclosing scope
删除all的兼容性定义修复了Python 2.5+的问题。
我想知道,在这种情况下,Python为什么不选择内置的
all()
。? 最佳答案
当Python解析函数体时,它会查找赋值中使用的变量名。除非使用global
变量声明,否则所有这些变量都假定为局部变量。def all
为变量名all
赋值。尽管赋值在if-block
中,但在所有情况下,all
都被视为局部变量(无论if-block
是否稍后执行)。
如果不执行if块,all
将成为未绑定的局部变量,从而引发NameError。
If you move the if not 'all' ...
block outside the def len_utf8_char
, then
你会避免这个问题的。
关于python - Python比内置函数更喜欢未分配的局部函数,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/6617354/