![]() |
Script optimisation and style help - Printable Version +- Python Forum (https://python-forum.io) +-- Forum: General (https://python-forum.io/forum-1.html) +--- Forum: Code sharing (https://python-forum.io/forum-5.html) +--- Thread: Script optimisation and style help (/thread-16204.html) |
Script optimisation and style help - TheFluffyOne - Feb-18-2019 As a long-time Perl coder, I've picked up loads of optimisations and style tips that make scripts easier to understand, shorter, and more efficient. I occasionally dabble in Python and typically end up brute-forcing some code together using the basic Python capabilities, often thinking how I'd write the script in Perl and then working out the Python equivalent methods. I recently wrote a script to reverse-engineer sample sizes from published percentages, and I suspect it's particularly bad since I directly translated some JavaScript into Python for one of the key functions. If anyone is able to offer advice on how to improve the script and make it more optimised and Pythonic, I'd be very grateful! I'm working with Python 3.7 simply because it's recent, and not because of any particular attachment to Python 3 over Python 2. # Determine minimum likely values based on provided percentages import math digit_accuracy = 2 results = {} #percentages = [ 4.71, 20.00, 42.35, 32.94 ] percentages = [ 8.57, 5.71, 2.86, 20.00, 14.29, 17.14, 20.00, 5.71, 5.71 ] # Calculate Greatest Common Divisor of two numbers # Based on code from https://www.programiz.com/python-programming/examples/lcm def gcd(x, y): while(y): x, y = y, x % y return x # Calculate Least Common Multiple of two numbers # Based on code from https://www.programiz.com/python-programming/examples/lcm def lcm(x, y): return ((x * y) // gcd(x, y)) # Use continued fraction method to calculate simplest fraction that represents provided decimal at given precision (decimal places) # Based on the JavaScript version at http://jonisalonen.com/2012/converting-decimal-numbers-to-ratios/ def estimate_fraction(decimal_value, decimal_precision): #print("Estimating fractions for", decimal_value) desired_result = round(decimal_value * 100, decimal_precision) h1 = 1 h2 = 0 k1 = 0 k2 = 1 b = decimal_value while True: a = math.floor(b) aux = h1 h1 = (a * h1) + h2 h2 = aux aux = k1 k1 = (a * k1) + k2 k2 = aux rounded_result = round(((h1 * 100) / k1), decimal_precision) if (rounded_result == desired_result): break b = 1 / (b - a) return [h1, k1] # ------------------- MAIN ------------------- def main(): lowest_denominator = 0 for item in percentages: # Find a fraction to estimate the current percentage to the given number of decimal places accuracy [numerator, denominator] = estimate_fraction((item / 100), digit_accuracy) results[item] = [numerator, denominator] # Find the lowest common multiple for the fraction denominators up to this point if (lowest_denominator == 0): lowest_denominator = denominator else: lowest_denominator = lcm(denominator, lowest_denominator) running_total = 0 for x in percentages: [numerator, denominator] = results[x] # Convert all fractions to a common denominator (which should be the sample size) if (denominator != lowest_denominator): multiplier = lowest_denominator / denominator numerator *= multiplier denominator *= multiplier running_total += numerator # Display summary of the calculated values for this entry calculated_percentage = round(((numerator * 100) / denominator), digit_accuracy) print(int(numerator), " / ", int(denominator), " = ", calculated_percentage, "% (Requested: ", x, "%)", sep="") # Print some summary information to help determine if the estimated sample size is sensible print("\nTotal", int(running_total), "items represented of", lowest_denominator) print("Percentages sum to ", round(sum(percentages), digit_accuracy), "%", sep="") # ---------- ENTRY POINT ---------- if __name__ == '__main__': main() RE: Script optimisation and style help - ichabod801 - Feb-18-2019 I just have style comments. First, your comments before the functions should be done as triple quoted strings right after the def line. That way they become __docstring__ attributes of the function. That is what is displayed when you do help(function) in the interpreter. Second, learn string formatting, either the format method of strings, or the even newer f-string syntax (Python 3.6+).
RE: Script optimisation and style help - buran - Feb-18-2019 Also no need of brackets, e.g. in following cases
RE: Script optimisation and style help - TheFluffyOne - Feb-18-2019 (Feb-18-2019, 04:08 PM)ichabod801 Wrote: I just have style comments. First, your comments before the functions should be done as triple quoted strings right after the def line. That way they become __docstring__ attributes of the function. That is what is displayed when you do Fantastic, thank you!(Feb-18-2019, 04:28 PM)buran Wrote: Also no need of brackets, e.g. in following casesThose are definitely a Perl-ism ![]() RE: Script optimisation and style help - buran - Feb-18-2019 by the way, if you don't want to implement gcd(), there is math.gcd() |