3
\$\begingroup\$

I have a python print statement and inside the string I wish to print are four digits. I would like to apply the same formatting function to each param. I am not familiar with the latest and greatest features of python PEPs.

Is there a slick way to do this?

Code

statement = "Splitting up the {} file into {} chunks, with the filesystem block size of {}, causing {} extra space to be used" print(statement.format( sizeof_fmt(input_file_size), sizeof_fmt(chunk_size), sizeof_fmt(block_size), sizeof_fmt(surrendered_space))) 

Format Function

def sizeof_fmt(num, suffix='B'): for unit in ['','Ki','Mi','Gi','Ti','Pi','Ei','Zi']: if abs(num) < 1024.0: return "%3.1f%s%s" % (num, unit, suffix) num /= 1024.0 return "%.1f%s%s" % (num, 'Yi', suffix) 
\$\endgroup\$
3
  • 1
    \$\begingroup\$This is not really a code review type question, and would be better asked on StackOverflow. But the slick way you are looking for is the map() function.\$\endgroup\$
    – AJNeufeld
    CommentedJun 17, 2019 at 16:29
  • \$\begingroup\$@AJNeufeld - I have been told something here - codereview.stackexchange.com/questions/222292/…. Is it true?\$\endgroup\$
    – Justin
    CommentedJun 18, 2019 at 2:33
  • 3
    \$\begingroup\$@Justin Ah. PEP 279 ... written in 2002, contains no mention of deprecating map, but a comment by GvR on the PEP suggested it should die. A discussion in 2005 suggested it might be gone by Python 3.0 ... which was released in December 2008. Now it is 11 years later, and I still see no signs of map being deprecated. True: you can use list comprehension instead of map, and in some cases it might be faster and clearer, but in others it can be slower and/or less clear. YMMV, but I don’t expect map will ever go away.\$\endgroup\$
    – AJNeufeld
    CommentedJun 18, 2019 at 4:19

1 Answer 1

2
\$\begingroup\$

Time will tell if your question is considered a worthy Code Review question, but till then I'ld like you to give a short review on your code nevertheless.

Format function

You could reduce the code duplication in the format function and make use of .format or f-strings (from Python 3.6 onwards).

def sizeof_fmt_rev(num, suffix='B'): for unit in ['', 'Ki', 'Mi', 'Gi', 'Ti', 'Pi', 'Ei', 'Zi']: if abs(num) < 1024.0: break num /= 1024.0 else: # this part is only executed if the loop was not left with a break unit = 'Yi' return f"{num:.1f}{unit}{suffix}" 

This uses for ... else, one of the less well-known features of Python and only has a single line where the format expression has to be written. I see a chance to build something using math.log instead of that loop, but I will leave that as an exercise to you. You can even build something that works without a loop, but at least the version I came up with (found below) is actually slower than the original implementation.

def sizeof_fmt_rev_log(num, suffix='B'): exponent = min(int(math.log(abs(num), 1024)), 8) num /= 1024**exponent unit = ('', 'Ki', 'Mi', 'Gi', 'Ti', 'Pi', 'Ei', 'Zi', 'Yi')[exponent] return f"{num:.1f}{unit}{suffix}" 

I used

for i in range(10): num = 3.8 * 1024**i print(sizeof_fmt_rev(num)) assert sizeof_fmt(num) == sizeof_fmt_rev(num) assert sizeof_fmt(-num) == sizeof_fmt_rev(-num) 

to test the revised version.

Code

As @AJNeufeld mentions in his comment, you could use map to save yourself some typing

print( statement.format(*map(sizeof_fmt, (input_file_size, chunk_size, block_size, surrendered_space))) ) 

which is functionally equivalent to using a list comprehension:

print( statement.format(*[ sizeof_fmt(i) for i in (input_file_size, chunk_size, block_size, surrendered_space) ]) ) 

Both build upon a technique called tuple unpacking, but as you can see it can also be used with lists, other sequences, and maybe also iterables (if it is a generator, it will be consumed - thanks @Graipher, who confirmed it/pointed it out in a comment).

\$\endgroup\$
1
  • \$\begingroup\$Tuple unpacking can indeed be used with any iterable. It will be consumed by it if it is a generator.\$\endgroup\$
    – Graipher
    CommentedJun 19, 2019 at 14:53

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.