faster geometric average on ASCII
Question: Is it possible to speed up the following code, but without using external
modules (NumPy, etc)? Just plain Python. Two lines of thought: speeding the
computation in

    
    
    chr(int(round( multiplOrds**(1.0/DLen), 0) ) )
    

or faster building of the desired structure. The aim is to find the geometric
average of an ord() of an ASCII symbol and report it as a round value
(symbol). The len(InDict) is anything above 1. The outcome of the example
should be

    
    
    KM<I
    

The code:

    
    
    def GA():
        InStr="0204507890"
        InDict={
           0:"ABCDEFGHIJ",
           1:"KLMNOPQRST",
           2:"WXYZ#&/()?"
           }
    
        OutStr = ""
    
        DLen = len(InDict)
        for pos in zip(InStr, *InDict.values()):
            if pos[0]=="0":
                multiplOrds = 1
                for mul in (ord(char) for char in pos[1:] if char!="!"): multiplOrds*=mul
                OutStr+= chr(int(round( multiplOrds**(1.0/DLen), 0) ) )
    
        return OutStr
    
    if __name__ == '__main__':
        import timeit
        print(timeit.timeit("GA()", setup="from __main__ import GA"))
    


Answer: A first thought:

Concatenating strings is slow as they are immutable, therefore each
modification results in creating a new copied instance. That's why you should
not do things like:

    
    
    s = ""
    for i in range(1000000):
        s += chr(65)
    

Each loop it will create a new string instance being one character larger than
the previous, the old instance will remain until the Garbage Collector kicks
in. Also allocating memory is slow.

Using a generator expression to store the partial strings and joining them
together in the end is about twice as fast and shorter to code:

    
    
    s = "".join(chr(65) for i in range(1000000))
    

