 <p>In <code>lcmm(*range(1,5))</code> you're unpacking the iterable <code>range(1, 5)</code> with <code>*</code> so you're actually calling <code>lcmm(1, 2, 3, 4)</code>. In other words, there are five arguments that don't have names but they're in order and they're passed in those positions. In the function <code>def lcmm(*args):</code> the <code>*</code> captures the positional arguments into <code>args</code>. This means <code>args</code> gets the value <code>(1, 2, 3, 4)</code>. That explains why you're getting the same as <code>reduce(lcm, range(1,5))</code> because that's the same as <code>reduce(lcm, args)</code> when <code>args = (1, 2, 3, 4)</code>.</p> <p>When you're calling <code>lcmm(range(1,5))</code> it means you're passing <code>[1, 2, 3, 4]</code> as your argument. This is the only positional argument so at <code>def lcmm(*args):</code> the value of <code>*args</code> still captures all positional arguments. But because there's only one positional arguments the value of <code>args</code> becomes <code>([1, 2, 3, 4],)</code>. That's a tuple with one value in it, namely <code>[1, 2, 3, 4]</code>. This gives you a different result when <code>lcm</code> computes the return value.</p>