2

in my project I have to repeat often such part of code:

class SimplePhysicObject(Object):
    def __init__(self):
        super(Object, self).__init__('SimplePhysicObject')

But instead of SimplePhysicObject there is new string each time. Are there any ways to write some macro to make this work easier? Something like:

DoTemplate(NewObject)
==>
class NewObject(Object):
    def __init__(self):
        super(Object, self).__init__('NewObject')

UPD Sorry, Object is my own class declared before in code

fferri
  • 18,285
  • 5
  • 46
  • 95
Max Frai
  • 61,946
  • 78
  • 197
  • 306
  • 2
    In every example you've given the string is also the name of the class. Is that always the case? – kojiro Jul 26 '12 at 18:24
  • 1
    `Object` is not the object that goes there (also you may mean `object`). The object that goes there needs to be the *child* class (i.e., the one you're writing). So, `super(SimplePhysicsObject, self).whatever()`. – Julian Jul 26 '12 at 18:25
  • 1
    @Ockonal Why do you have `__init__`'s that take the names of classes (and the name of the class itself nonetheless)? – Julian Jul 26 '12 at 18:28
  • @Julian `Object` is my own type with constructor wich takes string. And I have to call that constructor from childrens (derivative classes) – Max Frai Jul 26 '12 at 18:29
  • Right, why though :)? Why does it need that string? – Julian Jul 26 '12 at 18:30
  • @Julian I'm writing main application in c++ and that's some info for log managers :) – Max Frai Jul 26 '12 at 18:31
  • This does feel like an X-Y problem. @Ockonal you may have better luck if you describe what you're ultimately trying to do, instead of just some python on which you're stuck along the way. – kojiro Jul 26 '12 at 18:35

5 Answers5

7

I don't see a reason why Object should need the actual class name as a parameter. You can access the actual class name in Object via self.__class__.__name__:

class Object(object):
    def __init__(self):
        self.name = self.__class__.__name__

class SimplePhysicObject(Object):
    pass

a = SimplePhysicObject()
print a.name

will print

SimplePhysicObject

This is slightly different than your original code: If you derive from SimplePhysicObject, the name attribute will be set to the name of the derived class, whereas your original code would continue to use "SimplePhysicObject".

Sven Marnach
  • 574,206
  • 118
  • 941
  • 841
  • 2
    Given the OP's reason that it's for logging, there may not even be a need to have an attribute at all other than `self.__class__.__name__`, but as given these answers are good now. +1. – Julian Jul 26 '12 at 18:33
3

Getting the argument to super(…).__init__ isn't hard. It's getting the class object as the argument to super itself that is best handled manually:

class SimplePhysicObject(Object):
    def __init__(self):
        cls = SimplePhysicObject
        super(cls, self).__init__(cls.__name__)
kojiro
  • 74,557
  • 19
  • 143
  • 201
1

To do something close to what you want as opposed to an alternative approach, you can use something like this:

CLASS_TEMPLATE = """
class {name}(object):
    def __init__(self):
        super({name}, self).__init__('{name}')
"""

def main():
    name = "SimplePhysicsObject"
    exec CLASS_TEMPLATE.format(name=name)
    print locals()[name]

if __name__ == '__main__':
    main()

This is valid for Python 2.7. (Seeing as you're using the old super() syntax.) If you're using Python 3.2, you could look at the implementation of collections.namedtuple that also creates classes dynamically to see how to use the new exec() function.

An important point is that this isn't really a macro, it won't expand into a class definition before the "compiler" processes it. It will return a new type object, it's up to you to make sure it goes into the right namespace.

millimoose
  • 39,073
  • 9
  • 82
  • 134
  • @Ockonal To be fair, Sven's approach is more likely to do what you want if you're going to set up an inheritance hierarchy, and you only need this for logging. (As opposed to generating lots and lots of similar classes for some reason.) – millimoose Jul 26 '12 at 18:43
0

You could do exactly that, have the DoTemplate function return a new instantiated class and you can get the class name from the Objects __class__ string.

sean
  • 3,955
  • 21
  • 28
0

i think MacroPy is what you're looking for: https://github.com/lihaoyi/macropy#case-classes

Hutch
  • 10,392
  • 1
  • 22
  • 18