green-code-initiative / ecoCode-challenge

Emboard in the hackhatons serie for improving ecoCode
3 stars 4 forks source link

[Python] Prefer using builtins functions (team 904000m2) #47

Open LordPatate opened 1 year ago

LordPatate commented 1 year ago

Detects patterns that mimic the behavior of builtins

Simple if / else blocks

Abs

# Non compliant
x if x > 0 else -x
# Non compliant
if x > 0:
  return x
else:
  return -x
# Compliant
abs(x)

Bool

# Non compliant
True if x else False
# Non compliant
if x:
  return True
else:
  return False
# Compliant
bool(x)

Functions taking an iterable as argument

All

# Non compliant
for element in iterable:
    if not element:
        return False
return True
# Compliant
all(iterable)

Any

# Non compliant
for element in iterable:
    if element:
        return True
return False
# Compliant
any(iterable)

Filter

# Non compliant
my_list = []
for element in iterable:
    if function(element):
        my_list.append(element)
# Compliant
filter(function, iterable)

Len

# Non compliant
count = 0
for element in iterable:
    count += 1
# Compliant
len(iterable)

Map

# Non compliant
my_list = []
for element in iterable:
    new_item = function(element)
    my_list.append(new_item)
# Non compliant
for element in iterable:
    function(element)
# Compliant
map(function, iterable)

Max

# Non compliant
max_value = None
for element in iterable:
    if max_value is None or element > max_value:
        max_value = element
# Compliant
max(iterable)

Min

# Non compliant
min_value = None
for element in iterable:
    if min_value is None or element < min_value:
        min_value = element
# Compliant
min(iterable)

Sum

# Non compliant
count = 0
for element in iterable:
    count += element
# Compliant
sum(iterable)

Index

# Non compliant
for i, element in enumerate(iterable):
    if element is searched_element:
        return i
raise ValueError
# Compliant
iterable.index(searched_element)

Count

# Non compliant
count = 0
for element in iterable:
    if element is searched_element:
        count += 1
# Compliant
iterable.count(searched_element)

Recognizable sorting algorithm

Most developers learned the most known sorting algorithms (selection, bubble, insertion, heap, merge, quick...) either for practice or for job interviews. They should not re-implement those but use the sorted() or list.sort() methods instead.

LordPatate commented 1 year ago

Could also add:

Operators

# Non compliant
for element in iterable:
    if element is x:
        return True
return False
# Compliant
x in iterable
LordPatate commented 1 year ago

Set operators

a = [1,2,3,4,5]
b = [2,3,4,5,6]

overlaps = []
for x in a:
  for y in b:
    if x==y:
      overlaps.append(x)

print(overlaps)

This will print the list [2, 3, 4, 5]. The number of comparisons here will get very large, very quickly.

Another approach would be:

a = [1,2,3,4,5]
b = [2,3,4,5,6]

overlaps = set(a) & set(b)

print(overlaps)

This will print the dictionary {2, 3, 4, 5}. You’re leaning on the built-in functions and getting a big speed and memory bump as a result.

LordPatate commented 1 year ago

Enumerate

# Non-compliant
for i in range(len(iterable)):
  element = iterable[i]
  ...
# Non-compliant
i = 0
for element in iterable:
  ...
  i += 1
# Compliant
for i, element in enumerate(iterable):
  ...
LordPatate commented 1 year ago

Usage of itertools standard module

Product

fruits = ["apple", "orange", "peach"]
sizes = ["small", "medium", "big"]
# Non-compliant
for fruit in fruits:
  for size in sizes:
    print(fruit, size)
# Better but not optimal
product = (
  (fruit, size)
  for fruit in fruits
  for size in sizes
)
for fruit, size in product:
  print(fruit, size)
# Compliant
import itertools
for fruit, size in itertools.product(fruits, sizes):
  print(fruit, size)
LordPatate commented 1 year ago

\newpage

Optimized API: Favor use of Python builtins

Platform

OS OS version Langage
- - Python

Main caracteristics

ID Title Category Sub-category
{id} Favor use of Python builtins Environment Optimized API

Severity / Remediation Cost

Severity Remediation Cost
Minor Easy

Rule short description

Rule complete description

Text

Because built-in functions are typically implemented in C or C++, they are faster and more efficient than equivalent Python code. They should always be preferred over writing Python code that accomplishes the same.

HTML

<p>Because built-in functions are typically implemented in C or C++, they are faster and more efficient than equivalent Python code.</p>
<p>They should always be preferred over writing Python code that accomplishes the same.</p>
<h2 id="abs">Abs</h2>
<h3 id="non-compliant-1">Non compliant #1</h3>
<pre><code class="lang-python">x <span class="hljs-keyword">if</span> x &gt; <span class="hljs-number">0</span> <span class="hljs-keyword">else</span> -x
</code></pre>
<h3 id="non-compliant-2">Non compliant #2</h3>
<pre><code class="lang-python"><span class="hljs-keyword">if</span> x &gt; <span class="hljs-number">0</span>:
  <span class="hljs-keyword">return</span> x
