0

Let's say I'm writing a class that does something that takes a lot of time.

class Example:
    def expensive(self, arg):
        return arg + 1

Since it takes a lot of time, there are few possible arguments and every result will be used many times, I decide to precompute the results when the application is started:

class Example:
    def expensive(arg):
        return arg + 1

    EXPENSIVE = {
        0: expensive(0),
        1: expensive(1),
        2: expensive(2),
        # ...
    }

    del expensive

Note that this does work. Obviously, this is very repetetive, so I decide to use dictionary comprehension:

class Example:
    def expensive(arg):
        return arg + 1

    EXPENSIVE = {x: expensive(x) for x in range(3)}

    del expensive

Unfortunately, Python rejects this with the following error:

Traceback (most recent call last):
  File ".code.tio", line 1, in <module>
    class Example:
  File ".code.tio", line 5, in Example
    EXPENSIVE = {x: expensive(x) for x in range(3)}
  File ".code.tio", line 5, in <dictcomp>
    EXPENSIVE = {x: expensive(x) for x in range(3)}
NameError: name 'expensive' is not defined

To be honest, this really surprised me. Python's scoping rules were really intuitive to me so far. Why does this happen, and how can I work around it?

Maya
  • 1,490
  • 12
  • 24
  • 1
    `self.expensive()` ? also you need to have `def expensive(self, arg):` – Druta Ruslan Jun 14 '18 at 16:36
  • @zimdero Try it. I dare you. While I find the stackoverflow question that explains this. You need `self` for a method, but not for an internal static function. – Maya Jun 14 '18 at 16:39
  • Precomputing the results may lead to doing unused computations. What you want to avoid is recomputing the same thing twice. You could use functools.lru_cache or implement your own caching decorator. – Olivier Melançon Jun 14 '18 at 16:39
  • @NieDzejkob and where is your `staticmethod` decorator ? – Druta Ruslan Jun 14 '18 at 16:40
  • The error code appears misleading. The error is caused when you call "del expensive", which isn't a defined term. – Ghoti Jun 14 '18 at 16:41
  • @Ghoti remove the line, error stays. – Maya Jun 14 '18 at 16:42
  • Sorry. It seems that I redefined the function outside of the class and it persisted in memory after being commented out. – Ghoti Jun 14 '18 at 16:44
  • @zimdero I want to access `expensive` only from the inside of the class, [and staticmethod works for the exactly opposite use case](https://tio.run/##TY5BC4JAEIXv/ooHXpJC1G5C0GUPXiIIouuiYwmuK7ObGNFv38zC9t3mfd8M0z/sTXdb58pWGgMxStW3lAeYsjdW2qZUNCkVQjApPRCsRt2MIGbNs1dRDRp76kwz0EryNfruf8Jk79xhKrFGGsy9uBzF4VScBXZ4LmaSe0eSaLOA1AepBzIfZB4IEcfxPL2C34ftX3XuDQ). – Maya Jun 14 '18 at 16:47
  • 1
    @OlivierMelançon I am aware of that, but I'd rather compute everything beforehand rather than compute it when a fast response is more important, since I can guarantee that each result will be used many times during the execution. – Maya Jun 14 '18 at 16:48

0 Answers0