将字符串的每个字母随机大写的代码(代码清理帮助)

The*_*hin 5 python

我是一名初级编码员,我最近创建了一个函数,该函数接受一个字符串并随机将每个字母大写。

def rand_upper(string):
    import random
    strList = [l for l in string.lower()] 
    newList = []
    for i in strList:
        j = random.randrange(2)
        if j == 1:
            letter = i.upper()
            newList.append(letter)
        else:
            newList.append(i)
    return "".join(newList)
Run Code Online (Sandbox Code Playgroud)

该代码按我的意图工作,但是有什么方法可以使此代码更清晰吗?我个人认为这很难阅读。有没有其他方法可以压缩代码以使其更具可读性/效率?谢谢!

sup*_*ain 7

使用choice代替,lower并且upper只调用一次。

from random import choice

def rand_upper(string):
    return ''.join(map(choice, zip(string.lower(), string.upper())))
Run Code Online (Sandbox Code Playgroud)

更好的是,正如彼得评论的那样

def rand_upper(string):
    return ''.join(map(choice, zip(string, string.swapcase())))
Run Code Online (Sandbox Code Playgroud)

另一个,基于Olvin_Roght 的

def rand_upper(string):
    return ''.join([c if getrandbits(1) else c.swapcase() for c in string])
Run Code Online (Sandbox Code Playgroud)

还有两个,混合我们迄今为止最快的解决方案:

def rand_upper(string):
    return ''.join([c if getrandbits(1) else d
                    for c, d in zip(string, string.swapcase())])
Run Code Online (Sandbox Code Playgroud)
def rand_upper(string):
    return ''.join([z[getrandbits(1)] for z in zip(string, string.swapcase())])
Run Code Online (Sandbox Code Playgroud)

基准使用string = rand_upper('a' * 1000)

739 ?s  797 ?s  725 ?s  original
764 ?s  787 ?s  693 ?s  original_2
713 ?s  691 ?s  680 ?s  Samwise
699 ?s  657 ?s  682 ?s  theCoder
477 ?s  486 ?s  490 ?s  superb_rain
520 ?s  476 ?s  489 ?s  Peter_Wood
135 ?s  131 ?s  141 ?s  based_on_Olvin_Roght
120 ?s  113 ?s  121 ?s  superb_Peter_Olvin
125 ?s  117 ?s  118 ?s  superb_Peter_Olvin_2
Run Code Online (Sandbox Code Playgroud)

(不包括 Olvin 的原始版本,因为它是唯一一个具有二次而非线性时间的版本,因此与单一尺寸的比较会产生误导。)

代码:

from timeit import repeat
from random import randrange, choice, getrandbits

def original(string):
    import random
    strList = [l for l in string.lower()] 
    newList = []
    for i in strList:
        j = random.randrange(2)
        if j == 1:
            letter = i.upper()
            newList.append(letter)
        else:
            newList.append(i)
    return "".join(newList)

def original_2(string):
    strList = [l for l in string.lower()] 
    newList = []
    for i in strList:
        j = randrange(2)
        if j == 1:
            letter = i.upper()
            newList.append(letter)
        else:
            newList.append(i)
    return "".join(newList)

def Samwise(string: str) -> str:
    return "".join(
        c.upper() if randrange(2) else c.lower() 
        for c in string
    )

def theCoder(string):
    return ''.join(choice((str.upper, str.lower))(c) for c in string)

def superb_rain(string):
    return ''.join(map(choice, zip(string.lower(), string.upper())))

def Peter_Wood(string):
    return ''.join(map(choice, zip(string, string.swapcase())))

def based_on_Olvin_Roght(string):
    return ''.join([c if getrandbits(1) else c.swapcase() for c in string])

def superb_Peter_Olvin(string):
    return ''.join([c if getrandbits(1) else d for c, d in zip(string, string.swapcase())])

def superb_Peter_Olvin_2(string):
    return ''.join([z[getrandbits(1)] for z in zip(string, string.swapcase())])

funcs = original, original_2, Samwise, theCoder, superb_rain, Peter_Wood, based_on_Olvin_Roght, superb_Peter_Olvin, superb_Peter_Olvin_2

string = original('a' * 1000)
number = 1000

tss = [[] for _ in funcs]
for _ in range(4):
    for func, ts in zip(funcs, tss):
        t = min(repeat(lambda: func(string), number=number)) / number
        ts.append(t)
        print(*('%d ?s ' % (1e6 * t) for t in ts[1:]), func.__name__)
    print()
Run Code Online (Sandbox Code Playgroud)


Sam*_*ord 3

掌握生成器表达式是使代码更短的好方法:

from random import randrange

def rand_upper(string: str) -> str:
    return "".join(
        c.upper() if randrange(2) else c.lower() 
        for c in string
    )
Run Code Online (Sandbox Code Playgroud)
>>> rand_upper("Sphinx of black quartz, witness my vow!")
'sPhiNx of BlacK qUARTz, wiTnEsS mY VOw!'
Run Code Online (Sandbox Code Playgroud)

一般的技巧是,每当您通过append一次 ing 一个元素来构建列表时,可能有一种方法可以更简单地作为列表理解来完成它,即编写一个生成列表中每个元素的表达式。

如果您实际上没有返回列表,而是将其传递给接受任何可迭代的函数(例如str.join),则可以省略列表部分( )[]并将生成器表达式直接传递给该函数。

  • 实际上,使用“str.join”[传递列表比生成器更好](/sf/answers/634271711/) (3认同)