Reputation: 3903
Say I have a variable in python called my_boolean = False
I want an end result to be: my_bool = "0"
The only way i can think of doing this is.
my_bool = str(int(my_boolean))
, a double type-casting.
Is there a better way of doing this? Disadvantages? Advantages? What happens internally?
Upvotes: 1
Views: 1590
Reputation: 101929
Never assume performances of operations. Profile and benchmark:
In [7]: value = False
In [8]: %%timeit bool_dict = {False: '0', True: '1'}
...: my_boolean = bool_dict[value]
...:
10000000 loops, best of 3: 47.7 ns per loop
In [9]: %timeit my_boolean = str(int(value))
1000000 loops, best of 3: 420 ns per loop
In [10]: %timeit my_boolean = '0' if value is False else '1'
10000000 loops, best of 3: 50 ns per loop
In [11]: %timeit my_boolean = '01'[value]
10000000 loops, best of 3: 52.1 ns per loop
As you can see the str(int(value))
is much slower than the rest because function calls have high overhead.
Note how the branching operation is mostly equal to the dictionary look-up[try it a few times and you'll see the two versions exchange timings], but it's more readable, so use it.
I personally find the conditional expression version easier to read than the original str(int(value))
, even though there isn't anything inherently wrong with using two conversions, and in other situations this may be the easier solution.
The version '01'[value]
is the fastest, but I believe you should prefer readability over performances, especially if you did not prove that this conversion is the bottleneck.
Note that using an identifier instead of the explicit constant False
I discovered that this:
'01'[False]
Is optimized by the interpreter to the expression "0"
:
In [14]: import dis
In [16]: def test():
...: a = '01'[False]
In [17]: dis.dis(test)
2 0 LOAD_CONST 3 ('0')
3 STORE_FAST 0 (a)
6 LOAD_CONST 0 (None)
9 RETURN_VALUE
Hence the benchmark I did before wasn't correct.
Upvotes: 1
Reputation: 129507
You could try
my_bool = '01'[my_boolean]
There seems to be a time difference between your approach and what is above:
>>> from timeit import timeit
>>> timeit("'01'[b]", "b = False")
0.10460775769296968
>>> timeit("str(int(b))", "b = False")
0.8879351199904466
Is it something to lose sleep over? Definitely not. I'm sure there are people who would call your current approach more Pythonic and prefer that over this. In other words, no, there is nothing wrong with what you're doing.
Upvotes: 3
Reputation: 3542
Could use a dictionary mapping like this:
bool_dict = { False : '0', True : '1' }
my_boolean = bool_dict[False]
Not sure if it is more efficient, I would imagine so since it is just hash look up in a map, generally an O(1) operation.
Upvotes: 1