Asked  7 Months ago    Answers:  5   Viewed   34 times

How can I divide two numbers in Python 2.7 and get the result with decimals?

I don't get it why there is difference:

in Python 3:

>>> 20/15
1.3333333333333333

in Python 2:

>>> 20/15
1

Isn't this a modulo actually?

 Answers

96

In python 2.7, the / operator is integer division if inputs are integers.

If you want float division (which is something I always prefer), just use this special import:

from __future__ import division

See it here:

>>> 7 / 2
3
>>> from __future__ import division
>>> 7 / 2
3.5
>>>

Integer division is achieved by using //, and modulo by using %

>>> 7 % 2
1
>>> 7 // 2
3
>>>

EDIT

As commented by user2357112, this import has to be done before any other normal import.

Tuesday, June 1, 2021
 
Zeth
answered 7 Months ago
42

Use dict.setdefault():

dic.setdefault(key,[]).append(value)

help(dict.setdefault):

    setdefault(...)
        D.setdefault(k[,d]) -> D.get(k,d), also set D[k]=d if k not in D
Wednesday, June 9, 2021
 
GGio
answered 6 Months ago
12

/ is a different operator in Python 3; in Python 2 / alters behaviour when applied to 2 integer operands and returns the result of a floor-division instead:

>>> 3/2   # two integer operands
1
>>> 3/2.0 # one operand is not an integer, float division is used
1.5

Add:

from __future__ import division

to the top of your code to make / use float division in Python 2, or use // to force Python 3 to use integer division:

>>> from __future__ import division
>>> 3/2    # even when using integers, true division is used
1.5
>>> 3//2.0 # explicit floor division
1.0

Using either of these techniques works in Python 2.2 or newer. See PEP 238 for the nitty-gritty details of why this was changed.

Wednesday, July 7, 2021
 
Pradip
answered 5 Months ago
35

yield

You can use a generator for an elegant solution. At each iteration, yield twice—once with the original element, and once with the element with the added suffix.

The generator will need to be exhausted; that can be done by tacking on a list call at the end.

def transform(l):
    for i, x in enumerate(l, 1):
        yield x
        yield f'{x}_{i}'  # {}_{}'.format(x, i)

You can also re-write this using the yield from syntax for generator delegation:

def transform(l):
    for i, x in enumerate(l, 1):
        yield from (x, f'{x}_{i}') # (x, {}_{}'.format(x, i))

out_l = list(transform(l))
print(out_l)
['a', 'a_1', 'b', 'b_2', 'c', 'c_3']

If you're on versions older than python-3.6, replace f'{x}_{i}' with '{}_{}'.format(x, i).

Generalising
Consider a general scenario where you have N lists of the form:

l1 = [v11, v12, ...]
l2 = [v21, v22, ...]
l3 = [v31, v32, ...]
...

Which you would like to interleave. These lists are not necessarily derived from each other.

To handle interleaving operations with these N lists, you'll need to iterate over pairs:

def transformN(*args):
    for vals in zip(*args):
        yield from vals

out_l = transformN(l1, l2, l3, ...)

Sliced list.__setitem__

I'd recommend this from the perspective of performance. First allocate space for an empty list, and then assign list items to their appropriate positions using sliced list assignment. l goes into even indexes, and l' (l modified) goes into odd indexes.

out_l = [None] * (len(l) * 2)
out_l[::2] = l
out_l[1::2] = [f'{x}_{i}' for i, x in enumerate(l, 1)]  # [{}_{}'.format(x, i) ...]

print(out_l)
['a', 'a_1', 'b', 'b_2', 'c', 'c_3']

This is consistently the fastest from my timings (below).

Generalising
To handle N lists, iteratively assign to slices.

list_of_lists = [l1, l2, ...]

out_l = [None] * len(list_of_lists[0]) * len(list_of_lists)
for i, l in enumerate(list_of_lists):
    out_l[i::2] = l

zip + chain.from_iterable

A functional approach, similar to @chrisz' solution. Construct pairs using zip and then flatten it using itertools.chain.

from itertools import chain
# [{}_{}'.format(x, i) ...]
out_l = list(chain.from_iterable(zip(l, [f'{x}_{i}' for i, x in enumerate(l, 1)]))) 

print(out_l)
['a', 'a_1', 'b', 'b_2', 'c', 'c_3']

iterools.chain is widely regarded as the pythonic list flattening approach.

Generalising
This is the simplest solution to generalise, and I suspect the most efficient for multiple lists when N is large.

list_of_lists = [l1, l2, ...]
out_l = list(chain.from_iterable(zip(*list_of_lists)))

Performance

Let's take a look at some perf-tests for the simple case of two lists (one list with its suffix). General cases will not be tested since the results widely vary with by data.

enter image description here

Benchmarking code, for reference.

Functions

def cs1(l):
    def _cs1(l):
        for i, x in enumerate(l, 1):
            yield x
            yield f'{x}_{i}'

    return list(_cs1(l))

def cs2(l):
    out_l = [None] * (len(l) * 2)
    out_l[::2] = l
    out_l[1::2] = [f'{x}_{i}' for i, x in enumerate(l, 1)]

    return out_l

def cs3(l):
    return list(chain.from_iterable(
        zip(l, [f'{x}_{i}' for i, x in enumerate(l, 1)])))

def ajax(l):
    return [
        i for b in [[a, '{}_{}'.format(a, i)] 
        for i, a in enumerate(l, start=1)] 
        for i in b
    ]

def ajax_cs0(l):
    # suggested improvement to ajax solution
    return [j for i, a in enumerate(l, 1) for j in [a, '{}_{}'.format(a, i)]]

def chrisz(l):
    return [
        val 
        for pair in zip(l, [f'{k}_{j+1}' for j, k in enumerate(l)]) 
        for val in pair
    ]
Thursday, July 15, 2021
 
Kenny
answered 5 Months ago
89

This question has been addressed on SO, for example, here: Nonalphanumeric list order from os.listdir() in Python

Looks like Python returns the order that the native filesystem uses, and you have to sort them afterwards.

Thursday, August 5, 2021
 
supermitch
answered 4 Months ago
Only authorized users can answer the question. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :  
Share