Try the following:
word="this is a lower case string" caps = word.upper() ''.join(x[random.randint(0,1)] for x in zip(word, caps))
This should outperform your version because it raises far fewer upper calls and because, more importantly, it avoids the sequential O (N ^ 2) additions that you used in the loop version.
With the change of the question, you will need to create both lowercase and uppercase versions:
word="This is a MixeD cAse stRing" caps = word.upper() lowers = word.lower() ''.join(random.choice(x) for x in zip(caps, lowers))
As suggested by Tim Pitzker in the comments, I used random.choice to select the letters from the tuples created by the zip call.
Since the question has been modified to focus more on speed, the fastest approach would probably be to use Numpy:
''.join(numpy.where(numpy.random.randint(2, size=len(caps)), list(caps), list(lowers)))
source share