Re: RFC: Assignment as expression (pre-PEP)
Alex Martelli schrieb: Adam Atlas [EMAIL PROTECTED] wrote: Hasn't this been discussed many many times before? I think Guido has been favourable to the idea of allowing :=, but that was a long time ago, and I don't think anything ever came of it. Personally, if anything, I'd like to see more use of the 'as' keyword as in Python 2.5's new 'with' statement. Assignment is basically what it adds to the statement, so if anything we should reuse it in other statements for consistency. if my_re1.match(exp) as temp: # do something with temp elif my_re2.match(exp) as temp: # do something with temp elif my_re3.match(exp) as temp: # do something with temp elif my_re4.match(exp) as temp: # do something with temp As others have mentioned, your particular instance is probably evidence that you need to restructure your code a little bit, but I do agree that x = y; if x: ... is a common enough idiom that it warrants a shortcut. And reusing as, I think, is nice and readable, and it's an advantage that it doesn't require adding any new keywords or symbols. Actually, I agree with you. Unfortunately, I doubt python-dev will, but the chance is good enough that it's probably worth proposing there (ideally together with a patch to implement it, just to avoid any [otherwise likely] whines about this being difficult to implement:-). The patch is already done -- I have it lying around here :) Georg -- Thus spake the Lord: Thou shalt indent with four spaces. No more, no less. Four shall be the number of spaces thou shalt indent, and the number of thy indenting shall be four. Eight shalt thou not indent, nor either indent thou two, excepting that thou then proceed to four. Tabs are right out. -- http://mail.python.org/mailman/listinfo/python-list
Re: RFC: Assignment as expression (pre-PEP)
Hasn't this been discussed many many times before? I think Guido has been favourable to the idea of allowing :=, but that was a long time ago, and I don't think anything ever came of it. Personally, if anything, I'd like to see more use of the 'as' keyword as in Python 2.5's new 'with' statement. Assignment is basically what it adds to the statement, so if anything we should reuse it in other statements for consistency. if my_re1.match(exp) as temp: # do something with temp elif my_re2.match(exp) as temp: # do something with temp elif my_re3.match(exp) as temp: # do something with temp elif my_re4.match(exp) as temp: # do something with temp As others have mentioned, your particular instance is probably evidence that you need to restructure your code a little bit, but I do agree that x = y; if x: ... is a common enough idiom that it warrants a shortcut. And reusing as, I think, is nice and readable, and it's an advantage that it doesn't require adding any new keywords or symbols. -- http://mail.python.org/mailman/listinfo/python-list
Re: RFC: Assignment as expression (pre-PEP)
Adam Atlas [EMAIL PROTECTED] wrote: Hasn't this been discussed many many times before? I think Guido has been favourable to the idea of allowing :=, but that was a long time ago, and I don't think anything ever came of it. Personally, if anything, I'd like to see more use of the 'as' keyword as in Python 2.5's new 'with' statement. Assignment is basically what it adds to the statement, so if anything we should reuse it in other statements for consistency. if my_re1.match(exp) as temp: # do something with temp elif my_re2.match(exp) as temp: # do something with temp elif my_re3.match(exp) as temp: # do something with temp elif my_re4.match(exp) as temp: # do something with temp As others have mentioned, your particular instance is probably evidence that you need to restructure your code a little bit, but I do agree that x = y; if x: ... is a common enough idiom that it warrants a shortcut. And reusing as, I think, is nice and readable, and it's an advantage that it doesn't require adding any new keywords or symbols. Actually, I agree with you. Unfortunately, I doubt python-dev will, but the chance is good enough that it's probably worth proposing there (ideally together with a patch to implement it, just to avoid any [otherwise likely] whines about this being difficult to implement:-). Alex -- http://mail.python.org/mailman/listinfo/python-list
RE: RFC: Assignment as expression (pre-PEP)
Alex Martelli wrote: As others have mentioned, your particular instance is probably evidence that you need to restructure your code a little bit, but I do agree that x = y; if x: ... is a common enough idiom that it warrants a shortcut. And reusing as, I think, is nice and readable, and it's an advantage that it doesn't require adding any new keywords or symbols. Actually, I agree with you. Unfortunately, I doubt python-dev will, but the chance is good enough that it's probably worth proposing there (ideally together with a patch to implement it, just to avoid any [otherwise likely] whines about this being difficult to implement:-). This was proposed on python-dev (or maybe it was python-ideas) - I think the discussion died out though without any resolution. You should check the archives to see if there was a resolution on it, and if not I'd suggest putting a PEP together, rather than just raising it again. Tim Delaney -- http://mail.python.org/mailman/listinfo/python-list
Re: RFC: Assignment as expression (pre-PEP)
On Apr 7, 9:55 pm, Paul McGuire [EMAIL PROTECTED] wrote: seriesAndEpnum = Combine( OneOrMore( ~Literal(-) + Word(alphas) ).setParseAction( capitalizeAll ), joinString= ).setResultsName(series) + \ Word(nums).setResultsName(episodeNum) should be: seriesAndEpnum = Combine( OneOrMore( Word(alphas) ).setParseAction( capitalizeAll ), joinString= ).setResultsName(series) + \ - + Word(nums).setResultsName(episodeNum) (This example is hypothetical based on the limited info in your posted code, the purpose of this element was to try to emulate your case where two variables are defined in a single expression.) -- Paul -- http://mail.python.org/mailman/listinfo/python-list
Re: RFC: Assignment as expression (pre-PEP)
On Apr 5, 2:51 pm, [EMAIL PROTECTED] wrote: I would like to gauge interest in the following proposal: Problem: Assignment statements cannot be used as expressions. Performing a list of mutually exclusive checks that require data processing can cause excessive tabification. For example, consider the following python snipet... temp = my_re1.match(exp) if temp: # do something with temp else: temp = my_re2.match(exp) if temp: # do something with temp else: temp = my_re3.match(exp) if temp: # do something with temp else: temp = my_re4.match(exp) # etc. Even with 2-space tabification, after about 20 matches, the indentation will take up half an 80-column terminal screen. Details: Python distinguishes between an assignment statement and an equality expression. This is to force disambiguation of assignment and comparison so that a statement like: if x = 3: Will raise an expression rather than allowing the programmer to accidentally overwrite x. Likewise, x == 3 Will either return True, False or raise a NameError exception, which can alert the author of any potential coding mistakes since if x = 3 (assignment) was meant, assignment being a statement returns nothing (though it may raise an exception depending on the underlying assignment function called). Because this forced disambiguation is a guiding virtue of the python language, it would NOT be wise to change these semantics of the language. Proposal: Add a new assignment-expression operator to disambiguate it completely from existing operators. Although any number of glyph could be used for such a new operator, I here propose using pascal/gnu make-like assignment. Specifically, let: x = 3 Be a statement that returns nothing; let: x == 3 Be an expression that, when x is a valid, in-scope name, returns True or False; let: x := 3 Be an expression that first assigned the value (3) to x, then returns x. Thus... if x = 3: # Rais exception pass if x == 3: # Execute IFF x has a value equivalent to 3 pass if x := 3: # Executes based on value of x after assignment; # since x will be 3 and non-zero and thus represents true, always executed pass Additional: Since python allows in-place operator assignment, (e.g. +=, *=, etc.), allow for these forms again by prefixing each diglyph with a colon (:), forming a triglyph. E.g. if x :+= 3: # Executes IFF, after adding 3 to x, x represents a non-zero number. pass Also note, that although the colon operator is used to denote the beginning of a programme block, it should be easily distinguished from the usage of : to denote a diglyph or triglyph assignment expression as well as the trinary conditional expression. This is because firstly, the statement(s) following a colon (:) in existing python should never begin with an assignment operator. I.e., if x: = y is currently not valid python. Any attempt at interpreting the meaning of such an expression in the current implementation of python is likely to fail. Secondly, the diglyph and triglyph expressions do not contain spaces, further disambiguating them from existing python. Alternative proposals for dyglyph and triglyph representations for assignment expressions are welcome. Implementation details: When the python interpreter parser encounters a diglyph or triglyph beginning with a colon (:) and ending with an equals sign (=), perform the assignment specified by glyph[1:] and then return the value of the variable(s) on the left-hand side of the expression. The assignment function called would be based on standard python lookup rules for the corresponding glyph[1:] operation (the glyph without the leading colon). Opposition: Adding any new operator to python could be considered code bloat. Using a colon in this way could still be ambiguous. Adding the ability to read triglyph operators in the python interpreter parser would require too big a code revision. Usage is too obscure. Using an assignment expression would lead to multiple conceptual instructions for a single python statement (e.g. first an assignment, then an if based on the assignment would mean two operations for a single if statement.) Comments: [Please comment] Jeffrey. If you really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really want to do something like this, just create a wrapper class: class Wrapper(object):
Re: RFC: Assignment as expression (pre-PEP)
Dustan [EMAIL PROTECTED] wrote: class Wrapper(object): def __init__(self, obj): self.obj = obj def getit(self): return self.obj def setit(self, obj): self.obj = obj return obj Yeah, that's substantialy the same approach I posted as a Python Cookbook recipe almost six years ago, see http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/66061 . My specific use case for that recipe was when using Python to code a reference algorithm found in a book, so that deep restructuring was unwanted -- a similar but opposite case is using Python to explore prototype algorithms that would later be recoded e.g. in C (here, too, you don't really want to refactor the Python code to use dictionaries properly, so assign-and-test is handy). Alex -- http://mail.python.org/mailman/listinfo/python-list
Re: RFC: Assignment as expression (pre-PEP)
On Apr 8, 10:56 am, [EMAIL PROTECTED] (Alex Martelli) wrote: Dustan [EMAIL PROTECTED] wrote: class Wrapper(object): def __init__(self, obj): self.obj = obj def getit(self): return self.obj def setit(self, obj): self.obj = obj return obj Yeah, that's substantialy the same approach I posted as a Python Cookbook recipe almost six years ago, see http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/66061 . Indeed, I did discover that in my copy of the Python Cookbook some time ago. Perhaps I should have noted that. My specific use case for that recipe was when using Python to code a reference algorithm found in a book, so that deep restructuring was unwanted -- a similar but opposite case is using Python to explore prototype algorithms that would later be recoded e.g. in C (here, too, you don't really want to refactor the Python code to use dictionaries properly, so assign-and-test is handy). Alex -- http://mail.python.org/mailman/listinfo/python-list
Re: RFC: Assignment as expression (pre-PEP)
On Apr 5, 4:08 pm, [EMAIL PROTECTED] [EMAIL PROTECTED] wrote: I love event-based parsers so I have no problem with that approach in general. You might find a pyparsing version of this to be to your liking. It is possible in the parser events (or parse actions as pyparsing calls them) to perform operations such as capitalization, string replacement, or string-to-integer conversion. To assign names to specific fields, one defines results names using setResultsName. A grammar for your file name might look something like (I'm just guessing from your code): from pyparsing import * def parseName2(name): Parse filenames of the form: programmeTitle.year.series.episodeNum.episodeName.capper.ext capper = oneOf(JJ JeffreyJacobs).replaceWith(Jeffrey C. Jacobs).setResultsName(capper) ext = Word(alphanums).setResultsName(ext) year = Word(nums,exact=4).setResultsName(year) capitalizeAll = lambda tokens : map(str.capitalize, tokens) title = Combine( OneOrMore( ~year + Word(alphas) ).setParseAction( capitalizeAll ), joinString= ) \ .setResultsName(programme) seriesAndEpnum = Combine( OneOrMore( ~Literal(-) + Word(alphas) ).setParseAction( capitalizeAll ), joinString= ).setResultsName(series) + \ Word(nums).setResultsName(episodeNum) epname = Combine( OneOrMore( ~capper + Word(alphas) ).setParseAction( capitalizeAll ), joinString= ) \ .setResultsName(episodeName) fileName = title + . + year + . + seriesAndEpnum + . + epname + . + capper + . + ext parts = fileName.parseString(name) return parts.programme, parts.series, parts.episodeName, parts.episodeNum, parst.year, parts.capper, parts.ext In this example, the parse actions are capitalizeAll (easily implemented with a simple lambda), and replaceWith (which is included with pyparsing). -- Paul -- http://mail.python.org/mailman/listinfo/python-list
Re: RFC: Assignment as expression (pre-PEP)
Gabriel Genellina [EMAIL PROTECTED] wrote: You have to build the handlers list, containing (regex, handler) items; the unknown case might be a match-all expression at the end. Well, after playing a bit with decorators I got this: snip That's a nice class, and more maintainable with the separate handler methods than a long function. Here's a completely untested variation. I hope the intent is clear: def handle_this(regex, handlers=handlers): # A decorator; associates the function to the regex # (Not intended to be used as a normal method! # not even a static method!) def register(function, regex=regex): handlers.append((function.__name__, regex)) return function return register ... insert handlers here ... def parse(self): regex = '|'.join(['(?P%s%s)' % pair for pair in self.handlers]) fields = str.split(self.name) for field in fields: match = regex.match(field) if match: handler = getattr(self, match.lastgroup, self.handle_unknown) handler(self, field, match) The handler functions themselves would have to be constrained to also use only named groups, but you gain by only having a single regex.match call on each field which could (if there are a lot of handlers) be significant. The calculation of regex could also of course be pulled out of parse to somewhere it only happens once for the class instead of once per instance. -- http://mail.python.org/mailman/listinfo/python-list
RFC: Assignment as expression (pre-PEP)
I would like to gauge interest in the following proposal: Problem: Assignment statements cannot be used as expressions. Performing a list of mutually exclusive checks that require data processing can cause excessive tabification. For example, consider the following python snipet... temp = my_re1.match(exp) if temp: # do something with temp else: temp = my_re2.match(exp) if temp: # do something with temp else: temp = my_re3.match(exp) if temp: # do something with temp else: temp = my_re4.match(exp) # etc. Even with 2-space tabification, after about 20 matches, the indentation will take up half an 80-column terminal screen. Details: Python distinguishes between an assignment statement and an equality expression. This is to force disambiguation of assignment and comparison so that a statement like: if x = 3: Will raise an expression rather than allowing the programmer to accidentally overwrite x. Likewise, x == 3 Will either return True, False or raise a NameError exception, which can alert the author of any potential coding mistakes since if x = 3 (assignment) was meant, assignment being a statement returns nothing (though it may raise an exception depending on the underlying assignment function called). Because this forced disambiguation is a guiding virtue of the python language, it would NOT be wise to change these semantics of the language. Proposal: Add a new assignment-expression operator to disambiguate it completely from existing operators. Although any number of glyph could be used for such a new operator, I here propose using pascal/gnu make-like assignment. Specifically, let: x = 3 Be a statement that returns nothing; let: x == 3 Be an expression that, when x is a valid, in-scope name, returns True or False; let: x := 3 Be an expression that first assigned the value (3) to x, then returns x. Thus... if x = 3: # Rais exception pass if x == 3: # Execute IFF x has a value equivalent to 3 pass if x := 3: # Executes based on value of x after assignment; # since x will be 3 and non-zero and thus represents true, always executed pass Additional: Since python allows in-place operator assignment, (e.g. +=, *=, etc.), allow for these forms again by prefixing each diglyph with a colon (:), forming a triglyph. E.g. if x :+= 3: # Executes IFF, after adding 3 to x, x represents a non-zero number. pass Also note, that although the colon operator is used to denote the beginning of a programme block, it should be easily distinguished from the usage of : to denote a diglyph or triglyph assignment expression as well as the trinary conditional expression. This is because firstly, the statement(s) following a colon (:) in existing python should never begin with an assignment operator. I.e., if x: = y is currently not valid python. Any attempt at interpreting the meaning of such an expression in the current implementation of python is likely to fail. Secondly, the diglyph and triglyph expressions do not contain spaces, further disambiguating them from existing python. Alternative proposals for dyglyph and triglyph representations for assignment expressions are welcome. Implementation details: When the python interpreter parser encounters a diglyph or triglyph beginning with a colon (:) and ending with an equals sign (=), perform the assignment specified by glyph[1:] and then return the value of the variable(s) on the left-hand side of the expression. The assignment function called would be based on standard python lookup rules for the corresponding glyph[1:] operation (the glyph without the leading colon). Opposition: Adding any new operator to python could be considered code bloat. Using a colon in this way could still be ambiguous. Adding the ability to read triglyph operators in the python interpreter parser would require too big a code revision. Usage is too obscure. Using an assignment expression would lead to multiple conceptual instructions for a single python statement (e.g. first an assignment, then an if based on the assignment would mean two operations for a single if statement.) Comments: [Please comment] Jeffrey. -- http://mail.python.org/mailman/listinfo/python-list
Re: RFC: Assignment as expression (pre-PEP)
On Thu, 2007-04-05 at 12:51 -0700, [EMAIL PROTECTED] wrote: I would like to gauge interest in the following proposal: Problem: Assignment statements cannot be used as expressions. Performing a list of mutually exclusive checks that require data processing can cause excessive tabification. For example, consider the following python snipet... temp = my_re1.match(exp) if temp: # do something with temp else: temp = my_re2.match(exp) if temp: # do something with temp else: temp = my_re3.match(exp) if temp: # do something with temp else: temp = my_re4.match(exp) # etc. Even with 2-space tabification, after about 20 matches, the indentation will take up half an 80-column terminal screen. If that's your only justification for this proposal, that's almost certainly not enough to convince anybody of its necessity. Your code example should be rewritten as a loop: match_actions = [(my_re1, action1), (my_re2, action2), ...] for my_re, action in match_actions: if my_re.match(exp): action(exp) break Hope this helps, Carsten -- http://mail.python.org/mailman/listinfo/python-list
Re: RFC: Assignment as expression (pre-PEP)
[EMAIL PROTECTED] wrote: Performing a list of mutually exclusive checks that require data processing can cause excessive tabification. For example, consider the following python snipet... temp = my_re1.match(exp) if temp: # do something with temp else: temp = my_re2.match(exp) if temp: # do something with temp else: temp = my_re3.match(exp) if temp: # do something with temp else: temp = my_re4.match(exp) Can you come up with a real example where this happens and which cannot be easily rewritten to provide better, clearer code without the indentation? I'll admit to having occasionally had code not entirely dissimilar to this when first written, but I don't believe it has ever survived more than a few minutes before being refactored into a cleaner form. I would claim that it is a good thing that Python makes it obvious that code like this should be refactored. -- http://mail.python.org/mailman/listinfo/python-list
Re: RFC: Assignment as expression (pre-PEP)
Carsten Haese [EMAIL PROTECTED] wrote: If that's your only justification for this proposal, that's almost certainly not enough to convince anybody of its necessity. Your code example should be rewritten as a loop: match_actions = [(my_re1, action1), (my_re2, action2), ...] for my_re, action in match_actions: if my_re.match(exp): action(exp) break Depending on what his 'do something with temp' actually was, it may or may not be easy to rewrite it as a for loop. However, even if a for loop isn't an obvious replacement other solutions may be appropriate such as combining the regular expressions to a single regex with named groups and/or using the command pattern. If assignment was an expression that only addresses one problem with the sample code. It still leaves his code with excessive repetition and probably with an excessively long function that calls out to be refactored as a group of smaller methods. -- http://mail.python.org/mailman/listinfo/python-list
Re: RFC: Assignment as expression (pre-PEP)
On Apr 5, 4:22 pm, Duncan Booth [EMAIL PROTECTED] wrote: Can you come up with a real example where this happens and which cannot be easily rewritten to provide better, clearer code without the indentation? I'll admit to having occasionally had code not entirely dissimilar to this when first written, but I don't believe it has ever survived more than a few minutes before being refactored into a cleaner form. I would claim that it is a good thing that Python makes it obvious that code like this should be refactored. I am trying to write a parser for a text string. Specifically, I am trying to take a filename that contains meta-data about the content of the A/V file (mpg, mp3, etc.). I first split the filename into fields separated by spaces and dots. Then I have a series of regular expression matches. I like Cartesian's 'event-based' parser approach though the even table gets a bit unwieldy as it grows. Also, I would prefer to have the 'action' result in a variable assignment specific to the test. E.g. def parseName(name): fields = sd.split(name) fields, ext = fields[:-1], fields[-1] year = '' capper = '' series = None episodeNum = None programme = '' episodeName = '' past_title = false for f in fields: if year_re.match(f): year = f past_title = True else: my_match = capper_re.match(f): if my_match: capper = capper_re.match(f).group(1) if capper == 'JJ' or capper == 'JeffreyJacobs': capper = 'Jeffrey C. Jacobs' past_title = True else: my_match = epnum_re.match(f): if my_match: series, episodeNum = my_match.group('series', 'episode') past_title = True else: # If I think of other parse elements, they go here. # Otherwise, name is part of a title; check for capitalization if f[0] = 'a' and f[0] = 'z' and f not in do_not_capitalize: f = f.capitalize() if past_title: if episodeName: episodeName += ' ' episodeName += f else: if programme: programme += ' ' programme += f return programme, series, episodeName, episodeNum, year, capper, ext Now, the problem with this code is that it assumes only 2 pieces of free-form meta-data in the name (i.e. Programme Name and Episode Name). Also, although this is not directly adaptable to Cartesian's approach, you COULD rewrite it using a dictionary in the place of local variable names so that the event lookup could consist of 3 properties per event: compiled_re, action_method, dictionary_string. But even with that, in the case of the epnum match, two assignments are required so perhaps a convoluted scheme such that if dictionary_string is a list, for each of the values returned by action_method, bind the result to the corresponding ith dictionary element named in dictionary_string, which seems a bit convoluted. And the fall-through case is state-dependent since the 'unrecognized field' should be shuffled into a different variable dependent on state. Still, if there is a better approach I am certainly up for it. I love event-based parsers so I have no problem with that approach in general. -- http://mail.python.org/mailman/listinfo/python-list
Re: RFC: Assignment as expression (pre-PEP)
[EMAIL PROTECTED]: else: my_match = capper_re.match(f): if my_match: capper = capper_re.match(f).group(1) if capper == 'JJ' or capper == 'JeffreyJacobs': capper = 'Jeffrey C. Jacobs' past_title = True The assignment to my_match here is not used, so the test can be if capper_re.match(f) which can then merge up into the previous else as an elif dropping one level of indentation. Neil -- http://mail.python.org/mailman/listinfo/python-list
Re: RFC: Assignment as expression (pre-PEP)
On Apr 5, 6:01 pm, Neil Hodgson [EMAIL PROTECTED] wrote: [EMAIL PROTECTED]: else: my_match = capper_re.match(f): if my_match: capper = capper_re.match(f).group(1) if capper == 'JJ' or capper == 'JeffreyJacobs': capper = 'Jeffrey C. Jacobs' past_title = True The assignment to my_match here is not used, so the test can be if capper_re.match(f) which can then merge up into the previous else as an elif dropping one level of indentation. Neil That was a typo. I meant to reuse my_match in the line capper = my_match.group(1) rather than the line above just so I would not have to evaluate the regular expression twice. Sorry for the confusion. Jeffrey. -- http://mail.python.org/mailman/listinfo/python-list
Re: RFC: Assignment as expression (pre-PEP)
[EMAIL PROTECTED] wrote: On Apr 5, 4:22 pm, Duncan Booth [EMAIL PROTECTED] wrote: Can you come up with a real example where this happens and which cannot be easily rewritten to provide better, clearer code without the indentation? I'll admit to having occasionally had code not entirely dissimilar to this when first written, but I don't believe it has ever survived more than a few minutes before being refactored into a cleaner form. I would claim that it is a good thing that Python makes it obvious that code like this should be refactored. I am trying to write a parser for a text string. Specifically, I am trying to take a filename that contains meta-data about the content of the A/V file (mpg, mp3, etc.). I first split the filename into fields separated by spaces and dots. Then I have a series of regular expression matches. I like Cartesian's 'event-based' parser approach though the even table gets a bit unwieldy as it grows. Also, I would prefer to have the 'action' result in a variable assignment specific to the test. E.g. def parseName(name): fields = sd.split(name) fields, ext = fields[:-1], fields[-1] year = '' capper = '' series = None episodeNum = None programme = '' episodeName = '' past_title = false for f in fields: if year_re.match(f): year = f past_title = True else: my_match = capper_re.match(f): if my_match: capper = capper_re.match(f).group(1) if capper == 'JJ' or capper == 'JeffreyJacobs': capper = 'Jeffrey C. Jacobs' past_title = True else: my_match = epnum_re.match(f): if my_match: series, episodeNum = my_match.group('series', 'episode') past_title = True else: # If I think of other parse elements, they go here. # Otherwise, name is part of a title; check for capitalization if f[0] = 'a' and f[0] = 'z' and f not in do_not_capitalize: f = f.capitalize() if past_title: if episodeName: episodeName += ' ' episodeName += f else: if programme: programme += ' ' programme += f return programme, series, episodeName, episodeNum, year, capper, ext Why can't you combine your regular expressions into a single expression, e.g. something like:: exp = r''' ... (?Pyear\d{4}) ... | ... by\[(?Pcapper.*)\] ... | ... S(?Pseries\d\d)E(?Pepisode\d\d) ... ''' matcher = re.compile(exp, re.VERBOSE) matcher.match('1990').groupdict() {'series': None, 'capper': None, 'episode': None, 'year': '1990'} matcher.match('by[Jovev]').groupdict() {'series': None, 'capper': 'Jovev', 'episode': None, 'year': None} matcher.match('S01E12').groupdict() {'series': '01', 'capper': None, 'episode': '12', 'year': None} Then your code above would look something like:: for f in fields: match = matcher.match(f) if match is not None: year = match.group('year') capper = match.group('capper') if capper == 'JJ' or capper == 'JeffreyJacobs': capper = 'Jeffrey C. Jacobs' series = match.group('series') episodeNum = match.group('episode') past_title = True else: if 'a' = f[0] = 'z' and f not in do_not_capitalize: f = f.capitalize() if past_title: if episodeName: episodeName += ' ' episodeName += f else: if programme: programme += ' ' programme += f STeVe -- http://mail.python.org/mailman/listinfo/python-list
Re: RFC: Assignment as expression (pre-PEP)
Steven Bethard wrote: [EMAIL PROTECTED] wrote: On Apr 5, 4:22 pm, Duncan Booth [EMAIL PROTECTED] wrote: Can you come up with a real example where this happens and which cannot be easily rewritten to provide better, clearer code without the indentation? I'll admit to having occasionally had code not entirely dissimilar to this when first written, but I don't believe it has ever survived more than a few minutes before being refactored into a cleaner form. I would claim that it is a good thing that Python makes it obvious that code like this should be refactored. I am trying to write a parser for a text string. Specifically, I am trying to take a filename that contains meta-data about the content of the A/V file (mpg, mp3, etc.). I first split the filename into fields separated by spaces and dots. Then I have a series of regular expression matches. I like Cartesian's 'event-based' parser approach though the even table gets a bit unwieldy as it grows. Also, I would prefer to have the 'action' result in a variable assignment specific to the test. E.g. def parseName(name): fields = sd.split(name) fields, ext = fields[:-1], fields[-1] year = '' capper = '' series = None episodeNum = None programme = '' episodeName = '' past_title = false for f in fields: if year_re.match(f): year = f past_title = True else: my_match = capper_re.match(f): if my_match: capper = capper_re.match(f).group(1) if capper == 'JJ' or capper == 'JeffreyJacobs': capper = 'Jeffrey C. Jacobs' past_title = True else: my_match = epnum_re.match(f): if my_match: series, episodeNum = my_match.group('series', 'episode') past_title = True else: # If I think of other parse elements, they go here. # Otherwise, name is part of a title; check for capitalization if f[0] = 'a' and f[0] = 'z' and f not in do_not_capitalize: f = f.capitalize() if past_title: if episodeName: episodeName += ' ' episodeName += f else: if programme: programme += ' ' programme += f return programme, series, episodeName, episodeNum, year, capper, ext Why can't you combine your regular expressions into a single expression, e.g. something like:: exp = r''' ... (?Pyear\d{4}) ... | ... by\[(?Pcapper.*)\] ... | ... S(?Pseries\d\d)E(?Pepisode\d\d) ... ''' matcher = re.compile(exp, re.VERBOSE) matcher.match('1990').groupdict() {'series': None, 'capper': None, 'episode': None, 'year': '1990'} matcher.match('by[Jovev]').groupdict() {'series': None, 'capper': 'Jovev', 'episode': None, 'year': None} matcher.match('S01E12').groupdict() {'series': '01', 'capper': None, 'episode': '12', 'year': None} Then your code above would look something like:: for f in fields: match = matcher.match(f) if match is not None: year = match.group('year') capper = match.group('capper') if capper == 'JJ' or capper == 'JeffreyJacobs': capper = 'Jeffrey C. Jacobs' series = match.group('series') episodeNum = match.group('episode') past_title = True I guess you need to be a little more careful here not to overwrite your old values, e.g. something like:: year = match.group('year') or year capper = match.group('capper') or capper ... STeVe -- http://mail.python.org/mailman/listinfo/python-list
Re: RFC: Assignment as expression (pre-PEP)
[EMAIL PROTECTED] a écrit : I would like to gauge interest in the following proposal: Problem: Assignment statements cannot be used as expressions. This is by design. Performing a list of mutually exclusive checks that require data processing can cause excessive tabification. For example, consider the following python snipet... temp = my_re1.match(exp) if temp: # do something with temp else: temp = my_re2.match(exp) if temp: # do something with temp else: temp = my_re3.match(exp) if temp: # do something with temp else: temp = my_re4.match(exp) OMG. actions = [ (my_re1, do_something_with_temp1), (my_re2, do_something_with_temp2), (my_re3, do_something_with_temp3), (my_re4, do_something_with_temp4), ] for my_re, do_something_with in actions: temp = my_re.match(exp): if temp: do_something_with(temp) break Having full-blown anonymous functions or Ruby/Smalltalk-like code blocks would be much more interesting IMHO. -- http://mail.python.org/mailman/listinfo/python-list
Re: RFC: Assignment as expression (pre-PEP)
Duncan Booth a écrit : [EMAIL PROTECTED] wrote: Performing a list of mutually exclusive checks that require data processing can cause excessive tabification. For example, consider the following python snipet... temp = my_re1.match(exp) if temp: # do something with temp else: temp = my_re2.match(exp) if temp: # do something with temp else: temp = my_re3.match(exp) if temp: # do something with temp else: temp = my_re4.match(exp) Can you come up with a real example where this happens and which cannot be easily rewritten to provide better, clearer code without the indentation? I'll admit to having occasionally had code not entirely dissimilar to this when first written, but I don't believe it has ever survived more than a few minutes before being refactored into a cleaner form. I would claim that it is a good thing that Python makes it obvious that code like this should be refactored. +2 QOTW -- http://mail.python.org/mailman/listinfo/python-list
Re: RFC: Assignment as expression (pre-PEP)
En Thu, 05 Apr 2007 18:08:46 -0300, [EMAIL PROTECTED] [EMAIL PROTECTED] escribió: I am trying to write a parser for a text string. Specifically, I am trying to take a filename that contains meta-data about the content of the A/V file (mpg, mp3, etc.). I first split the filename into fields separated by spaces and dots. Then I have a series of regular expression matches. I like Cartesian's 'event-based' parser approach though the even table gets a bit unwieldy as it grows. Also, I would prefer to have the 'action' result in a variable assignment specific to the test. E.g. def parseName(name): fields = sd.split(name) fields, ext = fields[:-1], fields[-1] year = '' capper = '' series = None episodeNum = None programme = '' episodeName = '' past_title = false for f in fields: if year_re.match(f): year = f past_title = True else: my_match = capper_re.match(f): if my_match: capper = capper_re.match(f).group(1) if capper == 'JJ' or capper == 'JeffreyJacobs': capper = 'Jeffrey C. Jacobs' past_title = True else: my_match = epnum_re.match(f): if my_match: series, episodeNum = my_match.group('series', 'episode') past_title = True else: # If I think of other parse elements, they go here. # Otherwise, name is part of a title; check for capitalization if f[0] = 'a' and f[0] = 'z' and f not in do_not_capitalize: f = f.capitalize() if past_title: if episodeName: episodeName += ' ' episodeName += f else: if programme: programme += ' ' programme += f return programme, series, episodeName, episodeNum, year, capper, ext Now, the problem with this code is that it assumes only 2 pieces of free-form meta-data in the name (i.e. Programme Name and Episode Name). Also, although this is not directly adaptable to Cartesian's approach, you COULD rewrite it using a dictionary in the place of local variable names so that the event lookup could consist of 3 properties per event: compiled_re, action_method, dictionary_string. But even with that, in the case of the epnum match, two assignments are required so perhaps a convoluted scheme such that if dictionary_string is a list, for each of the values returned by action_method, bind the result to the corresponding ith dictionary element named in dictionary_string, which seems a bit convoluted. And the fall-through case is state-dependent since the 'unrecognized field' should be shuffled into a different variable dependent on state. Still, if there is a better approach I am certainly up for it. I love event-based parsers so I have no problem with that approach in general. Maybe it's worth using a class instance. Define methods to handle each matching regex, and keep state in the instance. class NameParser: def handle_year(self, field, match): self.year = field self.past_title = True def handle_capper(self, field, match): capper = match.group(1) if capper == 'JJ' or capper == 'JeffreyJacobs': capper = 'Jeffrey C. Jacobs' self.capper = capper self.past_title = True def parse(self, name): fields = sd.split(name) for field in fields: for regex,handler in self.handlers: match = regex.match(field) if match: handler(self, field, match) break You have to build the handlers list, containing (regex, handler) items; the unknown case might be a match-all expression at the end. Well, after playing a bit with decorators I got this: class NameParser: year = '' capper = '' series = None episodeNum = None programme = '' episodeName = '' past_title = False handlers = [] def __init__(self, name): self.name = name self.parse() def handle_this(regex, handlers=handlers): # A decorator; associates the function to the regex # (Not intended to be used as a normal method! not even a static method!) def register(function, regex=regex): handlers.append((re.compile(regex), function)) return function return register @handle_this(r\(?\d+\)?) def handle_year(self, field, match): self.year = field self.past_title = True @handle_this(r(expression)) def handle_capper(self, field, match): capper = match.group(1) if capper == 'JJ' or capper == 'JeffreyJacobs':