Python 为什么在使用集合创建随机字符串时会出现这种模式?
我编写了一个小函数,它将创建一个特定长度的随机字符串:Python 为什么在使用集合创建随机字符串时会出现这种模式?,python,string,random,Python,String,Random,我编写了一个小函数,它将创建一个特定长度的随机字符串: 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) 这一切都有效,所以一切都很
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}~'
>>>
现在我明白了set()
将不允许字符串中有多个相同的字符,但是,这并不能解释模式总是相同的(不是真的相同,而是完全相同)。查看我是否通过列表执行此操作
函数从来没有模式:
>>> 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 '
所以我的问题是,为什么模式会出现在集合中?大写和小写字符具有不同的ord
编号,因此是不同的字符。即:
>>> ord("c")
99
>>> ord("C")
67
>>>
所以在我看来,如果字符串是随机生成的,为什么字符串中有一个模式是没有意义的?根据帮助(设置)
:
您的问题是set
s并不是真正无序的。它们遵循实现定义的顺序,您无法依赖或预测(这与python解释器的两次执行不同),但它确实存在()
在这种情况下,它似乎是自然的字母顺序,但不一定是:
Python 3.4.3 (v3.4.3:9b73f1c3e601, Feb 24 2015, 22:44:40) [MSC v.1600 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> set("ABCDEFG")
{'A', 'E', 'F', 'G', 'C', 'B', 'D'}
>>> set("ABCDEFG")
{'A', 'E', 'F', 'G', 'C', 'B', 'D'}
两个不同集合的顺序相同,不按字母顺序。现在让我们再次运行它:
Python 3.4.3 (v3.4.3:9b73f1c3e601, Feb 24 2015, 22:44:40) [MSC v.1600 64 bit (AM D64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> set("ABCDEFG")
{'C', 'G', 'D', 'B', 'E', 'A', 'F'}
>>>
不同顺序(与哈希种子和python安全特性相关)
因此,在解释器的同一个实例中,它对不同的字符类型进行相同的排序,从而创建一个“模式”
要受益于set
(O(1)
average lookup vsO(n)
for list)的速度,并保持random
提供的混乱顺序,您可以使用辅助集进行测试,但要存储在列表中:
def append_until_length(acceptable, length=45):
retval = []
testset = set()
for _ in range(10000):
char = random.choice(acceptable)
if char not in testset: # fast lookup (O(1))
retval.append(char) # add to the result list
testset.add(char) # add to the set
if len(retval) == length:
return ''.join(retval)
根据帮助(集合)
类集合(对象)构建唯一元素的无序集合。
无序意味着:不能依赖顺序。但是在您的python版本/实现中至少有一个:因此,如果我设置了set([1,2,3,4,5,6,7,8,9,10])
它应该以从大到小的顺序显示?在我的python 3.4版本中,我会得到完全相同的排序列表。最少的是最大的。试试看。对于整数来说更容易,因为大多数情况下整数本身就是散列(对于小整数,除了-1)是的,我确实尝试过。我还试用了set([1,2,2,2,5,5,5,5,58,58])
,它显示为set([1,2,58,5])
<代码>集
s都是奇怪的男人哈哈。
Python 3.4.3 (v3.4.3:9b73f1c3e601, Feb 24 2015, 22:44:40) [MSC v.1600 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> set("ABCDEFG")
{'A', 'E', 'F', 'G', 'C', 'B', 'D'}
>>> set("ABCDEFG")
{'A', 'E', 'F', 'G', 'C', 'B', 'D'}
Python 3.4.3 (v3.4.3:9b73f1c3e601, Feb 24 2015, 22:44:40) [MSC v.1600 64 bit (AM D64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> set("ABCDEFG")
{'C', 'G', 'D', 'B', 'E', 'A', 'F'}
>>>
def append_until_length(acceptable, length=45):
retval = []
testset = set()
for _ in range(10000):
char = random.choice(acceptable)
if char not in testset: # fast lookup (O(1))
retval.append(char) # add to the result list
testset.add(char) # add to the set
if len(retval) == length:
return ''.join(retval)