Matt Millar
Matt Millar

Reputation: 21

Access the class type when constructing a class attribute in python?

I'd like to do this:

class MyThing(object):
    def __init__(self,owning_cls):
        self.owning_cls = owning_cls

class MyClass(object):
    thing = MyThing(self.__class__)

print MyClass.thing.owning_cls

This doesn't work - as there isn't a self to refer to in the class construction of MyClass.

Is there any way to achieve this (it's clearly trivial if we make thing an instance attribute, but I'd like to be a class attribute please!)?

Upvotes: 2

Views: 64

Answers (5)

Ponkadoodle
Ponkadoodle

Reputation: 5957

Use a decorator. I find this to be a clean solution because it lets you keep more of the class definition together, rather than having to write additional class-related code after the class definition or forcing you to instantiate MyClass, etc.

class MyThing(object):
    def __init__(self,owning_cls):
        self.owning_cls = owning_cls

def set_thing(cls):
    cls.thing = MyThing(cls)
    return cls

@set_thing
class MyClass(object):
    pass

>>> print MyClass.thing.owner_cls
<class '__main__.MyClass'>

Upvotes: 1

Matt Millar
Matt Millar

Reputation: 21

Ah, the use MetaClasses comment helps a lot here.

This looks like an "easy" way to achieve exactly what I want

class MyClassMetaclass(type):
    def __new__(cls, name, bases, dct):
        cls.thing = MyThing(name)
        return super(MyClassMetaclass, cls).__new__(cls, name, bases, dct)

class MyThing(object):
    def __init__(self,owning_cls):
        self.owning_cls = owning_cls

class MyClass(object):
    __metaclass__=MyClassMetaclass

print MyClass.thing.owning_cls

Upvotes: 0

Aleksei astynax Pirogov
Aleksei astynax Pirogov

Reputation: 2491

Use desciptor:

class Ownable(object):
    def __init__(self, clz):
        self._clz = clz
        self._inst = None
    def __get__(self, inst, owner_clz):
        self._inst = self._inst or self._clz(owner_clz)
        return self._inst

class MyThing(object):
    def __init__(self, owner_clz):
        self.owner_clz = owner_clz

class MyClass(object):
    thing = Ownable(MyThing)

>>> print MyClass.thing.owner_clz
<class '__main__.MyClass'>

Upvotes: 0

djc
djc

Reputation: 11711

Maybe you can initialize the class with __new__?

Upvotes: 0

Marcin
Marcin

Reputation: 49826

Perform the call immediately after the class declaration:

class MyClass(object): pass
MyClass.thing = MyThing(MyClass)

Upvotes: 1

Related Questions