<span class="hljs-keyword">else</span>:
  <span class="hljs-keyword">return</span> -x
</code></pre>
<h3 id="compliant">Compliant</h3>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-title">abs</span><span class="hljs-params">(x)</span></span>
</code></pre>
<h2 id="bool">Bool</h2>
<h3 id="non-compliant-1">Non compliant #1</h3>
<pre><code class="lang-python"><span class="hljs-literal">True</span> <span class="hljs-keyword">if</span> x <span class="hljs-keyword">else</span> <span class="hljs-literal">False</span>
</code></pre>
<h3 id="non-compliant-2">Non compliant #2</h3>
<pre><code class="lang-python"><span class="hljs-keyword">if</span> x:
  <span class="hljs-keyword">return</span> <span class="hljs-literal">True</span>
<span class="hljs-keyword">else</span>:
  <span class="hljs-keyword">return</span> <span class="hljs-literal">False</span>
</code></pre>
<h3 id="compliant">Compliant</h3>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-title">bool</span><span class="hljs-params">(x)</span></span>
</code></pre>
<h2 id="all">All</h2>
<h3 id="non-compliant">Non compliant</h3>
<pre><code class="lang-python"><span class="hljs-keyword">for</span> element <span class="hljs-keyword">in</span> iterable:
    <span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> element:
        <span class="hljs-keyword">return</span> <span class="hljs-literal">False</span>
<span class="hljs-keyword">return</span> <span class="hljs-literal">True</span>
</code></pre>
<h3 id="compliant">Compliant</h3>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-title">all</span><span class="hljs-params">(iterable)</span></span>
</code></pre>
<h2 id="any">Any</h2>
<h3 id="non-compliant">Non compliant</h3>
<pre><code class="lang-python"><span class="hljs-keyword">for</span> element <span class="hljs-keyword">in</span> iterable:
    <span class="hljs-keyword">if</span> element:
        <span class="hljs-keyword">return</span> <span class="hljs-literal">True</span>
<span class="hljs-keyword">return</span> <span class="hljs-literal">False</span>
</code></pre>
<h3 id="compliant">Compliant</h3>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-title">any</span><span class="hljs-params">(iterable)</span></span>
</code></pre>
<h2 id="filter">Filter</h2>
<h3 id="non-compliant">Non compliant</h3>
<pre><code class="lang-python">my_list = []
<span class="hljs-keyword">for</span> <span class="hljs-keyword">element</span> <span class="hljs-keyword">in</span> iterable:
    <span class="hljs-keyword">if</span> <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-title">element</span>):</span>
        my_list.append(<span class="hljs-keyword">element</span>)
</code></pre>
<h3 id="compliant">Compliant</h3>
<pre><code class="lang-python"><span class="hljs-built_in">filter</span>(<span class="hljs-function"><span class="hljs-keyword">function</span>, <span class="hljs-title">iterable</span>)</span>
</code></pre>
<h2 id="len">Len</h2>
<h3 id="non-compliant">Non compliant</h3>
<pre><code class="lang-python"><span class="hljs-built_in">count</span> = <span class="hljs-number">0</span>
<span class="hljs-keyword">for</span> element <span class="hljs-keyword">in</span> iterable:
    <span class="hljs-built_in">count</span> += <span class="hljs-number">1</span>
</code></pre>
<h3 id="compliant">Compliant</h3>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-title">len</span><span class="hljs-params">(iterable)</span></span>
</code></pre>
<h2 id="map">Map</h2>
<h3 id="non-compliant-1">Non compliant #1</h3>
<pre><code class="lang-python">my_list = []
<span class="hljs-keyword">for</span> element <span class="hljs-keyword">in</span> iterable:<span class="hljs-type"></span>
    <span class="hljs-keyword">new</span><span class="hljs-type">_item</span> = <span class="hljs-function"><span class="hljs-keyword">function</span></span>(element)
    my_list.append(<span class="hljs-keyword">new</span><span class="hljs-type">_item</span>)
</code></pre>
<h3 id="non-compliant-2">Non compliant #2</h3>
<pre><code class="lang-python"><span class="hljs-keyword">for</span> <span class="hljs-keyword">element</span> <span class="hljs-keyword">in</span> iterable:
    <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-title">element</span>)</span>
</code></pre>
<h3 id="compliant">Compliant</h3>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-title">map</span><span class="hljs-params">(function, iterable)</span></span>
</code></pre>
<h2 id="max">Max</h2>
<h3 id="non-compliant">Non compliant</h3>
<pre><code class="lang-python">max<span class="hljs-number">_</span><span class="hljs-keyword">value</span> = None
<span class="hljs-keyword">for</span> element <span class="hljs-keyword">in</span> iterable:
    <span class="hljs-keyword">if</span> max<span class="hljs-number">_</span><span class="hljs-keyword">value</span> <span class="hljs-keyword">is</span> None or element &gt; max<span class="hljs-number">_</span><span class="hljs-keyword">value</span>:
        max<span class="hljs-number">_</span><span class="hljs-keyword">value</span> = element
