Container Objects Enforcing Contents

Jim Kraai jkraai at paypal.com
Wed Feb 13 19:33:04 EST 2002


On 13-Feb-2002 Sean 'Shaleh' Perry wrote:
> On 13-Feb-2002 jim kraai wrote:
> > Greetings,
> > 
> > I'm looking for suggestions on making container objects which must,
> > may, or must not allow particular kinds of container objects to be
> > added.
> > 
> > Any suggestions on a general approach for this?
> 
> Let's see .......
> 
> a constraints approach:
> 
> class Foo:
>     def __init__(self, item):
>         try:
>             # look for a method of item that must exist
>         except AttributeError:
>             raise ConstraintException
> 
> This way you could add only items which support a method or have a certain
> attribute.
> 
> You could also try to enforce types by ensuring the type of item matches
types
> you know about.  This often leads to a maintenance nightmare though.

Maybe a dictionary approach based on the parental enforcement
class Type1:
	def __init__(self,item):
		self.type = 'Type1'
		self.children_must = ['type2','type3']
		self.children_may  = ['type4','type5']
		}

	def addChild(self,child):
		if (
			! child.name in self.children_must or
			! child.name in self.children_may
		):
			raise exception

The problem with this is that it can accumulate children over time, 
but when will all of the constraints be finalized/enforced?  Add a 
finalize method?

	def finalize(self):
		# loop over self.children_must and verify existence
		# if constraints not met, raise exception
		# recurse and call finalize for all children

This sounds like a pain, the mandatory call to root.finalize() would 
be a good way to make enforcement _optional_, but maybe not good in a 
context where you want it to be enforced 100% of the time.

Maybe leave the enforcement responsibility on the child, but this 
could be semantically very ugly because of the need to pass the parent 
to the child for introspection.

Maybe child enforcement could be done by the parent calling a method 
in the child class before the child is actually added
in (parent) class Type 1:
	def addChild(self,child):
		if child.validateParent(self):
			self.children.append(child)

in (child) class Type 2:
	def __init__(self):
		self.valid_parents = [list of acceptable parents]
	def validateParent(self,parent):
		if ! parent.type in self.self.valid_parents:
			raise exception

It looks like leaving validation up to the child might be marginally 
easier, but it doesn't remove the need for the finalize call.

--jim




More information about the Python-list mailing list