एक यादृच्छिक स्ट्रिंग और एक यादृच्छिक हेक्साडेसिमल संख्या बनाने के लिए सबसे हल्का तरीका


94

निम्नलिखित की तरह 30 अक्षरों का एक यादृच्छिक स्ट्रिंग बनाने के लिए सबसे हल्का तरीका क्या है?

ufhy3skj5nca0d2dfh9hwd2tbk9sw1

और अनुवर्ती की तरह 30 अंकों की एक हेक्साडेसिमल संख्या?

8c6f78ac23b4a7b8c0182d7a89e9b1


3
कैसे (क्यों?) यह है कि (अच्छी तरह से तैयार) उत्तरों में से कोई भी स्वीकार नहीं किया गया है?
— r2evans

जवाबों:


124

मुझे हेक्स आउटपुट के लिए तेजी से एक मिला। उपरोक्त के रूप में समान t1 और t2 का उपयोग करना:

>>> t1 = timeit.Timer("''.join(random.choice('0123456789abcdef') for n in xrange(30))", "import random")
>>> t2 = timeit.Timer("binascii.b2a_hex(os.urandom(15))", "import os, binascii")
>>> t3 = timeit.Timer("'%030x' % random.randrange(16**30)", "import random")
>>> for t in t1, t2, t3:
...     t.timeit()
... 
28.165037870407104
9.0292739868164062
5.2836320400238037

t3 केवल यादृच्छिक मॉड्यूल के लिए एक कॉल करता है, एक सूची बनाने या पढ़ने के लिए नहीं है, और फिर स्ट्रिंग प्रारूपण के साथ बाकी है।


5
अच्छा लगा। बस एक यादृच्छिक संख्या 30 हेक्स अंक उत्पन्न करें और इसे प्रिंट करें। जाहिर है जब बताया गया। अच्छा है।
— eemz

दिलचस्प है, मैं यह भूल गया कि पायथन (और यादृच्छिक मॉड्यूल) मूल रूप से बड़े संकेतों को संभालता है।
— wump

3
उपयोग करने पर नीचे दिए गए यारोन्फ़ का उत्तर देखें string.hexdigits: stackoverflow.com/a/15462293/311288 " string.hexdigitsरिटर्न 0123456789abcdefABCDEF(लोअरकेस और अपरकेस) दोनों, [...]। इसके बजाय, बस उपयोग करें random.choice('0123456789abcdef')।"
— थॉमस

3
इसे और भी तेज़ बनाने के getrandbitsबजाय उपयोग करें randrange।
— रोबिन

@robinst के पास एक अच्छी बात है। '%030x' % random.getrandbits(60)इससे भी अधिक तेजी से '%030x' % random.randrange(16**30)होने की संभावना है , क्योंकि इसमें बड़े-से-ints से कोई रूपांतरण नहीं करना है
— Dan Lenski

79

30 अंक हेक्स स्ट्रिंग:

>>> import os,binascii
>>> print binascii.b2a_hex(os.urandom(15))
"c84766ca4a3ce52c3602bbf02ad1f7"

लाभ यह है कि इससे ओएस से सीधे यादृच्छिकता प्राप्त होती है, जो यादृच्छिक () की तुलना में अधिक सुरक्षित और / या तेज हो सकती है, और आपको इसे बीजने की आवश्यकता नहीं है।


यह दिलचस्प है, और 30 अंकों की हेक्स संख्या को उत्पन्न करने के लिए शायद एक अच्छा विकल्प है। शायद अल्फ़ान्यूमेरिक स्ट्रिंग को उत्पन्न करने के लिए यूरेनियम और एक स्लाइस ऑपरेटर का उपयोग कर सकता है।
— ईमेज

मैंने बिनसिसी में अन्य कार्यों पर एक नज़र डाली, उनके पास बेस 64 और यूएनकोड है, लेकिन पहली तरह के तारों को उत्पन्न करने का कोई तरीका नहीं है जो वह चाहते हैं (बेस 36)।
— wump

1
क्या यह यादृच्छिक / अद्वितीय पर्याप्त है, जिसे सत्र टोकन कहा जाता है?
— मोरास

1
उ: नहीं। उत्तर मिला: stackoverflow.com/questions/817882/unique-session-id-in-python/…
— मोराज़

लंबाई कैसे निर्दिष्ट करता है?
— 3kstc

53

Py3.6 + में, एक अन्य विकल्प नए मानक secretsमॉड्यूल का उपयोग करना है :

>>> import secrets
>>> secrets.token_hex(15)
'8d9bad5b43259c6ee27d9aadc7b832'
>>> secrets.token_urlsafe(22)   # may include '_-' unclear if that is acceptable
'teRq7IqhaRU0S3euX1ji9f58WzUkrg'

28
import string
import random
lst = [random.choice(string.ascii_letters + string.digits) for n in xrange(30)]
str = "".join(lst)
print str
ocwbKCiuAJLRJgM1bWNV1TPSH0F2Lb

6
और random.choice (string.hexdigits)
— eemz

1
कोई भी अधिक क्रिप्टोग्राफिक रूप से सुरक्षित पसंद कर सकता हैrandom.SystemRandom().choice
— ब्रायन एम। हंट

1
xrange () रेंज होनी चाहिए () - NameError: नाम 'xrange' परिभाषित नहीं है
— कालेब

xth सही है (और आमतौर पर बेहतर है) अजगर में 2.x
— jcdyer

25

नाटकीय रूप से उन लोगों की तुलना में तेजी से समाधान:

timeit("'%0x' % getrandbits(30 * 4)", "from random import getrandbits")
0.8056681156158447

