Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/string/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 为什么在使用集合创建随机字符串时会出现这种模式?_Python_String_Random - Fatal编程技术网

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 vs
O(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)