Golfing with Python Import

16

1

When is it beneficial to use inline, single use importing in Python?

For example:

__import__("x").doSomething()

Is the above ever shorter than the below?

import x
x.doSomething()

Or

from x import*
doSomething()

Beta Decay

Posted 2015-08-02T17:31:43.350

Reputation: 21 478

Answers

11

This can be useful if you want to use a module just once in an anonymous lambda function, as it allows you to avoid writing a separate statement:

lambda x:__import__('SomeModule').foo(x,123)

is one byte shorter than

from SomeModule import*;f=lambda x:foo(x,123)

If the code is a named function or program, then __import__ is unlikely to help except in the most extreme or contrived circumstances.

feersum

Posted 2015-08-02T17:31:43.350

Reputation: 29 566

__import__ would help inside of a named function since it would be inside of an indented block. An import would cost extra since it's on two lines and indented. (That's assuming that imports aren't allowed outside of the function.) – Alex A. – 2015-08-02T18:01:37.857

@AlexA I see no problem with placing imports outside of a named function. – feersum – 2015-08-02T18:03:47.160

Then would there ever be a time when import would be called inside of an indented block? Probably not. – Alex A. – 2015-08-02T18:05:00.277

placing imports outside of the named function won't work for challenges where you're writing just one function. – Sparr – 2015-08-02T19:53:40.260

6

The second example doesn't require the f= because anonymous functions are allowed and can have content outside the function.

– xnor – 2015-08-02T20:25:36.013

@xnor Nowhere in the 2nd question or its answers are anonymous functions mentioned. I wouldn't call a block of code a function literal unless the entire code is a single expression. – feersum – 2015-08-03T04:44:38.857

This is not true, because imports are allowed preceding a function literal. Here, from SomeModule import*;lambda x:foo(x,123) would be the shortest. – Esolanging Fruit – 2017-05-07T12:08:28.560

@Challenger5 I don't agree that from SomeModule import*;lambda x:foo(x,123) is a valid answer. It is not a program, does not define a named function, and is not a function expression. – feersum – 2017-05-07T12:18:30.353

@feersum Here's a random example I found.

– Esolanging Fruit – 2017-05-07T12:39:18.587

4

When importing multiple modules with sufficiently long names, it can be helpful to assign the __import__ function to a shorter variable and use it for imports

Example:

Regular import statements - 97 bytes

from itertools import*
from datetime import*
print list(permutations("abc"))
print datetime.now()

Assigning __import__ to i - 94 bytes:

i=__import__
print list(i("itertools").permutations("abc"))
print i("datetime").datetime.now()

negative seven

Posted 2015-08-02T17:31:43.350

Reputation: 1 931

1

Almost never.

__import__("x").doSomething() needs 15+x characters to refer to a module with a name of length x.

import x\nx.doSomething() needs 9+2*x characters. These functions overlap at x=6, so compared to this way any module with a longer name is better off using __import__, anything shorter benefits from normal imports:

However, from x import*\ndoSomething() needs only 14+x characters, so compared to the normal import it is not worth it unless the module name is longer than 5 characters:

This all assumes that you are referring to a function/class/whatever only once. If you refer to it more than once, the formulas change, and the latter version might become the winner. In case you use something long from an imported module several times, yet another version wins:

from x import y as z nets you 18+x+y+z*(n+1) characters for n uses of z, which is a large improvement if y is big, because z can be made 1.

L3viathan

Posted 2015-08-02T17:31:43.350

Reputation: 3 151

1Can you check your math? I find __import__("x").doSomething() to be one char shorter than from x import*;doSomething(). Maybe you're counting the newline as two chars? And I recall the break-even point being 5, falling between time and random. – xnor – 2017-05-07T09:25:43.817

@xnor I didn't count newlines twice, but I missed that you don't need the dot in that version. Give me a minute, I'll update. – L3viathan – 2017-05-07T09:28:34.847

1z=__import__("x").y is a byte shorter than from x import y as z – negative seven – 2019-06-18T13:06:38.547

1@negativeseven Shorter: from x import*;z=y. – L3viathan – 2019-06-18T14:05:41.823