The Cost of Dynamism (was Re: Pyhon 2.x or 3.x, which is faster?)

BartC bc at freeuk.com
Mon Mar 14 10:43:22 EDT 2016


On 13/03/2016 09:39, Steven D'Aprano wrote:
> On Sun, 13 Mar 2016 04:54 am, BartC wrote:

>> Common sense tells you it is unlikely.
>
> Perhaps your common sense is different from other people's common sense. To
> me, and many other Python programmers, it's common sense that being able to
> replace functions or methods on the fly is a useful feature worth having.
> More on this below.
>
> Perhaps this is an example of the "Blub Paradox":

Perhaps it's time to talk about something which many languages have, but 
Python hasn't. Not as far as I know anyway.

That's references to names (sometimes called pointers). So if I write:

  a = 100
  f(a)

then function f gets passed the value that a refers to, or 100 in this 
case. But how do you pass 'a' itself?

Perhaps you can say:

   f('a')

and f can do some sort of lookup, if it knows the caller's context, for 
such a name and retrieve the value that way. But that's rather 
heavy-handed, and f can't distinguish between a reference to a name, and 
a string.

Unless maybe you wrap this up in a class and .... Well, you end up with 
something that might emulate a name reference, but with so much 
complexity and such overheads that it is not worthwhile.

Yet, this is a feature I use extensively, far more often than I would 
use mutable functions. And in fact it was used in the code for my jpeg 
example, where in the Python I has to use a workaround (see below).

I would argue that such references are more useful than mutable function 
names, as the latter can be more easily emulated and with little or no 
extra overheads.

-------------------------------------------------

Non-Python example of reference parameters:

fastidct8(
     block[j],          # each argument can be updated by the callee
     block[j+8],
     block[j+16],
     block[j+24],
     block[j+32],
     block[j+40],
     block[j+48],
     block[j+56])

proc fastidct8(&a1,&a2,&a3,&a4,&a5,&a6,&a7,&a8) =
     const w1 = 2841  # (Incidentally, here's a use-case for proper
     const w2 = 2676  # consts. Evaluated at compile-time here ...
     const w3 = 2408
     const w5 = 1609
     const w6 = 1108
     const w7 = 565
....
     a1 := (x8 + x2) >> 8
     a2 := (x4 + x3) >> 8
     a3 := (x1 + x5) >> 8
     a4 := (x9 + x7) >> 8
     a5 := (x9 - x7) >> 8
     a6 := (x1 - x5) >> 8
     a7 := (x4 - x3) >> 8
     a8 := (x8 - x2) >> 8
end

Python version:

(block[j],
  block[j+8],
  block[j+16],
  block[j+24],
  block[j+32],
  block[j+40],
  block[j+48],
  block[j+56]) = fastidct8(
     block[j],
     block[j+8],
     block[j+16],
     block[j+24],
     block[j+32],
     block[j+40],
     block[j+48],
     block[j+56])

def fastidct8(a1,a2,a3,a4,a5,a6,a7,a8):
     w1 = 2841   #  ... but at run-time in here)
     w2 = 2676
     w3 = 2408
     w5 = 1609
     w6 = 1108
     w7 = 565
....
     a1 = (x8 + x2) >> 8
     a2 = (x4 + x3) >> 8
     a3 = (x1 + x5) >> 8
     a4 = (x9 + x7) >> 8
     a5 = (x9 - x7) >> 8
     a6 = (x1 - x5) >> 8
     a7 = (x4 - x3) >> 8
     a8 = (x8 - x2) >> 8
     return [a1,a2,a3,a4,a5,a6,a7,a8]

-- 
Bartc



More information about the Python-list mailing list