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