RE: Redefining __call__ in an instance

Discussion in 'Python' started by Robert Brewer, Jan 16, 2004.

  1. 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
     
    Robert Brewer, Jan 16, 2004
    #1
    1. Advertising

  2. 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
    >
    >


    --
    (------------------------------(
    )~~~~~ Jason A. Mobarak ~~~~~~~)
    (~~ aether_at_gentoo_dot_org ~~(
    )~~~~ jmob_at_unm_dot_edu ~~~~~)
    (------------------------------(
     
    Jason Mobarak, Jan 16, 2004
    #2
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Patrick Lioi
    Replies:
    7
    Views:
    353
    Beni Cherniavsky
    Aug 19, 2003
  2. chenyu
    Replies:
    1
    Views:
    300
  3. Robert Ferrell

    Redefining __call__ in an instance

    Robert Ferrell, Jan 15, 2004, in forum: Python
    Replies:
    5
    Views:
    368
    John Roth
    Jan 21, 2004
  4. Ksenia Marasanova
    Replies:
    2
    Views:
    329
    Ksenia Marasanova
    Sep 9, 2005
  5. Steve Holden

    Re: instance has no __call__ method

    Steve Holden, Dec 11, 2010, in forum: Python
    Replies:
    0
    Views:
    1,234
    Steve Holden
    Dec 11, 2010
Loading...

Share This Page