</code></pre>
<h3 id="compliant">Compliant</h3>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-title">max</span><span class="hljs-params">(iterable)</span></span>
</code></pre>
<h2 id="min">Min</h2>
<h3 id="non-compliant">Non compliant</h3>
<pre><code class="lang-python">min<span class="hljs-number">_</span><span class="hljs-keyword">value</span> = None
<span class="hljs-keyword">for</span> element <span class="hljs-keyword">in</span> iterable:
    <span class="hljs-keyword">if</span> min<span class="hljs-number">_</span><span class="hljs-keyword">value</span> <span class="hljs-keyword">is</span> None or element &lt; min<span class="hljs-number">_</span><span class="hljs-keyword">value</span>:
        min<span class="hljs-number">_</span><span class="hljs-keyword">value</span> = element
</code></pre>
<h3 id="compliant">Compliant</h3>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-title">min</span><span class="hljs-params">(iterable)</span></span>
</code></pre>
<h2 id="sum">Sum</h2>
<h3 id="non-compliant">Non compliant</h3>
<pre><code class="lang-python"><span class="hljs-built_in">count</span> = <span class="hljs-number">0</span>
<span class="hljs-keyword">for</span> element <span class="hljs-keyword">in</span> iterable:
    <span class="hljs-built_in">count</span> += element
</code></pre>
<h3 id="compliant">Compliant</h3>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-title">sum</span><span class="hljs-params">(iterable)</span></span>
</code></pre>
<h2 id="index">Index</h2>
<h3 id="non-compliant">Non compliant</h3>
<pre><code class="lang-python"><span class="hljs-keyword">for</span> <span class="hljs-selector-tag">i</span>, element <span class="hljs-keyword">in</span> enumerate(iterable):
    <span class="hljs-keyword">if</span> element is searched_element:
        return <span class="hljs-selector-tag">i</span>
raise ValueError
</code></pre>
<h3 id="compliant">Compliant</h3>
<pre><code class="lang-python">iterable.<span class="hljs-keyword">index</span>(searched_element)
</code></pre>
<h2 id="count">Count</h2>
<h3 id="non-compliant">Non compliant</h3>
<pre><code class="lang-python"><span class="hljs-built_in">count</span> = <span class="hljs-number">0</span>
<span class="hljs-keyword">for</span> element <span class="hljs-keyword">in</span> iterable:
    <span class="hljs-keyword">if</span> element <span class="hljs-keyword">is</span> searched_element:
        <span class="hljs-built_in">count</span> += <span class="hljs-number">1</span>
</code></pre>
<h3 id="compliant">Compliant</h3>
<pre><code class="lang-python">iterable.<span class="hljs-built_in">count</span>(searched_element)
</code></pre>
<h2 id="iterable-operators">Iterable operators</h2>
<h3 id="non-compliant">Non compliant</h3>
<pre><code class="lang-python"><span class="hljs-keyword">for</span> element <span class="hljs-keyword">in</span> iterable:
    <span class="hljs-keyword">if</span> element <span class="hljs-keyword">is</span> x:
        <span class="hljs-keyword">return</span> <span class="hljs-literal">True</span>
<span class="hljs-keyword">return</span> <span class="hljs-literal">False</span>
</code></pre>
<h3 id="compliant">Compliant</h3>
<pre><code class="lang-python">x <span class="hljs-keyword">in</span> iterable
</code></pre>
<h2 id="set-operators">Set operators</h2>
<h3 id="compliant">Compliant</h3>
<pre><code class="lang-python">overlaps = []
<span class="hljs-keyword">for</span> x <span class="hljs-keyword">in</span> <span class="hljs-selector-tag">a</span>:
  <span class="hljs-keyword">for</span> y <span class="hljs-keyword">in</span> <span class="hljs-selector-tag">b</span>:
    <span class="hljs-keyword">if</span> x==y:
      overlaps.append(x)
</code></pre>
<h3 id="non-compliant">Non compliant</h3>
<pre><code class="lang-python">set(<span class="hljs-name">a</span>) &amp; set(<span class="hljs-name">b</span>)
</code></pre>

<h2 id="recognizable-sorting-algorithm">Recognizable sorting algorithm</h2>
<p>Most developers learned the most known sorting algorithms (selection, bubble, insertion, heap, merge, quick...) either for practice or for job interviews.
They should not re-implement those but use the <code>sorted()</code> or <code>list.sort()</code> methods instead.</p>

Implementation principle

jhertout commented 5 months ago

We should have an issue for each "pattern". Each pattern rule needs to be measured in my point of view. I think it can be done with tools like RAPL. I am not sure of what to do with this issue as it is today.