3

In Python I have a dictionary of settings which relate to a task class. In the parent constructor of these tasks I would like to store only the relevant settings, but to do this I need to access the child class from the parent class.

settings = {
    SomeTask: { 'foo': 'bar' },
    SomeOtherTask: { 'bar': 'foo' },
}

class SomeTask(BaseTask):
    pass

class SomeOtherTask(BaseTask):
    pass

class BaseTask:
    def __init__(self, settings):
        self.settings = settings[child_class]

In PHP I can do this by calling get_class($this); in the constructor (returns the child class name rather than the parent), does Python have something similar?

4
  • You do realize the definitions are precisely in the wrong order? Commented Apr 29, 2013 at 14:20
  • Yep, I did this deliberately as it makes more sense (to me) to describe it this way - although that might just be me? Commented Apr 29, 2013 at 14:21
  • self(or really the first argument in class methods) always refers to the instanstiated class you are working with Commented Apr 29, 2013 at 14:22
  • @JoranBeasley Oh that's right, it seems to work now. Thanks! Commented Apr 29, 2013 at 14:24

3 Answers 3

3

Just do this:

class BaseTask:
    def __init__(self, settings):
        self.settings = settings[self.__class__]

class SomeTask(BaseTask):
    pass

class SomeOtherTask(BaseTask):
    pass

When you initialise one of the child classes with the settings, they will do what you expect.

Sign up to request clarification or add additional context in comments.

4 Comments

Can this be done without creating a circular reference though?
@Aya There's no circular reference (and even if there was, it wouldn't be a problem).
Alternatively, type(self), which is closer to the PHP version and more idiomatic. Plus, it breaks on old-style classes so you're forced to use new-style classes ;-)
@delnan Oops. Didn't notice the settings param. I thought the code was using the global.
1

The closest Python equivalent to the PHP code...

$class_name = get_class($my_object)

...is...

class_name = my_object.__class__.__name__

...which should work for both old-style and new-style Python classes.

Indeed, if you index the classes by their name, rather than using a reference to the class object, then you don't need to pass in the settings parameter (which I assume you only did to avoid a circular reference), and access the global settings variable directly...

settings = {
    'SomeTask': { 'foo': 'bar' },
    'SomeOtherTask': { 'bar': 'foo' },
}

class BaseTask:
    def __init__(self):
        self.settings = settings[self.__class__.__name__]

class SomeTask(BaseTask):
    pass

class SomeOtherTask(BaseTask):
    pass

1 Comment

Going by class name is pretty fragile in general. Even going my module name + qualified name in module is quite hacky.
0

I would it consider much cleaner to do

class SomeTask(BaseTask):
    settings = { 'foo': 'bar' }

class SomeOtherTask(BaseTask):
    settings = { 'bar': 'foo' }

provided no changes are made to these settings.

This way, the changes are tightly coupled to the class and there is only one dict object containing these settings.

1 Comment

In practice it's a bit more complicated - more like settings = { 'client1': { SomeTask: {} }, 'client2': { OtherTask: {} } }. But I agree if that were the case :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.