ich möchte den Zugriff auf die Attribute einer Klasse kontrollieren, und zwar den Lesezugriff *und* den Schreibzugriff. Suchen und Lesen bringt einen schnell auf die Methoden __get/setattr__ und __get/setattribute__. Leider habe ich irgendwas nicht verstanden oder ich will etwas völlig blödsinniges tun:
Zunächst mal nur die Schreibkontrolle:
Code: Alles auswählen
class SetGetAttr_overwritten( object):
def __init__( self):
self.attr1 = 7
print self.__dict__
def __setattr__(self, name, value):
print "__setattr__"
if name in self.__dict__:
print "Attributschreiben: " + name
self.__dict__[name] = value
else:
print "Attribut anlegen: " + name
self.__dict__[name] = value
obj = SetGetAttr_overwritten()
print obj
print "Attribut1: " + str( obj.attr1)
obj.attr1 = 1
print "Attribut1: " + str( obj.attr1)
Code: Alles auswählen
Attribut anlegen: attr1
{'attr1': 7}
<__main__.SetGetAttr_overwritten object at 0x02DC4AF0>
Attribut1: 7
Attributschreiben: attr1
Attribut1: 1
Jetzt die Kontrolle des Attributlesens:
Code: Alles auswählen
class SetGetAttr_overwritten( object):
def __init__( self):
self.attr1 = 7
print self.__dict__
def __getattr__(self, name):
if name in self.__dict__:
print "Attributlesen: " + name
return self.__dict__[name]
else:
return "Attribut nicht vorhanden (lesen): " + name
obj = SetGetAttr_overwritten()
print obj
print "Attribut1: " + str( obj.attr1)
obj.attr1 = 1
print "Attribut1: " + str( obj.attr1)
print "Attribut3: " + str( obj.attr3)
Code: Alles auswählen
{'attr1': 7}
<__main__.SetGetAttr_overwritten object at 0x02DC4AF0>
Attribut1: 7
Attribut1: 1
Attribut3: Attribut nicht vorhanden (lesen): attr3
Mein Ziel ist es aber auch die Lesezugriffe zu kontrollieren, aber __getattribute__() ist auch keine Hilfe, da hier auch der Zugriff auf __dict__ abgefangen wird. Das bedeutet natürlich, daß die erste Zeile von
Code: Alles auswählen
def __getattribute__(self, name):
if name in self.__dict__:
print "Attributlesen: " + name
return self.__dict__[name]
else:
return "Attribut nicht vorhanden (lesen): " + name
Hintergrund:
Eine Klasse beschreibt den Inhalt bzw die Bedeutung einer Anzahl von Bytes. Die Größe der Datenblöcke ist bekannt und immer gleich, die Bedeutungen sind aber je nach Zusammenhang anders.
Benutzt werden soll es dann so (wie die Blöcke an ihre Daten kommen, lasse ich jetzt mal weg):
Code: Alles auswählen
block1 = DataBlock1()
block2 = DataBlock2()
block1.part2 = 1
if block2.teil2:
block1.part1 = 3
else:
block1.part1 = 1
...
Ein Ziel ist es, mit relativ einfachen Mitteln die Blockbedeutungen zu definieren. Ein weiteres Ziel ist, daß die einzelnen Namen eines Blocks fest definiert sind und nicht über Strings angegeben werden müssen (daher soll es eben eine Klasse werden). Im Beispiel müssen nur die Namen, Masken und Positionen angepaßt werden:
Code: Alles auswählen
class DataBlock1( BlockParent):
def __init__(self, blockName):
super( DataBlock1, self).__init__(blockName = blockName)
self.part1 = BitBlockDef( name = "Part1", pos = 0, mask = 0x3)
self.part2 = BitBlockDef( name = "Part2", pos = 2, mask = 0x4)
self.part3 = BitBlockDef( name = "Part3", pos = 3, mask = 0x8)
self.reserved = BitBlockDef( name = "res", pos = 4, mask = 0xf0)
class DataBlock2( BlockParent):
def __init__(self, blockName):
super( DataBlock1, self).__init__(blockName = blockName)
self.teil1 = BitBlockDef( name = "Teil1", pos = 0, mask = 0xf)
self.teil2 = BitBlockDef( name = "Teil2", pos = 4, mask = 0x10)
self.reserved = BitBlockDef( name = "res", pos = 5, mask = 0xe0)
Die Bitschieberei und Maskiererei wird in der Elternklasse weggekapselt (__get__ und __set__ sind die gewünschten Methoden...):
Code: Alles auswählen
class BitBlockDef( object):
def __init__(self, name = "Part1", pos = 0, mask = 0x3):
self.name = name
self.pos = pos
self.mask = mask
class BlockParent( object):
def __init__( self, blockName = blockName):
self.blockName = blockName
self._dataList = [0,0,0,0]
def __get__( self, name, value)
if name not in self.__dict__:
raise
else:
attr = self.__dict__[name]
if isinstance( attr, BitBlockDef):
# Dieses greift nur auf das erste Byte der Daten zu:
tmp = self.__dict__["_dataList"][0]
val |= ((value & attr.mask) >> attr.pos)
elif isinstance( attr, BytBlockDef):
print "Zugriff auf Bytebereich..."
else:
print "Ungültiger Zugriff: %s!" % name
def __set__( self, name, value)
if name not in self.__dict__:
# Attribut prüfen und anlegen (eigentlich sollen nur "BitBlockDef" und "BytBlockDef" erlaubt sein...)
self.__dict__[name] = value
else:
attr = self.__dict__[name]
if isinstance( attr, BitBlockDef):
# Dieses greift nur auf das erste Byte der Daten zu:
tmp = self.__dict__["_dataList"][0]
tmp |= ((value << attr.pos) & attr.mask)
self.__dict__["_dataList"][0] = tmp
elif isinstance( attr, BytBlockDef):
print "Zugriff auf Bytebereich..."
else:
print "Ungültiger Zugriff: %s!" % name
So, vielleicht hat einer / eine von denen, die bis hier unten hin gekommen sind, eine Idee, wie ich das Problem lösen kann. Das fänd ich prima ...
Gruß und Danke,
Christoph