why is %s faster than %d for integer substitution in python?

  • Last Update :
  • Techknowledgy :

The str() implementation for ints is in int_to_decimal_string in (Objects/intobject.c) and it's incredibly simple:

do {
   *--p = '0' + (char)(absn % 10);
   absn /= 10;
} while (absn);

The code for formatint is way more complex, and it contains two call to the native snprintf:

PyOS_snprintf(fmt, sizeof(fmt), "%s%%%s.%dl%c",
   sign, (flags & F_ALT) ? "#" : "",
   prec, type);
// ...
PyOS_snprintf(buf, buflen, fmt, -x);

Suggestion : 2

Last Updated : 24 Jan, 2021,GATE CS 2021 Syllabus


Hey, Geek!


Using %d
Traceback (most recent call last):
File "<string>", line 4, in <module>
      TypeError: %d format: a number is required, not str

Suggestion : 3

Local variables are faster than globals; if you use a global constant in a loop, copy it to a local variable before the loop. And in Python, function names (global or built-in) are also global constants! ,Small is beautiful. Given Python's hefty charges for bytecode instructions and variable look-up, it rarely pays off to add extra tests to save a little bit of work. ,Sure, I replied, but it does so at the cost of a function call (the lambda function) per list item. I betcha it's slower, since function call overhead in Python is bigger than for loop overhead. ,This led us to consider a compromise, which wouldn't waste extra space, but which would speed up the lookup for the chr() function:

The first version I came up with was totally straightforward:

    def f1(list):
       string = ""
    for item in list:
       string = string + chr(item)
    return string

That can't be the fastest way to do it, said my friend. How about this one:

    def f2(list):
       return reduce(lambda string, item: string + chr(item), list, "")

Hmm, said my friend. I need this to be faster. OK, I said, how about this version:

    def f3(list):
       string = ""
    for character in map(chr, list):
       string = string + character
    return string

There's a general technique to avoid quadratic behavior in algorithms like this. I coded it as follows for strings of exactly 256 items:

    def f5(list):
       string = ""
    for i in range(0, 256, 16): # 0, 16, 32, 48, 64, ...
       s = ""
    for character in map(chr, list[i: i + 16]):
       s = s + character
    string = string + s
    return string

Finally, I tried a radically different approach: use only implied loops. Notice that the whole operation can be described as follows: apply chr() to each list item; then concatenate the resulting characters. We were already using an implied loop for the first part: map(). Fortunately, there are some string concatenation functions in the string module that are implemented in C. In particular, string.joinfields(list_of_strings, delimiter) concatenates a list of strings, placing a delimiter of choice between each two strings. Nothing stops us from concatenating a list of characters (which are just strings of length one in Python), using the empty string as delimiter. Lo and behold:

    import string
    def f6(list):
       return string.joinfields(map(chr, list), "")

Suggestion : 4

If i or j is negative, the index is relative to the end of sequence s: len(s) + i or len(s) + j is substituted. But note that -0 is still 0.,Return the number of non-overlapping occurrences of subsequence sub in the range [start, end]. Optional arguments start and end are interpreted as in slice notation.,There are three basic sequence types: lists, tuples, and range objects. Additional sequence types tailored for processing of binary data and text strings are described in dedicated sections.,This table lists the sequence operations sorted in ascending priority. In the table, s and t are sequences of the same type, n, i, j and k are integers and x is an arbitrary object that meets any type and value restrictions imposed by s.

>>> n = -37 >>>
'-0b100101' >>>
def bit_length(self):
   s = bin(self) # binary representation: bin(-37) -- > '-0b100101'
s = s.lstrip('-0b') # remove leading zeros and minus sign
return len(s) # len('100101') -- > 6
>>> n = 19 >>>
'0b10011' >>>
def bit_count(self):
   return bin(self).count("1")
>>> (1024).to_bytes(2, byteorder = 'big')
b '\x04\x00' >>>
   (1024).to_bytes(10, byteorder = 'big')
b '\x00\x00\x00\x00\x00\x00\x00\x00\x04\x00' >>>
   (-1024).to_bytes(10, byteorder = 'big', signed = True)
b '\xff\xff\xff\xff\xff\xff\xff\xff\xfc\x00' >>>
   x = 1000 >>>
   x.to_bytes((x.bit_length() + 7) // 8, byteorder='little')
      b '\xe8\x03'
>>> int.from_bytes(b '\x00\x10', byteorder = 'big')
   int.from_bytes(b '\x00\x10', byteorder = 'little')
   int.from_bytes(b '\xfc\x00', byteorder = 'big', signed = True) -
   1024 >>>
   int.from_bytes(b '\xfc\x00', byteorder = 'big', signed = False)
   int.from_bytes([255, 0, 0], byteorder = 'big')