tags:

views:

141

answers:

7

From the tutorial: "A class definition is an executable statement."

Is the following recommended in a script?

my_switch = False
if my_switch:
    class Hello:
        def __init__(self):
            self.greeting = "Hello!"

else:
    class Hello:
        def __init__(self):
            self.greeting = "Salut!"
+3  A: 

Yes, the code is valid. but why not just run the code to find out?

You can also do this with function definitions.

aaronasterling
+5  A: 

You can even do

class Hello:
    def __init__(self):
        self.greeting = "Hello!"

class Salut:
    def __init__(self):
        self.greeting = "Salut!"

if my_switch:
    Hello = Salut

(note that your code needs lower-case Class keywords...)

Radomir Dopieralski
Thanks, updated my code. This is a very cool thing!
Jasie
-1 @Jasie This is wrong for three reasons. 1) why define a class if you're not going to use it? 2) as you originally had it, it was clear that the identifier `Hello` could refer to one of two different class objects __at creation time__. Now, I need to read further into the code to see this as it is not at all obvious. 3) any debugging done with `my_switch == True` will output `Salut` as the class name. This will be confusing to other people.
aaronasterling
I rather meant that as an example demonstrating that classes are first-class objects too in Python, not as an actual code to use. Of course for things like translations you are going to use gettext or something similar anyways.
Radomir Dopieralski
+2  A: 

It is valid code but not really recommended in that format (assuming that code would follow the class declaration). Since you will eventually use the class. Assuming that you still use two classes named the same, it might be confusing afterward. Maybe you should have the code wrapped in a function to return the class that you have created. Now you have a basic factory.

def HelloFactory(my_switch)
    if my_switch:
        class Hello:
           def __init__(self):
               self.greeting = "Hello!"
    else:
        class Hello:
           def __init__(self):
               self.greeting = "Salut!"
    return Hello

helloClass = HelloFactory(False)
hello = helloClass()
hello.greeting

Would output "Salut!"

Rod
helloClass = HelloFactory(False) uh huh? You're not returning anything
Robus
@Robus Thanks, fixed.
Rod
i feel this snippet even more complicated than the OP's one. I believe that using nested classes/functions should be avoided if possible as it really decreases code readability.
MatToufoutu
@MatToufoutu It was not meant to be a replacement but a simple example that you could create factory methods. I agree that adding code for the sake of adding code will create code readability.
Rod
+4  A: 

It's certainly not recommended for localization, as in your example.

The main thing to consider is how much of the code is going to be similar versus different in the specialized versions of the class. If only a small amount of code is different, or if only data is different ("Hello" vs "Salut"), there are better ways.

One case where I might consider conditional declaration of classes is if I'm providing functionality on two different OSes, and getting that functionality is very different between the two. As an example, maybe I'm trying to drive iTunes from a script, and on MacOS I'm using AppleScript to drive it, but on Windows I have to use COM. I might create a wrapper class that the rest of my code could use without caring about which OS was in use.

Russell Borogove
Even in your OS case I wouldn't do it like this. I'd have one parent class that's an `abc`. The children would be OS-specific. The parent's `__new__` would return an object of the appropriate OS-specific type.
Daenyth
A: 

You may not need to repeat the code as you do. Ask yourself if you need to repeat the class construction code, or just variables within the class itself? If it's the latter, then you could use the same class for both cases using an argument in __init__(), and then conditionally return an instance of the class with the desired variable:

my_switch = False

class Hello:
    def __init__(self, greeting):
        self.greeting = greeting

if my_switch:
    mygreeting = "Hello!"
else:
    mygreeting = "Salut!"

hello = Hello(mygreeting)
print hello.greeting
# => Salut!
jathanism
+1  A: 

You can also put conditions around the "declarations" inside the class, since those are executed as part of the class construction:

class Hello:
    if my_switch:
        igreeting = "Hello!"
    else:
        igreeting = "Salut!"       
    def __init__(self, greeting):
            self.greeting = self.igreeting

(igreeting here is a class variable, greeting a member variable)

or just plain

class Hello:
    if my_switch:
        greeting = "Hello!"
    else:
        greeting = "Salut!"       

... will usually give the same effect.

greggo
+1  A: 

If you like it better, you could put each class definition in a separate .py file and just import the one you want. Something like the following:

if my_switch:
    from hello_en import Hello
else:
    from hello_fr import Hello

h = Hello()
martineau