एक उपयोगकर्ता को सटीक आधार रेखा प्राप्त करने के लिए एक ही मशीन पर सभी तरीकों का प्रयास करना होगा। हार्डवेयर स्पेक्स एक बड़ा बदलाव ला सकते हैं। >>>> timeit.timeit ("'% 0x'% getrandbits (30 * 4)", "यादृच्छिक आयात getrandbits से") 0.24712469499993 </ pre>
— ptay

धन्यवाद, यह दूसरों की तुलना में बहुत तेजी से ऊपर है। %timeit '%030x' % randrange(16**30)1000000 लूप देता है, सर्वश्रेष्ठ 3: 1.61 µ प्रति लूप जबकि %timeit '%0x' % getrandbits(30 * 4)1000000 लूप देता है, सर्वश्रेष्ठ 3: 396 एनएस प्रति लूप
— frmdstryr

15

नोट: random.choice(string.hexdigits)गलत है, क्योंकि string.hexdigitsरिटर्न 0123456789abcdefABCDEF(लोअरकेस और अपरकेस दोनों), इसलिए आपको एक पक्षपाती परिणाम मिलेगा, जिसमें हेक्स अंक 'सी' दो बार अंक '7' के रूप में दिखाई देगा। इसके बजाय, बस उपयोग करें random.choice('0123456789abcdef')।


6

एक अन्य विधि:

from Crypto import Random
import binascii

my_hex_value = binascii.hexlify(Random.get_random_bytes(30))

मुद्दा यह है: बाइट मान हमेशा हेक्स में मूल्य के बराबर होता है ।


5

एक-पंक्ति समारोह:

import random
import string

def generate_random_key(length):
    return ''.join(random.choice(string.ascii_lowercase + string.digits) for _ in range(length))

print generate_random_key(30)

3
In [1]: import random                                    

In [2]: hex(random.getrandbits(16))                      
Out[2]: '0x3b19'

FYI करें: इस उत्तर को निम्न-गुणवत्ता के रूप में चिह्नित किया गया था, आप इसे सुधारना चाह सकते हैं।
— ओगुज़ेमेल

सुधार के लिए कोई सुझाव?
— बॉब

कोई जानकारी नहीं। मैंने सोचा था कि आपको पता होना चाहिए कि
— ओगुज़ इस्माइल

2

संयोग से, यह timeitसुझाए गए दो दृष्टिकोणों पर उपयोग करने का परिणाम है :

का उपयोग कर random.choice():

>>> t1 = timeit.Timer("''.join(random.choice(string.hexdigits) for n in xrange(30))", "import random, string")
>>> t1.timeit()
69.558588027954102

का उपयोग कर binascii.b2a_hex():

>>> t2 = timeit.Timer("binascii.b2a_hex(os.urandom(15))", "import os, binascii")
>>> t2.timeit()
16.288421154022217

2

Jcdyer ने जो उल्लेख किया है उसकी तुलना में एक तेज़ है। यह उसकी सबसे तेज़ विधि का ~ 50% हिस्सा है।

from numpy.random.mtrand import RandomState
import binascii
rand = RandomState()

lo = 1000000000000000
hi = 999999999999999999
binascii.b2a_hex(rand.randint(lo, hi, 2).tostring())[:30]

>>> timeit.Timer("binascii.b2a_hex(rand.randint(lo,hi,2).tostring())[:30]", \
...                 'from __main__ import lo,hi,rand,binascii').timeit()
1.648831844329834         <-- this is on python 2.6.6
2.253110885620117         <-- this on python 2.7.5

यदि आप base64 में चाहते हैं:

binascii.b2a_base64(rand.randint(lo, hi, 3).tostring())[:30]

आप अपनी आवश्यकता के आधार पर आउटपुट लंबाई को अलग करने के लिए रैंडिंट (अंतिम arg) को दिए गए आकार पैरामीटर को बदल सकते हैं। तो, एक 60 चार के लिए:

binascii.b2a_hex(rand.randint(lo, hi, 4).tostring())[:60]

थोड़ी भिन्नता: binascii.b2a_hex(np.random.rand(np.ceil(N/16)).view(dtype=int))[:N]जहां N=30।
— डैन-मैन

@ डैन-मैन इस वैकल्पिक विधि के लिए धन्यवाद। हालाँकि, मुझे लगता है कि यह कम से कम 5 गुना अधिक खपत करता है। क्या आप उस पर भी गौर करते हैं?
— एथन

0

उस मिश्रण का एक और उत्तर जोड़ना जो @eemz समाधान की तुलना में तेज़ी से कार्य करता है और पूरी तरह से अल्फ़ान्यूमेरिक भी है। ध्यान दें कि यह आपको एक हेक्सिडेसिमल उत्तर नहीं देता है।

import random
import string

LETTERS_AND_DIGITS = string.ascii_letters + string.digits

def random_choice_algo(width):
  return ''.join(random.choice(LETTERS_AND_DIGITS) for i in range(width))

def random_choices_algo(width):
  return ''.join(random.choices(LETTERS_AND_DIGITS, k=width))


print(generate_random_string(10))
# prints "48uTwINW1D"

एक त्वरित बेंचमार्क पैदावार

from timeit import timeit
from functools import partial

arg_width = 10
print("random_choice_algo", timeit(partial(random_choice_algo, arg_width)))
# random_choice_algo 8.180561417000717
print("random_choices_algo", timeit(partial(random_choices_algo, arg_width)))
# random_choices_algo 3.172438014007639

0

यह सुनिश्चित करने के लिए है कि सबसे हल्का संस्करण नहीं है, लेकिन यह यादृच्छिक है और यह उस वर्णमाला / लंबाई को समायोजित करना आसान है जिसे आप चाहते हैं:

import random

def generate(random_chars=12, alphabet="0123456789abcdef"):
    r = random.SystemRandom()
    return ''.join([r.choice(alphabet) for i in range(random_chars)])
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.