Commit a06146f
authored
fix: vim.eval should treat Vim boolean as Python bool #603
Problem:
- In Nvim, Vim bool is evaled to string, but in Vim 8+, it is evaled to
Python bool. So pynvim's legacy vim.eval is not compatible with Vim
8+.
- Previously, the argument against compatibility with Vim 8+ in this
aspect is that adding checking for Python bool would be slower. But if
we use `type(obj)` with operator `is`, it would be 3% ~ 80% faster
than the current num_to_str implementation (more complex obj seems to
have more performance gain).
This is the script I use to benchmark
```python
import timeit
num_types = (int, float)
def num_to_str(obj):
if isinstance(obj, num_types):
return str(obj)
else:
return obj
def num_to_str2(obj):
obj_type = type(obj)
if obj_type is int or obj_type is float:
return str(obj)
else:
return obj
def num_to_str3(obj):
obj_type = type(obj)
if obj_type == int or obj_type == float:
return str(obj)
else:
return
test_cases = [
(100, "Integer"),
(10.5, "Float"),
(True, "Boolean"),
("hello", "String"),
([1, 2], "List"),
({'a': 1, 'b': 2}, "Dict"), # Restored!
]
def run_benchmark():
# Using a fixed format string for perfect alignment
fmt = "{:<15} | {:<10} | {:<18} | {:<18} | {:>9}"
header = fmt.format("Input", "Type", "isinstance (s)",
"type is (s)", "type == (s)")
print("\n" + header)
print("-" * len(header))
for val, label in test_cases:
setup = "from __main__ import num_to_str, num_to_str2, num_types"
# Number of loops: 1,000,000
t1 = timeit.timeit("num_to_str(obj)", setup=setup,
number=1_000_000, globals={'obj': val, **globals()})
t2 = timeit.timeit("num_to_str2(obj)", setup=setup,
number=1_000_000, globals={'obj': val, **globals()})
t3 = timeit.timeit("num_to_str3(obj)", setup=setup,
number=1_000_000, globals={'obj': val, **globals()})
display_val = str(val)
if len(display_val) > 14:
display_val = display_val[:11] + "..."
print(fmt.format(display_val, label, f"{t1:.4f}",
f"{t2:.4f}", f"{t3:.4f}"))
if __name__ == "__main__":
run_benchmark()
```
And the benchmark result:
```
Input | Type | isinstance (s) | type is (s) | type == (s)
------------------------------------------------------------------------------------
100 | Integer | 0.1125 | 0.1095 | 0.1118
10.5 | Float | 0.3256 | 0.2512 | 0.2791
True | Boolean | 0.0731 | 0.0604 | 0.0788
hello | String | 0.1005 | 0.0600 | 0.0793
[1, 2] | List | 0.0940 | 0.0602 | 0.0755
{'a': 1, 'b... | Dict | 0.1080 | 0.0599 | 0.0759
```
So clearly using `type(obj)` with `is` is the fastest way.
Solution:
- Use type(obj) with is operator is to check for exact number1 parent fdaae82 commit a06146f
2 files changed
Lines changed: 2 additions & 4 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
63 | 63 | | |
64 | 64 | | |
65 | 65 | | |
66 | | - | |
67 | | - | |
68 | | - | |
69 | 66 | | |
70 | 67 | | |
71 | 68 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
195 | 195 | | |
196 | 196 | | |
197 | 197 | | |
198 | | - | |
| 198 | + | |
| 199 | + | |
199 | 200 | | |
200 | 201 | | |
201 | 202 | | |
| |||
0 commit comments