descriptor problems

G

Gary Stephenson

I want to define a class-level attribute that will be shared by all
subclasses. That is, I want this class, every subclass of this class, every
instance of this class and every instance of every subclass to be able to
read and write to the _same_ slot/variable. But I can't figure out how to
do it.

My attempts so far have led me to using a descriptor as follow, but it
doesn't get me where I want to be:

class sharedClassVar(object):
def __init__(self,x=None):
print "creating"
self.value = x
def __get__(self,ob,cls):
print "getting"
return self.value
def __set__(self,ob,x):
print "setting"
self.value = x


class A( object ):
# install it like this I guess:
cls2 = sharedClassVar(5)

class B( A ):
pass

print A.cls2 # so far so good
o = A()
o2 = B()
print o.cls2 # ok
print o2.cls2 # ok
o.cls2 = 2
print B.cls2 # perfect
print o2.cls2 # ""
o2.cls2 = 3
print A.cls2 # ""
print o.cls2 # ""

# but I need to be able to update the value through the class
# how do I do it?
A.cls2 = 4 # whoops - we just overwrote the descriptor with an integer

A.cls2.__set__(None,4) # AttributeError: 'int' object has no attribute
'__set__'
 
P

Peter Otten

Gary said:
I want to define a class-level attribute that will be shared by all
subclasses. That is, I want this class, every subclass of this class,
every instance of this class and every instance of every subclass to be
able to
read and write to the _same_ slot/variable. But I can't figure out how to
do it.

class A:
class __metaclass__(type):
_shared = 42
def get_shared(self):
return self.__class__._shared
def set_shared(self, value):
print "%r --> %r" % (self._shared, value)
self.__class__._shared = value
shared = property(get_shared, set_shared)

def get_shared(self):
return self.__class__.shared
def set_shared(self, value):
self.__class__.shared = value
shared = property(get_shared, set_shared)

Does that what you want?

Peter
 
M

Michele Simionato

Gary said:
# but I need to be able to update the value through the class
# how do I do it?
A.cls2 = 4 # whoops - we just overwrote the descriptor with an integer

A.cls2.__set__(None,4) # AttributeError: 'int' object has no attribute
'__set__'

You need to define the descriptor at the metaclass level too.

Michele Simionato
 
G

Gary Stephenson

Peter Otten said:
class A:
class __metaclass__(type):
_shared = 42
def get_shared(self):
return self.__class__._shared
def set_shared(self, value):
print "%r --> %r" % (self._shared, value)
self.__class__._shared = value
shared = property(get_shared, set_shared)

def get_shared(self):
return self.__class__.shared
def set_shared(self, value):
self.__class__.shared = value
shared = property(get_shared, set_shared)

Does that what you want?

It certainly does! But I need to figure out how to package it up a bit more
elegantly. I'd prefer not to have to define a separate metaclass for each
class if I could avoid it. hmmm ..... The following is what I eventually
came up with, which is exactly what I was after:

class valueDescriptor(object):
def __init__(self,x=None):
self.value = x
def __get__(self,ob,cls=None):
return self.value
def __set__(self,ob,x):
self.value = x

class Ameta(type):
def createShared( cls, nm, initValue=None ):
o = valueDescriptor(initValue)
setattr( cls,nm, o )
setattr( cls.__class__,nm, o )

class A:
__metaclass__ = Ameta

class B( A ):
A.createShared("cls2",1)


Many thanks,

gary
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,768
Messages
2,569,575
Members
45,053
Latest member
billing-software

Latest Threads

Top