Reference class in class creation

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Gregor Horvath

    Reference class in class creation

    Hi,

    I want to reference a class itself in its body:

    class SomeElement(obj ect):
    def __init__(self, mycontainer):
    self.mycontaine r=mycontainer

    class SomeContainer(o bject):
    a = SomeElement(Som eContainer)


    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(o bject):
    ----6 a = SomeElement(Som eContainer)
    7
    8

    NameError: name 'SomeContainer' is not defined


    How to do this?

    Unfortunatly the obvious:

    class SomeContainer(o bject):
    def __init__(self):
    self.a = SomeElement(Som eContainer)

    is not possible because of other constraints.

    --
    Servus, Gregor

  • Diez B. Roggisch

    #2
    Re: Reference class in class creation

    Gregor Horvath wrote:
    Hi,
    >
    I want to reference a class itself in its body:
    >
    class SomeElement(obj ect):
    def __init__(self, mycontainer):
    self.mycontaine r=mycontainer
    >
    class SomeContainer(o bject):
    a = SomeElement(Som eContainer)
    >
    >
    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(o bject):
    ----6 a = SomeElement(Som eContainer)
    7
    8
    >
    NameError: name 'SomeContainer' is not defined
    >
    >
    How to do this?
    Anything wrong with:

    class Foo(object):
    pass

    Foo.a = Foo

    ?

    Diez

    Comment

    • Gregor Horvath

      #3
      Re: Reference class in class creation

      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

      Comment

      • Duncan Booth

        #4
        Re: Reference class in class creation

        Gregor Horvath <gh@gregor-horvath.comwrot e:
        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?

        Comment

        • Bruno Desthuilliers

          #5
          Re: Reference class in class creation

          Gregor Horvath wrote:
          Hi,
          >
          I want to reference a class itself in its body:
          >
          class SomeElement(obj ect):
          def __init__(self, mycontainer):
          self.mycontaine r=mycontainer
          >
          class SomeContainer(o bject):
          a = SomeElement(Som eContainer)
          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(o bject):
          def __init__(self):
          self.a = SomeElement(Som eContainer)
          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 'onurb@xiludom. gro'.split('@')])"

          Comment

          • Carl Banks

            #6
            Re: Reference class in class creation


            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__(metatyp e,name,bases,cl sdict):
            # do some weird stuff here
            return type.__new__(me tatype,name,bas es,clsdict)

            You could change it to look like this instead:

            def __new__(metatyp e,name,bases,cl sdict):
            # do some weird stuff here
            cls = type.__new__(me tatype,name,bas es,clsdict)
            cls.a = SomeContainer(c ls)
            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__(metatyp e,name,bases,di ct):
            cls = GivenMetaclass. __new__(metatyp e,name,bases,di ct)
            cls.a = SomeContainer(c ls)
            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

            Comment

            • Gregor Horvath

              #7
              Re: Reference class in class creation

              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_at trs['widget_edit'])
              (bases[0].save)
              return type.__new__(me ta, class_name, bases, new_attrs)


              class MotourForm(Tabl eForm):
              template = "motour.templat es.motourform"
              params = ["delete_attrs", "cancel_att rs"]

              member_widgets = ["delete","cance l"]
              cancel = ResetButton(nam e="cancel")
              delete_attrs = {}

              def __init__(self, controller, *args, **kwargs):
              super(MotourFor m, self).__init__( action = "%s/save" %
              controller.get_ path, *args, **kwargs)
              self.controller = controller
              self.delete = LinkButtonAsk(n ame="delete", caption =
              _(u"Löschen"), question = _(u"Wirklich loeschen"),
              link = "%s/delete" % controller.get_ path())

              self.cancel_att rs = dict(onClick="s elf.location.hr ef='%s/back';"
              % controller.get_ path())

              class TourEdit(Motour Form):
              template = "motour.templat es.touredit"
              params = ["tourposval ue"]

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

              class Tour(MotourCont roller):
              __metaclass__ = ControllerMeta
              sqlobjectclass = model.Tour

              #Here is the problem
              widget_edit = TourEdit(contro ller=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

              Comment

              • Kay Schluehr

                #8
                Re: Reference class in class creation

                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(MotourCont roller):
                pass

                Tour.sqlobjectc lass = model.Tour
                Tour.widget_edi t = TourEdit(contro ller=Tour, name = "tourheader ", ...)

                Tour = validate(Tour)

                Comment

                • Gregor Horvath

                  #9
                  Re: Reference class in class creation

                  Carl Banks schrieb:
                  You could change it to look like this instead:
                  >
                  def __new__(metatyp e,name,bases,cl sdict):
                  # do some weird stuff here
                  cls = type.__new__(me tatype,name,bas es,clsdict)
                  cls.a = SomeContainer(c ls)
                  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__(me ta, class_name, bases, new_attrs)
                  cls.__classinit __.im_func(cls, new_attrs)
                  cls.save = validate(cls.wi dget_edit)(base s[0].save)
                  return cls

                  and the Tour Class:

                  class Tour(MotourCont roller):
                  __metaclass__ = ControllerMeta
                  sqlobjectclass = model.Tour

                  def __classinit__(c ls, newattrs):
                  cls.widget_edit = TourEdit(contro ller=cls, name = "tourheader ",
                  fields = [Label(name="id" )])


                  And this seems to work fine.

                  Thanks
                  --
                  Greg

                  Comment

                  • Guest's Avatar

                    #10
                    Re: Reference class in class creation

                    class Foo(object):
                    me = None
                    def __init__(self):
                    Foo.me = self

                    easy!



                    "Gregor Horvath" <gh@gregor-horvath.comwrot e in message
                    news:a1b59$4562 eff8$547078de$2 1737@news.chell o.at...
                    Hi,
                    >
                    I want to reference a class itself in its body:
                    >
                    class SomeElement(obj ect):
                    def __init__(self, mycontainer):
                    self.mycontaine r=mycontainer
                    >
                    class SomeContainer(o bject):
                    a = SomeElement(Som eContainer)
                    >
                    >
                    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(o bject):
                    ----6 a = SomeElement(Som eContainer)
                    7
                    8
                    >
                    NameError: name 'SomeContainer' is not defined
                    >
                    >
                    How to do this?
                    >
                    Unfortunatly the obvious:
                    >
                    class SomeContainer(o bject):
                    def __init__(self):
                    self.a = SomeElement(Som eContainer)
                    >
                    is not possible because of other constraints.
                    >
                    --
                    Servus, Gregor
                    >

                    Comment

                    Working...