4

I have a question similar to the question asked here: Importing a long list of constants to a Python file

Basically, I have a separate module which just contains a long list of constants, e.g.

constants.py

x = 1.2
y = 30.4
.
.
.

In another module, I would like import these constants and initialize them as instance attributes.

class.py

class something(object):
    def __init__(self):
        import constants
        self.x = constants.x
        self.y = constants.y
        .
        .
        .

Is there an easier or more pythonic way to do this instead of retyping all of the variable names?

Community
  • 1
  • 1
Manila Thrilla
  • 547
  • 1
  • 8
  • 17

5 Answers5

5

Python developers have developed a cool solution: it's called ConfigParser.

A practical example: config.ini

[constants]
key = value
x = 0
y = 1

class.py

from ConfigParser import SafeConfigParser
class MyClass(object):
    def __init__(self, **kwargs):
        self.config = SafeConfigParser(defaults=kwargs).read('config.ini')

    def get_x(self):
        return self.config.get('constants', 'x')

I hope this helps.

EDIT: If you need instance attributes, you can do:

class MyClass(object):
    ...
    def __getattr__(self, key):
        return self.config.get('constants', key)

EDIT2: need a Python file and a .ini file is not a solution?

from . import config
class Myclass(object):
    def __getattr__(self, key):
        return getattr(config, key)
gioi
  • 1,463
  • 13
  • 16
1

You could do

for constant, value in constants.__dict__.values():
  setattr(self, constant, value)

Why do you need them as instance attributes?

Pavel Anossov
  • 60,842
  • 14
  • 151
  • 124
1

You could put the constants in a class in the module. This class can be more easily passed around, or used as a mixin class for any class that needs those constants as class attributes.

class Constants(object):
    x = 1.2
    y = 30.4


# optional 
class Base(object):
    pass

class Something(Constants, Base):
    pass


s = Something()

print(s.x)

However, since it's just data I would probably just use some type of data structure, such as a dictionary, to hold them. I'm not sure why you would need to put them as class attributes, when any code could just reference them from the module just the same.

Keith
  • 42,110
  • 11
  • 57
  • 76
  • Creating a class you never intend to instantiate just to hold a bunch of attributes is a bit of an anti-pattern, IMHO. Modules themselves are first-class objects too; just pass around the module instead of creating a class and passing that around. I'll admit using it as a mixin could potentially be useful, but then you've got multiple inheritance going on (with seeing that it's just a simple class-var dump left as an exercise for the reader). – Ben Oct 31 '12 at 12:10
  • @Ben That's what I said at the end. :) – Keith Oct 31 '12 at 12:23
  • Thanks. Actually you're right, a dictionary is probably a better way to hold them. I just like the idea of using 'instance.attribute' syntax – Manila Thrilla Nov 14 '12 at 22:25
1

There's always something like:

class something(object):
    def __init__(self):
        import constants
        for name in ['x', 'y', ...]:
            setattr(self, name, getattr(constants, name))

That has the advantage of avoiding repreating self.X = constants.X so very many times, and means you're only listing the names once in one place.

You could use this:

for name, value in constants.__dict__.iteritems():
    setattr(self, name, value)

To get all the names bound in constants without explicitly listing them, but I personally would not. It makes it much less clear what attributes something objects actually have, and it's very easy for Python modules to end up containing more names than you realise. For example, if you have to import another module (say, math) in constants in the process of defining all your constants, then you'll end up with an unexpected math attribute of all your something instances.

I think explicitly listing the names you mean to import is clearer. Plus, it means that you don't affect all your something instances if you discover you need to add more constants for some other part of your program to use (and if the constants can only ever have relevance to something then they really should be listed in something, not in an external module).

Ben
  • 68,572
  • 20
  • 126
  • 174
0

from constants import x, y just be sure you don't accidentally over ride your variables later (i.e. don't use generic names)

John
  • 13,197
  • 7
  • 51
  • 101