Reputation: 73
I have three Python modules in the same directory. Within two of these files are classes I am trying to access. I am under the impression that if I have the following code in one of my modules (called enum):
class Directions:
UP = 1
DOWN = 2
LEFT = 3
RIGHT = 4
class Colors:
RED = [255, 0, 0]
that I can use the following statements:
from enum import Directions
from enum import Colors
be able to access class members like so:
foo = DOWN
bar = RED
However, I have to access them like this
foo = Directions.DOWN
bar = Colors.RED
otherwise an error is produced. Is there any way to use import/from-import statements to access my class members without having to specify the class name? Or should I be organizing my "enumerations" in a different manner?
Upvotes: 1
Views: 129
Reputation: 3534
If your classes are as simple as what you've posted here, then there is no need for them to be classes really. BUT, to get what you want with the code you've got, you need to do it like this:
from enum import Directions
from enum import Colors
foo = Directions() # This is called instantiation
foo.DOWN
bar = Colors() # You can potentially instantiate as many of these as you want
bar.RED
rab = Colors()
rab.RED # Try it, you'll see
Classes are not really intended to hold static variables like you've got, but this code is how it works.
The reason Python shouldn't be such that your code would work is because of the following example:
class Directions:
UP = 1
DOWN = 2
LEFT = 3
RIGHT = 4
class Directions2:
UP = 9
DOWN = 8
LEFT = 7
RIGHT = 6
Then you import
from enum import Directions
from enum import Directions2
If you then try to use foo = DOWN
, then how can Python know what DOWN
you are talking about? The technical term for this underlying concept is namespace.
Upvotes: 2
Reputation: 387755
from enum import Directions
This will import the name Directions
from the module enum
. What happens internally, that the internal import function will actually set the local variable Directions
to whatever is imported in that way. In particular, it will not set any other local variables—which is exactly why you use the from..import
syntax, so you have complete control over what names are set.
So using it like that, you just cannot get variables DOWN
and RED
set.
If you want to use them, you will need to import those directly, i.e. from <something> import DOWN, RED
or from <something> import *
if you just want to import everything (which is usually discouraged).
Now for the <something>
part; you cannot import properties of a type, so you will have to change your enum
module in some way. One verbose possibility would be to change each type Directions
and Colors
into separate modules, so you can do from enum.Directions import DOWN
etc.
The other possibility would be to expose those variables directly in the enum module, for example like this:
class Directions:
UP = 1
DOWN = 2
LEFT = 3
RIGHT = 4
UP = Directions.UP
DOWN = Directions.DOWN
LEFT = Directions.LEFT
RIGHT = Directions.RIGHT
Of course then you could argue if you even need that Directions
type. Usually though, you would actually want to import just Directions
and specify each enum values explicitely using Directions.UP
etc. so you actually know what kind of enum you are referring to.
Upvotes: 1
Reputation: 30947
Organize them in a different manner. There's no direct way to do what you're asking.
On the other hand, referring to Directions.DOWN
and Colors.RED
is very Pythonic. It's explicit (DOWN
refers to a Direction
, not a MattressStuffing
) and uses namespaces to contain the data (Colors.RED
is different from Alerts.RED
). These are Good Things.
Upvotes: 3
Reputation: 208495
It is impossible to access class members directly from code anywhere other than inside of that class definition.
Try changing your enum module to the following:
__all__ = ['UP', 'DOWN', 'LEFT', 'RIGHT', 'RED']
# Directions
UP = 1
DOWN = 2
LEFT = 3
RIGHT = 4
# Colors
RED = [255, 0, 0]
And then use from enum import *
inside of your modules where you want access to those variables.
Defining __all__
isn't necessary here but it is good practice to use it anyway. It controls what names are imported when from foo import *
is used.
Upvotes: 5