【发布时间】:2018-04-10 14:55:08
【问题描述】:
我写了一个小函数,它会创建一个一定长度的随机字符串:
def append_until_length(acceptable, length=45):
retval = set()
for _ in range(1000):
retval.add(random.choice(acceptable))
if len(retval) == length:
return ''.join(retval)
这一切正常,所以一切都很好。但是在运行它时,如果你愿意的话,我注意到了一种模式:
>>> for _ in range(10):
... append_until_length(acceptable)
...
'!#"%\'(+*-,/.057698=?ADGIHLRUV[]\\`behjmonpryx~'
'"$\')+*,025498:=?ACBGKONQPSY[]\\acdgfhkmruvy{z|'
'#"\'&)+,/03248=<?>ABFHJLOPWYXZ]cbdfhklonqrutz}'
' #"(*-/0328EIJMPSRUWVYX]_^acbegfkmlqpstwvx{}|'
'!#"(,/.032549;=>EDHMLOSYX[]_^acbedjlonprtvxz~'
" %',10346?@CEDFIKNQRVYXZ]\\_abghkjlnqpruw{z}|~"
'! #+,/035469:<@CFIKLSRUVY[Z^cbfijloqsutwvxz}|'
'$&)(+-/5;:?>ABDFIHMLOPSUTYXZa`bdhkjmonprwvx}~'
'!#"&*-/102579:=>@DFKJMLONQSTVYX\\^acimoqpstw}~'
'! &(+-/.2548:=<?A@EGFIKOQPSRTVX\\eihjonprutx}~'
>>>
如果你看这个,前几个字符是 always 标点符号,接下来的几个是 always 数字,然后是带有一些混合标点符号的大写字母,另一个标点符号,小写字母,最后一个字符是 always 标点符号。
我使用的可接受的字符是list(string.printable)[:-6] 和.append(" ")。这个list的长度是95:
>>> acceptable
['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '!', '"', '#', '$', '%', '&', "'", '(', ')', '*', '+', ',', '-', '.', '/', ':', ';', '<', '=', '>', '?', '@', '[', '\\', ']', '^', '_', '`', '{', '|', '}', '~', ' ']
>>> len(acceptable)
95
>>>
现在我知道set() 不允许字符串中有多个相同的字符,但是,这并不能解释模式总是相同的(不是真的相同,但远程相同)。看看我是否通过list 执行此操作,该函数从来没有模式:
>>> def append_until_length(acceptable, length=45):
... retval = []
... for _ in range(length):
... retval.append(random.choice(acceptable))
... return ''.join(retval)
...
>>> for _ in range(10):
... append_until_length(acceptable)
...
"] *rZI/<=LwPGU-PzWj)\\jp9tZ}e9T#}4/\\R`4Q^?4)'W"
'%z6wTvuzK;{eS}"^GRf(}a3<"Qqg_*2v?1`y@;=Bn#ycQ'
"t'bqj,*}7:w]:8c;Ddy. 17@^Y0{)>}'25tsl1kf+C%6^"
'RZt)s=?~QrAok+Z\\ei}5K^&1e+w0~*zl{hS2;l]|?p/T;'
'%InO5_fWcJU#v,6_=cPb^cfd1=\\;k{37~$214vd+F&oH&'
'!6Ey#"\'3.,ivG+7\'y[&1`aYNDg-\\j#:! -7(8b#$x)Q1m'
'w}/{mnT\\-IT2?;V_K ZDDy:YzaG+LgGkZWkV8E y@_)Y;'
'e1@71AFDF;|Q.<_fRG0tG*`557z(|}bHDCT+dc}{[QGq8'
"ie~;Iy1O)f!n,Z%%0\\36-!Lke1}cA'uptRS7(2ki|mzgi"
'G=v&#.J1@E$N?NK|~>( E4M/^y[~HK)#Hi$23ez~EY>N '
即使我将list 视为set,输出字符串仍然没有模式:
def append_until_length(acceptable, length=45):
retval = []
for _ in range(10000):
char = random.choice(acceptable)
if char not in retval:
retval.append(char)
if len(retval) == length:
return ''.join(retval)
8hKO W5"'ERJa/N$vb9^4!)fig:c_n&?@(#}oTC]qePwZ
,b2;Y^VD9|:O!>QilH`4(7/F?8f&5~_B$x#pN{Igahs\n
_z1eDiH$9k&rRt>M/FOqb8SLY.{|0dI4A^:l,3cs7ng][
Y/iu#eOlVMmZ 9S`t?1JX2$<)&|jUz'"~wLIvoqkr}!(H
r~/m{8SLvU?_aVX4A"0%zEgK1I!9#B|snphOZb,@jw\]2
;nX!T20.^b"\eqNExOlrQF'V&#(%iht{Hw+-Sy,Dj]:9[
B@%H[2f&JuwSd1bEnih#}]3jTMLzAW.ZG~,tX|!/N_`D(
usv}KkZgL]&<hY^6Blp\GENTrFC~Xw3#4S8QmRf"PUnM|
?G3Ao[z7gVLve-}S>X]&<+k(DZ*UcsM50r)^1Om`P4K,6
,#&(1-'sj9qy7~dZpuIk!%Q D8haSNrco{xe;=.T[WK0<
所以我的问题是,为什么set 会出现这种模式?大写和小写字符具有不同的ord 数字,因此是不同的字符。即:
>>> ord("c")
99
>>> ord("C")
67
>>>
所以在我看来,如果字符串是随机生成的,为什么字符串中有模式是没有意义的?根据help(set):
class set(object)
| set() -> new empty set object
| set(iterable) -> new set object
|
| Build an unordered collection of unique elements.
【问题讨论】: