C-like assignment expression?

Paul McGuire ptmcg at austin.rr.com
Wed May 21 11:23:45 EDT 2008


On May 21, 9:09 am, "Diez B. Roggisch" <de... at nospam.web.de> wrote:
> cokofree... at gmail.com wrote:
>
> >> And wastes time. regular expressions can become expensive to match -
> >> doing it twice might be hurtful.
>
> >> Diez
>
> > match = (my_re1.match(line) or my_re2.match(line)) or
> > my_re3.match(line)
>
> How do you know *which* of the three has matched then?
>
> Diez

Since the OP is processing alternative regexp's, he may be drifting
close to parsing territory.  Here is a pyparsing example showing how
to match one of 'n' alternatives, and then apply functional logic
depending on which expression was matched.  This example actually
shows 4 ways to address this question (in roughly increasing order of
OO-ness):
- explicit if/elif/... test on the name of the specific match to see
which alternative matched
- more Pythonic dispatch using a dict of names and corresponding
expression processing functions
- parse-time processing using pyparsing parse actions
- parse actions invoke class constructors, to return expression-
specific objects

-- Paul


from pyparsing import oneOf, Combine, Optional, Word, \
    alphas, nums, alphanums, QuotedString

# define basic expressions
sign = oneOf("+ -")
integer = Combine(Optional(sign) + Word(nums))
real = Combine(Optional(sign) + Word(nums) + "." +
Optional(Word(nums)))
name = Word(alphas,alphanums) | QuotedString("'")

# define alternates with results names
item = real("real") | integer("integer") | name("name")

print "\nUse results names to determine which pattern matched"
for it in item.searchString("abc 123 -3.14 'phase of the moon'"):
    if it.getName() == "real":
        print "Real:", (float(it[0]))
    elif it.getName() == "integer":
        print "Int:", (int(it[0]))
    else:
        print "String:", it[0]


print "\nUse dict to dispatch to type-specific functions " \
       "- more Pythonically canonical"
def processRealItem(it):
    print "Real:", (float(it[0]))

def processIntegerItem(it):
    print "Int:", (int(it[0]))

def processNameItem(it):
    print "String:", it[0]

for it in item.searchString("abc 123 -3.14 'phase of the moon'"):
    {"real"    : processRealItem,
     "integer" : processIntegerItem,
     "name"    : processNameItem }[it.getName()](it)


print "\nMove expression-specific logic into parse-time parse actions"
def convertInt(t):
    return int(t[0])
def convertReal(t):
    return float(t[0])
integer.setParseAction(convertInt)
real.setParseAction(convertReal)
item = real("real") | integer("integer") | name("name")

for it in item.searchString("abc 123 -3.14 'phase of the moon'"):
    print "%s: %s %s" % (it.getName(), it[0], type(it[0]))


print "\nUse class constructors as parse-time parse actions " \
      "- results names no longer needed"
class IntObject(object):
    def __init__(self,t):
        self.type, self.value = "Int", int(t[0])
class RealObject(object):
    def __init__(self,t):
        self.type, self.value = "Real", float(t[0])
class StringObject(object):
    def __init__(self,t):
        self.type, self.value = "String", t[0]
integer.setParseAction(IntObject)
real.setParseAction(RealObject)
name.setParseAction(StringObject)
item = real | integer | name

for it in item.searchString("abc 123 -3.14 'phase of the moon'"):
    print "%s: %s (%s)" % (it[0].type, it[0].value,
it[0].__class__.__name__)


Prints:

Use results names to determine which pattern matched
String: abc
Int: 123
Real: -3.14
String: phase of the moon

Use dict to dispatch to type-specific functions - more Pythonically
canonical
String: abc
Int: 123
Real: -3.14
String: phase of the moon

Move expression-specific logic into parse-time parse actions
name: abc <type 'str'>
integer: 123 <type 'int'>
real: -3.14 <type 'float'>
name: phase of the moon <type 'str'>

Use class constructors as parse-time parse actions - results names no
longer needed
String: abc (StringObject)
Int: 123 (IntObject)
Real: -3.14 (RealObject)
String: phase of the moon (StringObject)




More information about the Python-list mailing list