2

I want to initialize a static field on declaration.

class Test:

    def _init_foo(): return 3

    foo = { _init_foo() for i in range(10)}

However, the interpreter is complaining

NameError: name '_init_foo' is not defined

How do I fix this?

Jsevillamol
  • 2,425
  • 2
  • 23
  • 46
  • 2
    What you're trying to achieve? If you need class attribute `foo` to be same and shared for all instances, just write `foo = 3`. But it will not be static anyway. – Slam Oct 30 '18 at 09:47
  • 1
    Why this fails is [explained here](https://stackoverflow.com/a/13913933/190597). – unutbu Oct 30 '18 at 09:54
  • @Slam in the real case, foo must be a dictionary whose attributes are loaded from files – Jsevillamol Oct 30 '18 at 09:56
  • Possible duplicate of [Accessing class variables from a list comprehension in the class definition](https://stackoverflow.com/questions/13905741/accessing-class-variables-from-a-list-comprehension-in-the-class-definition) – MyNameIsCaleb Oct 30 '18 at 10:18

2 Answers2

2

Why this fails is explained here.

You could work around the problem by defining foo via a class decorator. This works because by the time add_foo is called, the class has been defined and _init_foo in then accessible as cls._init_foo:

def add_foo(cls):
    cls.foo = { cls._init_foo() for i in range(10) }
    return cls

@add_foo
class Test:

    def _init_foo(): return 3


print(Test.foo)
# {3}
unutbu
  • 842,883
  • 184
  • 1,785
  • 1,677
1

Before finding the class decorator option, I was initialising fields after the class declaration. I don't know which one I like less... :) I miss a static init block like in Java.

class Box:

    def __init__(self, x):
        self.x = x
        Box.count += 1  # static field usage

    @staticmethod
    def instance_count():
        return Box.count  # static field usage

Box.count = 0  # static field initialisation

b1 = Box(10)
b2 = Box(20)
print(Box.count)  # 2
Ferran Maylinch
  • 10,919
  • 16
  • 85
  • 100