relation class

Aaron Brady castironpi at gmail.com
Thu Apr 23 06:34:18 CEST 2009


On Apr 22, 11:52 am, Aaron Brady <castiro... at gmail.com> wrote:
> On Apr 22, 12:09 am, Chris Rebert <c... at rebertia.com> wrote:
>
> > On Tue, Apr 21, 2009 at 5:51 PM, Aaron Brady <castiro... at gmail.com> wrote:
> > > Hi all,
>
> > > I think Python should have a relation class in the standard library.
> > > Fat chance.
>
> > Perhaps I'm not understanding "relation" correctly, but are you not
> > aware ofhttp://docs.python.org/library/sqlite3.html?
>
> > Cheers,
> > Chris
> > --
> > I have a blog:http://blog.rebertia.com
snip
> It only supports numbers and strings.
snip

My point is that in undirected relations, it's redundant to maintain
reciprocal membership.  Each participant is a member of the other.
'child.parent.child is child'.  It's not a difficult redundancy to
maintain, but it isn't true to the concept.

Here is another sample:

Tree= Relation( ( "parent", "child", "direction" ) )
nodes= [ object( ) for _ in range( 10 ) ]
Tree( ( nodes[ 0 ], nodes[ 1 ], "left" ) )
Tree( ( nodes[ 0 ], nodes[ 2 ], "right" ) )

Here is the query (*non-functional)*:

recordset= Tree.select( [ "child" ],
    "parent is nodes[0] and direction=='left'" )

Here's an alternative*:

recordset= Tree.select( [ "child" ],
    lambda record: record.parent is nodes[0] and
        record.direction=='left' )

I want some more concise ways of retrieving the same data.  Those two
don't even work as is.*

recordset= Tree.select( operator.and_(
    operator.is_( 'parent', nodes[0] ),
    operator.eq( 'direction', 'left' ) ) )

This is evaluated too soon.  The comparisons need to be
'functools.partial' functions*.

recordset= Tree.select(
    partial(
        operator.and,
        partial(
            operator.is_,
            'parent',
            nodes[0]
        ),
        partial(
            operator.eq,
            'direction',
            'left'
        )
    )
)

This is close, but the partial functions just compare strings.  They
would have to be replaced with specialized functions that can
recognize designated strings as field names, and replace them with
actual fields.

Furthermore, it doesn't address the awkwardness of prefix notation,
which is required for function calls that aren't native operators.

I think the first is the closest.  'ast' makes it particularly
convenient, though maybe not trivial, to parse the selection.  Where
it sees an 'ast.Name' node, it can replace it with an actual field
name.  Here it is again*:

recordset= Tree.select( [ "child" ],
    "parent is nodes[0] and direction=='left'" )

The only problem is passing variables in to the expression.  By the
time 'nodes[0]' would get evaluated, it would be too late to know what
it is, without dirty frame stackery.  'select' would need the context
of its caller, which isn't available.

I think some kind of markers would have to replace any identifiers it
would use:

recordset= Tree.select( [ "child" ],
    "parent is %var and direction=='left'", nodes[0] )

It's counterintuitive, but it's better than entirely prefix notation.
This way the function gets all the actual objects it needs, and can
still take shortcuts in its search.

I don't really see the argument for only returning a subset of fields,
instead of the entire record where matched, although I may not have
experience enough to know the downside, such as in the case of large
joins.  It could be optional, defaulting to 'select *'.

recordset= Tree.select(
    "parent is %var and direction=='left'", nodes[0] )

Since select returns an iterator, it's probably wise to include a
'selectone' function, like the 'Cursor.fetchone' function in
'sqllite3'.  Of course, one could just add a '.next()' call to the
front of the query.

record= next( Tree.select(
    "parent is %var and direction=='left'", nodes[0] ) )

or

record= Tree.selectone(
    "parent is %var and direction=='left'", nodes[0] )

Does anyone see a better way?  Would anyone have use for it?  Do you
agree that it is more conceptually true to data structures like
trees?  Is the optimization worth a specialized syntax?  Even if
selection used a linear-time search, would encapsulating relations be
an improvement over redundant and cyclic attributes?  Are the
equivalents in existing packages just as light-weight and functional?
That is, is it competitive?

Furthermore, is anyone developing something which uses a quoted
expression in a custom evaluation?  I'd be interested in seeing those
results too.  I understand that languages like LISP and Logix (
http://www.livelogix.com/logix/ ) are suited for it, but I want
something that is just a single class.  Is it outside the scope of
Python's capabilities to do?



More information about the Python-list mailing list