Question about accessing class-attributes.

Michele Simionato mis6 at pitt.edu
Fri Apr 25 20:00:47 CEST 2003


Michael Hudson <mwh at python.net> wrote in message news:<7h3bryulp3e.fsf at pc150.maths.bris.ac.uk>...
> mis6 at pitt.edu (Michele Simionato) writes:
> 
> > The meta-type conflict is rather annoying, indeed. According to the
> > metaclass book, the language should generate the correct metaclass
> > that solves the conflict automatically, without burden for the
> > programmer. Python is not that magic (yet) therefore you have to
> > solve the conflict yourself.
> 
> I guess a potential problem is that if you do
> 
> class C(object):
>     __metaclass__ = A
> 
> class D(object):
>     __metaclass__ = B
> 
> class E(C, D):
>     pass
> 
> class F(C, D):
>     pass
> 
> you'd like both E and F to have the *same* (rather than merely
> equivalent) metaclasses.  This would seem to be tricky to arrange.
> 
> Cheers,
> M.

Yes, but I didn't posted  my full solution ;)

I take a list of all generated metaclasses and I reuse them:

  def withmemory(f):
      """This closure remembers all f invocations"""
      argskw=[]; result=[]
      def _(*args,**kw): 
          akw=args,kw
          try: # returns a previously stored result
              i=argskw.index(akw)
          except ValueError: # there is no previously stored result
              res=f(*args,**kw)  # returns the new result
              argskw.append(akw) # update argskw
              result.append(res) # update result
              return res
          else:
              return result[i]  
      _.argskw=argskw #makes the argskw list accessible outside
      _.result=result #makes the result list accessible outside
      return _

 
  _generatemetaclass=withmemory(_generatemetaclass) 

Now, when _generatemetaclass is invoked with the same bases it returns the
same metaclass:
   
>>> class A(type): pass
...
>>> class B(type): pass
...
>>> class C: __metaclass__=A
...
>>> class D: __metaclass__=B
...
>>> E=child(C,D,name='E')
>>> type(E)
<class 'oopp._AB'>
>>> F=child(C,D,name='F')
>>> type(F)
<class 'oopp._AB'>
>>> type(E) is type(F)
True

It works enough for me ;)

                                    Michele




More information about the Python-list mailing list