RE: polymorphism in python

Discussion in 'Python' started by Robert Brewer, Nov 27, 2003.

  1. Roy Smith wrote:
    > But how often is it actually useful to do such a thing? I can't
    > remember the last time I wanted to do something like that in
    > Python.


    And Jay O'Connor replied:
    > Generally, if you are programming to the interface and not to
    > the class (which is what you are usually doing in OO programming,
    > or should be if your language allows it) than testing for the
    > actual type of an object is usually a no-no


    I find this comes up quite often in application interfaces; that is,
    points at which your code manipulates someone else's code in someone
    else's language. A prime example is forming valid SQL statements:

    "SELECT * FROM xyz WHERE %(Name)s = %(Value)s" % ({'Name': fieldName,
    'Value': fieldValue})

    If fieldValue is an int, fine. If it's a string, you're probably going
    to wrap '%(Value)s' in quote marks. So do you:

    1) Explicitly check type.
    2) Design your language so you can set attributes on basic type classes:
    def format_str_for_SQL(...):
    ...
    str.format_for_SQL = format_str_for_SQL
    3) Use custom subclasses of basic types like int and str throughout the
    app.
    4) Same as #3, with metaclassing.
    5) Hard-code every possible SQL statement.
    6) Try: the SQL statement each way. Watch the permutation explosion with
    multiple fields (now I'm just getting silly, but I've seen sillier
    things in the field, sometimes written by me).

    There are other ways. I'm probably going to go with option 1 in this
    limited case, although in other cases option 3 has appeal.


    Robert Brewer
    MIS
    Amor Ministries
    Robert Brewer, Nov 27, 2003
    #1
    1. Advertising

  2. Robert Brewer

    Roy Smith Guest

    In article <>,
    "Robert Brewer" <> wrote:

    > Roy Smith wrote:
    > > But how often is it actually useful to do such a thing? I can't
    > > remember the last time I wanted to do something like that in
    > > Python.

    >
    > And Jay O'Connor replied:
    > > Generally, if you are programming to the interface and not to
    > > the class (which is what you are usually doing in OO programming,
    > > or should be if your language allows it) than testing for the
    > > actual type of an object is usually a no-no

    >
    > I find this comes up quite often in application interfaces; that is,
    > points at which your code manipulates someone else's code in someone
    > else's language. A prime example is forming valid SQL statements:
    >
    > "SELECT * FROM xyz WHERE %(Name)s = %(Value)s" % ({'Name': fieldName,
    > 'Value': fieldValue})


    OK, that's a fair example (and one that I've dealt with myself). In
    C++, you might write a polymorphic function:

    MyClass::doSqlStuff (String fieldName, int fieldValue);
    MyClass::doSqlStuff (String fieldName, String fieldValue);

    In Python you'd just write a single function and embed some logic to do
    the right thing depending on which type you got passed:

    def doSqlStuff (fieldName, fieldValue):
    if type (fieldValue) == StringType: # or whatever
    formatString = "'%s'"
    else:
    formatString = "%d"

    Either way, it's basicly "if this type, execute this code, if that type,
    execute some other code". The only real difference is that in something
    like C++, the conditional logic is done implicitly by the compiler (with
    hints from you in the form of which polymorphic methods you supply) and
    in Python you write the condition explicitly. I find the explicit form
    much easier to write, understand, and debug.

    And don't get me started on the evils of automatic type promition and
    inexact signature matching in C++.
    Roy Smith, Nov 27, 2003
    #2
    1. Advertising

  3. Robert Brewer

    Jay O'Connor Guest

    Roy Smith wrote:

    >In article <>,
    > "Robert Brewer" <> wrote:
    >
    >
    >
    >>Roy Smith wrote:
    >>
    >>
    >>>But how often is it actually useful to do such a thing? I can't
    >>>remember the last time I wanted to do something like that in
    >>>Python.
    >>>
    >>>

    >>And Jay O'Connor replied:
    >>
    >>
    >>>Generally, if you are programming to the interface and not to
    >>>the class (which is what you are usually doing in OO programming,
    >>>or should be if your language allows it) than testing for the
    >>>actual type of an object is usually a no-no
    >>>
    >>>

    >>I find this comes up quite often in application interfaces; that is,
    >>points at which your code manipulates someone else's code in someone
    >>else's language. A prime example is forming valid SQL statements:
    >>
    >>"SELECT * FROM xyz WHERE %(Name)s = %(Value)s" % ({'Name': fieldName,
    >>'Value': fieldValue})
    >>
    >>

    >
    >OK, that's a fair example (and one that I've dealt with myself).
    >


    That was another example that came to mind...dealing with external
    systems that care a bit more.

    > In
    >C++, you might write a polymorphic function:
    >
    >MyClass::doSqlStuff (String fieldName, int fieldValue);
    >MyClass::doSqlStuff (String fieldName, String fieldValue);
    >
    >In Python you'd just write a single function and embed some logic to do
    >the right thing depending on which type you got passed:
    >
    >def doSqlStuff (fieldName, fieldValue):
    > if type (fieldValue) == StringType: # or whatever
    > formatString = "'%s'"
    > else:
    > formatString = "%d"
    >
    >Either way, it's basicly "if this type, execute this code, if that type,
    >execute some other code". The only real difference is that in something
    >like C++, the conditional logic is done implicitly by the compiler (with
    >hints from you in the form of which polymorphic methods you supply) and
    >in Python you write the condition explicitly. I find the explicit form
    >much easier to write, understand, and debug.
    >
    >


    I actually ran into this recently with a Smalltalk application to
    Postgresql. However, since Smalltalk allows you to add new behavior to
    existing classes; I just added String>>asDBString and
    Number>>asDBString. So my above code would look like:

    MyClass>>doSqlStuff:: filedName with: fieldValue
    formatString := fieldValue asDBString.

    And it would polymophically get the right formatted string without any
    type checking at all.

    Adding such behavior to Object, Number, String, UndefniedObject etc...is
    an effective way to get around such checking. For example if a value is
    undefined (None) than you usually have to print something like "NULL"
    (on INSERTs) to the database, so I implemented
    UndefiinedObject>>asDBString to return 'NULL' so my code doensn't have
    to check for nil values
    Jay O'Connor, Nov 27, 2003
    #3
  4. Robert Brewer

    David Bolen Guest

    Jay O'Connor <> writes:

    > I actually ran into this recently with a Smalltalk application to
    > Postgresql. However, since Smalltalk allows you to add new behavior
    > to existing classes; I just added String>>asDBString and
    > Number>>asDBString. So my above code would look like:
    >
    > MyClass>>doSqlStuff:: filedName with: fieldValue
    > formatString := fieldValue asDBString.
    >
    > And it would polymophically get the right formatted string without any
    > type checking at all.


    While you could inject such a method with user defined classes, it's
    clearly a problem for built-in types. But one approach to achieve
    something similar in Python would be to define an interface (using a
    PEP 246-like approach such as PyProtocols) that contained the
    asDBString method, and explicitly adapt the arguments to the SQL
    function to that interface.

    You could then define (right in the module defining that interface if
    you like) very simple adapters for the built-in types that would let
    them be used without changing any calling code. So you could end up
    with a module like (I prefer the abstract class version of interfaces):

    - - - - - - - - - - - - - - - - - - - - - - - - -

    from protocols import Interface, advise, adapt

    class ISQLFieldValue(Interface):
    """Value to be used in a SQL operation"""

    def asDBString(self):
    """Return string representation valid for use in a query"""
    raise NotImplementedError


    class SQLAdapterString:
    """Adapter for string types"""

    advise(instancesProvide = [ISQLFieldValue],
    asAdapterForTypes = [str,unicode])

    def __init__(self, ob, protocol):
    self.ob = ob

    def asDBString(self):
    return "'%s'" % self.ob


    class SQLAdapterNumeric:
    """Adapter for numeric types"""

    advise(instancesProvide = [ISQLFieldValue],
    asAdapterForTypes = [int,long])

    def __init__(self, ob, protocol):
    self.ob = ob

    def asDBString(self):
    return str(self.ob)


    class MyClass:

    def doSqlStuff (fieldName, fieldValue):
    formatString = adapt(fieldValue,ISQLFieldValue).asDBString()
    return formatString

    - - - - - - - - - - - - - - - - - - - - - - - - -


    And once written, other objects could inherit the interface, and/or
    other modules could externally define their own adapters for other
    data types, and MyClass never needs to change.

    -- David
    David Bolen, Dec 11, 2003
    #4
    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. Michael Peuser

    Re: Polymorphism the Python way

    Michael Peuser, Aug 31, 2003, in forum: Python
    Replies:
    6
    Views:
    1,751
    Bob Gailer
    Sep 3, 2003
  2. Graham Fawcett

    Re: Polymorphism the Python way

    Graham Fawcett, Aug 31, 2003, in forum: Python
    Replies:
    1
    Views:
    315
    Daniel Klein
    Sep 2, 2003
  3. Peter Otten

    Re: Polymorphism the Python way

    Peter Otten, Aug 31, 2003, in forum: Python
    Replies:
    1
    Views:
    298
    Daniel Klein
    Sep 2, 2003
  4. rashkatsa

    polymorphism in python

    rashkatsa, Nov 26, 2003, in forum: Python
    Replies:
    7
    Views:
    8,064
    Jay O'Connor
    Nov 26, 2003
  5. Krivenok Dmitry
    Replies:
    13
    Views:
    1,391
    Axter
    Jun 1, 2006
Loading...

Share This Page