0

I have the following:

class X(object):
    def __init__(self, *args, **kwargs):
        type(self).label_type = xyzzy(self.__class__.__name__)

class Y(X):
    def __init__(self, *args, **kwargs):
        super(Y, self).__init__(self, *args, **kwargs)

When I create a new instance of Y, a class variable called label_type is created using Y, not X. This is good and works fine.

But it burns me that I have to wait until there's an instance of Y before the class variable is created. How can I set label_type when class Y is compiled, not when it is instantiated?

EDIT - I have numerous subclasses that are derived from X. I want to push as much of the work into X as possible.

Tony Ennis
  • 12,000
  • 7
  • 52
  • 73

2 Answers2

3

You can use a metaclass to do this kind of thing. Here's a trivial example to demonstrate:

class NameLabelMeta(type):

    def __new__(meta, name, bases, dct):
        """Create a new class and label it with its name."""
        cls = super(NameLabelMeta, meta).__new__(meta, name, bases, dct)
        cls.label_type = name  # or xyzzy(name), or whatever
        return cls

In use:

>>> class X(object):
    __metaclass__ = NameLabelMeta  # 2.x syntax


>>> class Y(X):
    pass

>>> Y.label_type
'Y'

Note that Y transparently inherits the metaclass from X, so doesn't need to implement anything at all for the correct behaviour to occur. It's also much more efficient, as it doesn't happen again every time you create a new instance of the class.

jonrsharpe
  • 115,751
  • 26
  • 228
  • 437
  • This looks like it will work, but I need time to understand it. – Tony Ennis Oct 28 '15 at 11:14
  • @TonyEnnis that's fair enough! A metaclass lets you customise creation of classes, in the same way that a class lets you customise creation of instances. See e.g. http://stackoverflow.com/q/100003/3001761 – jonrsharpe Oct 28 '15 at 11:16
2

Do you need to set the label_type dynamically? Why not use a "static variable" such as

class X(object):
    LABEL_TYPE = 'X'

class Y(X):
    pass

print Y().LABEL_TYPE # Prints 'X'
KeatsKelleher
  • 10,015
  • 4
  • 45
  • 52