[Tutor] Class attributes not overriding parameters

Andreas Kostyrka andreas at kostyrka.org
Sun Nov 6 10:54:59 CET 2005


Am Samstag, den 05.11.2005, 22:30 +0100 schrieb Jan Eden:
> Hi,
> 
> I use the following construction to make sure the data attribute site_id is set only once for each object:
> 
> def GetSiteID(self):
>     return self._site_id
> 
> def SetSiteID(self, value):
>     if not (hasattr(self, '_site_id') and self._site_id): self._site_id = value
>     
> site_id = property(GetSiteID, SetSiteID)
> 
> site_id is supposed to be set either through a parameter, derived from the server name (the default case) or via a class attribute:
> 
> class SiteList(Lists):
>     site_id = 1
> 
> The latter case does not work: the site_id is still derived from the server name for objects of class SiteList. Why is that? How can I make Python check the superclasses for a class attribute before applying the SiteMode() method?

The basic misunderstanding is how it all works :)

class X:
	dict_definition

Basically, Python just collects all that definitions into a dictionary,
and it passes it into the type constructor. Using metaclasses one can
actually manipulate this dictionary.

class X:
	a = 1
	def b(self):
		print self.a

x=X()
X.__dict__['b'] # function
X.b             # unbound method
x.b             # bound method

x.b() # print 1
x.a = 100 # e.g. self.a = self.a + 99
x.b() # print 100
print X.a # print 1
print x.a # print 100

So basically, one of the mechanisms of Python is to look for attributes
(like self.a) first in self, and then in all the class dictionaries.

Back to your example:
class SiteList(Lists):
    site_id = 1

you can basically do two things: (both solutions untested)

Use the internal variable name:

class SiteList(Lists):
    _site_id = 1 

This way the hasattr method will find a _site_id attribute.

Or use a metaclass, which would then result in something like this

class MyMeta(type):
    def __init__(cls, name, bases, dict):
        super(MyMeta, cls).__init__(name, bases, dict)
        if cls.__dict__.has_key("site_id"):
            cls._site_id = cls.site_id
        def getSite(self):
            return self._site_id
        def setSite(self, val):
            if not (hasattr(self, '_site_id') and self._site_id):
                self._site_id = val
            else:
                raise TypeError("site_id already set")
            
        cls.site_id = property(getSite, setSite)

class Base(object):
    __metaclass__ = MyMeta

class Test(Base):
    site_id = 100

t = Base()
t2 = Test()
t.site_id = "Baseid"
print t.site_id
try:
    t.site_id = "Baseid"
    assert None == "Something went really wrong."
except TypeError:
    pass
print t2.site_id

t2.site_id = 101

Andreas
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: Dies ist ein digital signierter Nachrichtenteil
Url : http://mail.python.org/pipermail/tutor/attachments/20051106/5a309c84/attachment-0001.pgp


More information about the Tutor mailing list