Redefining __call__ in an instance

Jason Mobarak jmob at nospam__unm.edu
Thu Jan 15 21:58:48 EST 2004


class SomeThing(object):
   def __call__ (self):
     print 'gnihtemos'

# get a reference to ourself
M = __import__(__name__)

'''
Return the requested class but don't instantiate it, leaves open the 
possibilty that class reference may be need to be stored and instantiate 
later.
'''

def factory(S):
   return getattr(M, S, None)

# A class version that instantiates.

class FactoryError (TypeError): pass

class Factory (object):

   def __new__(cls, name):

     C = getattr(cls, '_call_%s' % (name,), None)
     if C is None:
       raise FactoryError('Nothing know about %s' % (name,))
     cls.__call__ = C

     return object.__new__(cls)

   def _call_SomeThing (self):

     print 'something'

   def __init__(self, n):

     pass


'''
Also, the point of doing this is to make getting a factory class more
convenient.  If you need *args and **kwargs in your factory-lookup
functionality there's no point in using it because it's no longer anonymous.

Consider the following:
'''

def init_factory (S, *args, **kwargs):
   return getattr(M, S, None)(*args, **kwargs)

class Foo:
   def __init__ (self, need, to, know):
     pass

class ooF:
   def __init__ (self, still, need, to, know):
     pass

# So doing:

init_factory('Foo', 'a', 'b', 'c')
init_factory('ooF', 'a', 'b', 'c', 'd')

# Is no different than:

target = None

# ... do stuff with target here ...

if target == 'Foo':
   f = Foo('a', 'b', 'c')
elif target == 'ooF':
   o = ooF('a', 'b', 'c', 'd')

"""
Okay, so a class could have it's __init__ define *args, **kwargs cull 
it's own data. But that's only useful for **kwargs, since otherwise you 
still need to know in the requesting code what kind class is needed, 
unless *args is just an arbitrary tuple of data in which case you could 
just pass a tuple to the class. Still this is a a bit past the point 
because the dictionary data in kwargs could just be passed as a dictory
"""

class Bar:

   def __init__ (self, *args, **kwargs):

     self.arbData = args
     self.sil = None
     self.i = None
     self.con = None

     for (key, val,) in kwargs.items():
       setter = getattr(self, key, None)
       if setter is None:
         setattr(self, key, val)
       else:
         setter(self, val)

   def set_sil (self, d):

     # check sil here
     self.sil = d

   def set_i (self, d):

     # check i here
     self.i = d

   def set_con (self, d):

     # check con here
     self.con = d

   def __call__ (self):
     print self.sil, self.i, self.con

DATA = """sil = foo
i = bar
con = baz
"""

if __name__ == '__main__':

   factory('SomeThing')()()
   Factory('SomeThing')()

   import cStringIO

   fp = cStringIO.StringIO(DATA)

   def g_ki (fp):

     while True:
       L = fp.readline()

       if L == '':
         break

       T = [I.strip() for I in L.split('=', 1)]

       if len(T) != 2:
         yield (T[0], None)
       else:
         yield tuple(T)

   g = g_ki(fp)
   data_dict = {}
   for (key, val,) in g:
     data_dict[key] = val

   init_factory('Bar', **data_dict)()

output = """
gnihtemos
something
foo bar baz
"""


Robert Brewer wrote:
> Robert Ferrell wrote:
> 
>>I'd like to have a factory class that takes a string argument 
>>and returns
>>the appropriate factory method based on that string.  I'd like the
>>instances to be callable.  Like this:
>>
>>fact = Factory('SomeThing')
>>aSomeThing = fact(some args)
>>
>>anotherFact = Factory('SomeThingElse')
>>anotherThing = anotherFact(some other args)
> 
> 
> Perhaps this will give you some ideas:
> 
> 
>>>>class SomeThing(object):
> 
> ... 	pass
> ... 
> 
>>>>def Factory(classname, *args, **kwargs):
> 
> ... 	return globals()[classname](*args, **kwargs)
> ... 
> 
>>>>st = Factory('SomeThing')
>>>>st
> 
> <__main__.SomeThing object at 0x010C0F10>
> 
> 
> If you still want to package that into a class instead of a function
> (and then override __call__), feel free. Obviously, more exception
> checking could be done.
> 
> 
> Robert Brewer
> MIS
> Amor Ministries
> fumanchu at amor.org
> 

-- 
(------------------------------(
  )~~~~~ Jason A. Mobarak ~~~~~~~)
(~~ aether_at_gentoo_dot_org ~~(
  )~~~~ jmob_at_unm_dot_edu ~~~~~)
(------------------------------(



More information about the Python-list mailing list