By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
444,199 Members | 1,120 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 444,199 IT Pros & Developers. It's quick & easy.

Reference class in class creation

P: n/a
Hi,

I want to reference a class itself in its body:

class SomeElement(object):
def __init__(self, mycontainer):
self.mycontainer=mycontainer

class SomeContainer(object):
a = SomeElement(SomeContainer)
Unfortunatly this does not work since the name SomeContainer is not
definied at class creation time of SomeContainer:

/tmp/python-9309vMe.py in SomeContainer()
4
5 class SomeContainer(object):
----6 a = SomeElement(SomeContainer)
7
8

NameError: name 'SomeContainer' is not defined
How to do this?

Unfortunatly the obvious:

class SomeContainer(object):
def __init__(self):
self.a = SomeElement(SomeContainer)

is not possible because of other constraints.

--
Servus, Gregor

Nov 21 '06 #1
Share this Question
Share on Google+
9 Replies


P: n/a
Gregor Horvath wrote:
Hi,

I want to reference a class itself in its body:

class SomeElement(object):
def __init__(self, mycontainer):
self.mycontainer=mycontainer

class SomeContainer(object):
a = SomeElement(SomeContainer)
Unfortunatly this does not work since the name SomeContainer is not
definied at class creation time of SomeContainer:

/tmp/python-9309vMe.py in SomeContainer()
4
5 class SomeContainer(object):
----6 a = SomeElement(SomeContainer)
7
8

NameError: name 'SomeContainer' is not defined
How to do this?
Anything wrong with:

class Foo(object):
pass

Foo.a = Foo

?

Diez

Nov 21 '06 #2

P: n/a
Diez B. Roggisch schrieb:
Anything wrong with:

class Foo(object):
pass

Foo.a = Foo

?
Thanks.
The problem with this is that there is also metaclass hacking involved
which relies on "a" 's creation in the class body. In your suggestion
"a" is not present when __new__ of the metaclass is called.

--
Servus, Gregor
Nov 21 '06 #3

P: n/a
Gregor Horvath <gh@gregor-horvath.comwrote:
Diez B. Roggisch schrieb:
>Anything wrong with:

class Foo(object):
pass

Foo.a = Foo

?

Thanks.
The problem with this is that there is also metaclass hacking involved
which relies on "a" 's creation in the class body. In your suggestion
"a" is not present when __new__ of the metaclass is called.
The class doesn't exist until the metaclass has created it, so you can't
expect to have any references to it.

You've told us that what you are trying to do doesn't work, but you haven't
said why you want to do it. What is the problem you are really trying to
solve?
Nov 21 '06 #4

P: n/a
Gregor Horvath wrote:
Hi,

I want to reference a class itself in its body:

class SomeElement(object):
def __init__(self, mycontainer):
self.mycontainer=mycontainer

class SomeContainer(object):
a = SomeElement(SomeContainer)
Are you sure you want to
1/ create SomeElement as a *class* attribute (that is, an attribute
shared by all instances of SomeContainer) and
2/ pass the SomeContainer *class* to the initializer of SomeElement ?

Well, anyway:
>
Unfortunatly this does not work since the name SomeContainer is not
definied at class creation time of SomeContainer:
indeed.
>
How to do this?

Unfortunatly the obvious:

class SomeContainer(object):
def __init__(self):
self.a = SomeElement(SomeContainer)
You do understand that declaring 'a' as an attribute of self creates an
instance attribute, while your above snippet creates 'a' as a class
attribute, do you ?
is not possible because of other constraints.
Care to elaborate ?

FWIW, there are technical answers to your question (look for descriptors
and/or metaclasses)
--
bruno desthuilliers
python -c "print '@'.join(['.'.join([w[::-1] for w in p.split('.')]) for
p in 'o****@xiludom.gro'.split('@')])"
Nov 21 '06 #5

P: n/a

Gregor Horvath wrote:
Diez B. Roggisch schrieb:
Anything wrong with:

class Foo(object):
pass

Foo.a = Foo

?

Thanks.
The problem with this is that there is also metaclass hacking involved
which relies on "a" 's creation in the class body. In your suggestion
"a" is not present when __new__ of the metaclass is called.
The metaclass's __new__ returns the class object. This is the first
time the object is available; it's impossible to access before that,
but you can get at it before __new__ exits. Most metaclass __new__
functions look like this:

def __new__(metatype,name,bases,clsdict):
# do some weird stuff here
return type.__new__(metatype,name,bases,clsdict)

You could change it to look like this instead:

def __new__(metatype,name,bases,clsdict):
# do some weird stuff here
cls = type.__new__(metatype,name,bases,clsdict)
cls.a = SomeContainer(cls)
return cls

Or, if you can't change the metaclass, you can subclass it and override
__new__ to get at cls before __new__ exits:

def __new__(metatype,name,bases,dict):
cls = GivenMetaclass.__new__(metatype,name,bases,dict)
cls.a = SomeContainer(cls)
return cls

If the "metaclass hacking" you describe is setting __metaclass__ to a
function (i.e., not metaclass hacking), then same thing applies, just
modify or wrap the function to get at the class object and do what you
need to do.
Carl Banks

Nov 21 '06 #6

P: n/a
Duncan Booth schrieb:
You've told us that what you are trying to do doesn't work, but you haven't
said why you want to do it. What is the problem you are really trying to
solve?
I need this for some complicated turbogears controller classes for a
generic framework.

The point is that I have a formwidget which has to know which controller
it belongs to. (Because the controller knows the path, the
sqlobjectclass etc.). The widget has to be created at class creation
time of the controller, because there is a metaclass which ensures
validation of the formwidget. (Necessary because the controller is
inherited)

Basically and stripped down this looks like this:

class ControllerMeta(type):
def __new__(meta, class_name, bases, new_attrs):
new_attrs["save"] = validate(new_attrs['widget_edit'])
(bases[0].save)
return type.__new__(meta, class_name, bases, new_attrs)
class MotourForm(TableForm):
template = "motour.templates.motourform"
params = ["delete_attrs","cancel_attrs"]

member_widgets = ["delete","cancel"]
cancel = ResetButton(name="cancel")
delete_attrs = {}

def __init__(self, controller, *args, **kwargs):
super(MotourForm, self).__init__(action = "%s/save" %
controller.get_path, *args, **kwargs)
self.controller = controller
self.delete = LinkButtonAsk(name="delete", caption =
_(u"Löschen"), question = _(u"Wirklich loeschen"),
link = "%s/delete" % controller.get_path())

self.cancel_attrs = dict(onClick="self.location.href='%s/back';"
% controller.get_path())

class TourEdit(MotourForm):
template = "motour.templates.touredit"
params = ["tourposvalue"]

member_widgets = ["tourpos"]
tourpos = DataGridAED()

class Tour(MotourController):
__metaclass__ = ControllerMeta
sqlobjectclass = model.Tour

#Here is the problem
widget_edit = TourEdit(controller=Tour, name = "tourheader",
fields = [Label(name="id", label=_("Tour-ID")),
TextField(name="name")])

I hope it's not to confusing.
Thank's for your help.

--
Greg
Nov 21 '06 #7

P: n/a
Is there a reason why don't you drop the metaclass and perform the
validation step after the class has been created using a generic
function?

class Tour(MotourController):
pass

Tour.sqlobjectclass = model.Tour
Tour.widget_edit = TourEdit(controller=Tour, name = "tourheader", ...)

Tour = validate(Tour)

Nov 21 '06 #8

P: n/a
Carl Banks schrieb:
You could change it to look like this instead:

def __new__(metatype,name,bases,clsdict):
# do some weird stuff here
cls = type.__new__(metatype,name,bases,clsdict)
cls.a = SomeContainer(cls)
return cls
Cark, many thanks for your suggestion, it solved my problem.

I changed the metaclass:

class ControllerMeta(type):
def __new__(meta, class_name, bases, new_attrs):
cls = type.__new__(meta, class_name, bases, new_attrs)
cls.__classinit__.im_func(cls, new_attrs)
cls.save = validate(cls.widget_edit)(bases[0].save)
return cls

and the Tour Class:

class Tour(MotourController):
__metaclass__ = ControllerMeta
sqlobjectclass = model.Tour

def __classinit__(cls, newattrs):
cls.widget_edit = TourEdit(controller=cls, name = "tourheader",
fields = [Label(name="id")])
And this seems to work fine.

Thanks
--
Greg
Nov 21 '06 #9

P: n/a
class Foo(object):
me = None
def __init__(self):
Foo.me = self

easy!

"Gregor Horvath" <gh@gregor-horvath.comwrote in message
news:a1***************************@news.chello.at. ..
Hi,

I want to reference a class itself in its body:

class SomeElement(object):
def __init__(self, mycontainer):
self.mycontainer=mycontainer

class SomeContainer(object):
a = SomeElement(SomeContainer)
Unfortunatly this does not work since the name SomeContainer is not
definied at class creation time of SomeContainer:

/tmp/python-9309vMe.py in SomeContainer()
4
5 class SomeContainer(object):
----6 a = SomeElement(SomeContainer)
7
8

NameError: name 'SomeContainer' is not defined
How to do this?

Unfortunatly the obvious:

class SomeContainer(object):
def __init__(self):
self.a = SomeElement(SomeContainer)

is not possible because of other constraints.

--
Servus, Gregor

Nov 21 '06 #10

This discussion thread is closed

Replies have been disabled for this discussion.