473,657 Members | 2,735 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

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(ex p)
if temp:
# do something with temp
else:
temp = my_re2.match(ex p)
if temp:
# do something with temp
else:
temp = my_re3.match(ex p)
if temp:
# do something with temp
else:
temp = my_re4.match(ex p)

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

Apr 5 '07 #1
20 2125
On Thu, 2007-04-05 at 12:51 -0700, Ti*******@gmail .com 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(ex p)
if temp:
# do something with temp
else:
temp = my_re2.match(ex p)
if temp:
# do something with temp
else:
temp = my_re3.match(ex p)
if temp:
# do something with temp
else:
temp = my_re4.match(ex p)

# 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
Apr 5 '07 #2
Ti*******@gmail .com 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(ex p)
if temp:
# do something with temp
else:
temp = my_re2.match(ex p)
if temp:
# do something with temp
else:
temp = my_re3.match(ex p)
if temp:
# do something with temp
else:
temp = my_re4.match(ex p)
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.
Apr 5 '07 #3
Carsten Haese <ca*****@uniqsy s.comwrote:
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.
Apr 5 '07 #4
On Apr 5, 4:22 pm, Duncan Booth <duncan.bo...@i nvalid.invalidw rote:
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_capitali ze:
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_stri ng.
But even with that, in the case of the epnum match, two assignments
are required so perhaps a convoluted scheme such that if
dictionary_stri ng is a list, for each of the values returned by
action_method, bind the result to the corresponding ith dictionary
element named in dictionary_stri ng, 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.

Apr 5 '07 #5
da******@timeho rse.com:
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
Apr 5 '07 #6
On Apr 5, 6:01 pm, Neil Hodgson <nyamatongwe+th un...@gmail.com wrote:
darkl...@timeho rse.com:
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.

Apr 5 '07 #7
da******@timeho rse.com wrote:
On Apr 5, 4:22 pm, Duncan Booth <duncan.bo...@i nvalid.invalidw rote:
>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_capitali ze:
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'''
... (?P<year>\d{4})
... |
... by\[(?P<capper>.*)\]
... |
... S(?P<series>\d\ d)E(?P<episode> \d\d)
... '''
>>matcher = re.compile(exp, re.VERBOSE)
matcher.match ('1990').groupd ict()
{'series': None, 'capper': None, 'episode': None, 'year': '1990'}
>>matcher.match ('by[Jovev]').groupdict()
{'series': None, 'capper': 'Jovev', 'episode': None, 'year': None}
>>matcher.match ('S01E12').grou pdict()
{'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('ye ar')
capper = match.group('ca pper')
if capper == 'JJ' or capper == 'JeffreyJacobs' :
capper = 'Jeffrey C. Jacobs'
series = match.group('se ries')
episodeNum = match.group('ep isode')
past_title = True
else:
if 'a' <= f[0] <= 'z' and f not in do_not_capitali ze:
f = f.capitalize()
if past_title:
if episodeName:
episodeName += ' '
episodeName += f
else:
if programme:
programme += ' '
programme += f

STeVe
Apr 5 '07 #8
Steven Bethard wrote:
da******@timeho rse.com wrote:
>On Apr 5, 4:22 pm, Duncan Booth <duncan.bo...@i nvalid.invalidw rote:
>>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
capitalizati on
if f[0] >= 'a' and f[0] <= 'z' and f not in
do_not_capital ize:
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'''
... (?P<year>\d{4})
... |
... by\[(?P<capper>.*)\]
... |
... S(?P<series>\d\ d)E(?P<episode> \d\d)
... '''
>>matcher = re.compile(exp, re.VERBOSE)
>>matcher.match ('1990').groupd ict()
{'series': None, 'capper': None, 'episode': None, 'year': '1990'}
>>matcher.match ('by[Jovev]').groupdict()
{'series': None, 'capper': 'Jovev', 'episode': None, 'year': None}
>>matcher.match ('S01E12').grou pdict()
{'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('ye ar')
capper = match.group('ca pper')
if capper == 'JJ' or capper == 'JeffreyJacobs' :
capper = 'Jeffrey C. Jacobs'
series = match.group('se ries')
episodeNum = match.group('ep isode')
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('ye ar') or year
capper = match.group('ca pper') or capper
...

STeVe
Apr 5 '07 #9
Ti*******@gmail .com 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(ex p)
if temp:
# do something with temp
else:
temp = my_re2.match(ex p)
if temp:
# do something with temp
else:
temp = my_re3.match(ex p)
if temp:
# do something with temp
else:
temp = my_re4.match(ex p)
OMG.

actions = [
(my_re1, do_something_wi th_temp1),
(my_re2, do_something_wi th_temp2),
(my_re3, do_something_wi th_temp3),
(my_re4, do_something_wi th_temp4),
]

for my_re, do_something_wi th in actions:
temp = my_re.match(exp ):
if temp:
do_something_wi th(temp)
break

Having full-blown anonymous functions or Ruby/Smalltalk-like code blocks
would be much more interesting IMHO.
Apr 5 '07 #10

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

23
3220
by: Paul Rubin | last post by:
OK, I want to scan a file for lines matching a certain regexp. I'd like to use an assignment expression, like for line in file: if (g := re.match(pat, line)): croggle(g.group(1)) Since there are no assignment expressions in Python, I have to use a temp var. That's a little more messy, but bearable:
24
1617
by: boblatest | last post by:
Hello, I have an if-elif chain in which I'd like to match a string against several regular expressions. Also I'd like to use the match groups within the respective elif... block. The C-like idiom that I would like to use is this: if (match = my_re1.match(line): # use match elsif (match = my_re2.match(line)):
0
8407
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
0
8739
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
0
8612
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
0
7347
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
1
6175
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
5638
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
1
2739
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
2
1969
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
2
1732
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.