For rapidly changing business rules, I'm storing IronPython fragments in XML files. So far this has been working out well, but I'm starting to get to the point where I need more that just one-line expressions.
The problem is that XML and significant whilespace don't play well together. Before I abandon it for another language, I would like to know if IronPython has an alternative syntax.
IronPython doesn't have an alternate syntax. It's an implementation of Python, and Python uses significant indentation (all languages use significant whitespace, not sure why we talk about whitespace when it's only indentation that's unusual in the Python case).
>>> from __future__ import braces
File "<stdin>", line 1
from __future__ import braces
^
SyntaxError: not a chance
All I want is something that will let my users write code like
Ummm... Don't do this. You don't actually want this. In the long run, this will cause endless little issues because you're trying to force too much content into an attribute.
Do this.
<Rule Name="Markup">
<Formula>(Account.PricingLevel + 1) * .05</Formula>
</Rule>
You should try not to have significant, meaningful stuff in attributes. As a general XML design policy, you should use tags and save attributes for names and ID's and the like. When you look at well-done XSD's and DTD's, you see that attributes are used minimally.
Having the body of the rule in a separate tag (not an attribute) saves much pain. And it allows a tool to provide correct CDATA sections. Use a tool like Altova's XML Spy to assure that your tags have space preserved properly.
I think you can set the xml:space="preserve" attribute or use a <![CDATA[ to avoid other issues, with for example quotes and greater equal signs.
Apart from the already mentioned CDATA sections, there's pindent.py which can, among others, fix broken indentation based on comments a la #end if - to quote the linked file:
When called as "pindent -r" it assumes its input is a Python program with block-closing comments but with its indentation messed up, and outputs a properly indented version.
...
A "block-closing comment" is a comment of the form '# end <keyword>' where is the keyword that opened the block. If the opening keyword is 'def' or 'class', the function or class name may be repeated in the block-closing comment as well. Here is an example of a program fully augmented with block-closing comments:
def foobar(a, b):
if a == b:
a = a+1
elif a < b:
b = b-1
if b > a: a = a-1
# end if
else:
print 'oops!'
# end if
# end def foobar
It's bundeled with CPython, but if IronPython doesn't have it, just grab it from the repository.
Related
I am writing a lexer + parser in JFlex + CUP, and I wanted to have Python-like syntax regarding blocks; that is, indentation marks the block level.
I am unsure of how to tackle this, and whether it should be done at the lexical or sintax level.
My current approach is to solve the issue at the lexical level - newlines are parsed as instruction separators, and when one is processed I move the lexer to a special state which checks how many characters are in front of the new line and remembers in which column the last line started, and accordingly introduces and open block or close block character.
However, I am running into all sort of trouble. For example:
JFlex cannot match empty strings, so my instructions need to have at least one blanck after every newline.
I cannot close two blocks at the same time with this approach.
Is my approach correct? Should I be doing things different?
Your approach of handling indents in the lexer rather than the parser is correct. Well, it’s doable either way, but this is usually the easier way, and it’s the way Python itself (or at least CPython and PyPy) does it.
I don’t know much about JFlex, and you haven’t given us any code to work with, but I can explain in general terms.
For your first problem, you're already putting the lexer into a special state after the newline, so that "grab 0 or more spaces" should be doable by escaping from the normal flow of things and just running a regex against the line.
For your second problem, the simplest solution (and the one Python uses) is to keep a stack of indents. I'll demonstrate something a bit simpler than what Python does.
First:
indents = [0]
After each newline, grab a run of 0 or more spaces as spaces. Then:
if len(spaces) == indents[-1]:
pass
elif len(spaces) > indents[-1]:
indents.append(len(spaces))
emit(INDENT_TOKEN)
else:
while len(spaces) != indents[-1]:
indents.pop()
emit(DEDENT_TOKEN)
Now your parser just sees INDENT_TOKEN and DEDENT_TOKEN, which are no different from, say, OPEN_BRACE_TOKEN and CLOSE_BRACE_TOKEN in a C-like language.
Of you’d want better error handling—raise some kind of tokenizer error rather than an implicit IndexError, maybe use < instead of != so you can detect that you’ve gone too far instead of exhausting the stack (for better error recovery if you want to continue to emit further errors instead of bailing at the first one), etc.
For real-life example code (with error handling, and tabs as well as spaces, and backslash newline escaping, and handling non-syntactic indentation inside of parenthesized expressions, etc.), see the tokenize docs and source in the stdlib.
What is the purpose of the colon before a block in Python?
Example:
if n == 0:
print "The end"
The colon is there to declare the start of an indented block.
Technically, it's not necessary; you could just indent and de-indent when the block is done. However, based on the Python koan “explicit is better than implicit” (EIBTI), I believe that Guido deliberately made the colon obligatory, so any statement that should be followed by indented code ends in a colon. (It also allows one-liners if you continue after the colon, but this style is not in wide use.)
It also makes the work of syntax-aware auto-indenting editors easier, which also counted in the decision.
This question turns out to be a Python FAQ, and I found one of its answers by Guido here:
Why are colons required for the if/while/def/class statements?
The colon is required primarily to enhance readability (one of the results of the experimental ABC language). Consider this:
if a == b
print a
versus
if a == b:
print a
Notice how the second one is slightly easier to read. Notice further how a colon sets off the example in this FAQ answer; it’s a standard usage in English.
Another minor reason is that the colon makes it easier for editors with syntax highlighting; they can look for colons to decide when indentation needs to be increased instead of having to do a more elaborate parsing of the program text.
Consider the following list of things to buy from the grocery store, written in Pewprikanese.
pewkah
lalala
chunkykachoo
pewpewpew
skunkybacon
When I read that, I'm confused, Are chunkykachoo and pewpewpew a kind of lalala? Or what if chunkykachoo and pewpewpew are indented just because they are special items?
Now see what happens when my Pewprikanese friend add a colon to help me parse the list better: (<-- like this)
pewkah
lalala: (<-- see this colon)
chunkykachoo
pewpewpew
skunkybacon
Now it's clear that chunkykachoo and pewpewpew are a kind of lalala.
Let's say there is a person who's starting to learn Python, which happens to be her first programming language to learn. Without colons, there's a considerable probability that she's going to keep thinking "this lines are indented because this lines are like special items.", and it could take a while to realize that that's not the best way to think about indentation.
Three reasons:
To increase readability. The colon helps the code flow into the following indented block.
To help text editors/IDEs, they can automatically indent the next line if the previous line ended with a colon.
To make parsing by python slightly easier.
As far as I know, it's an intentional design to make it more obvious, that the reader should expect an indentation after the colon.
It also makes constructs like this possible:
if expression: action()
code_continues()
since having the code for the if immediately following the colon makes it possible for the compiler to understand that the next line should not be indented.
According to Guido Van Rossum, the Python inventor, the idea of using a colon to make the structure more apparent is inspired by earlier experiments with a Python predecessor, ABC language, which also targeted the beginners. Apparently, on their early tests, beginner learners progressed faster with colon than without it. Read the whole story at Guido's post python history blog.
http://python-history.blogspot.com/2009/02/early-language-design-and-development.html
And yes, the colon is useful in one-liners and is less annoying than the semicolon. Also style guide for long time recommended break on several lines only when it ends with a binary operator
x = (23 +
24 +
33)
Addition of colon made compound statement look the same way for greater style uniformity.
There is a 'colonless' encoding for CPython as well as colon-less dialect, called cobra. Those did not pick up.
Is there a method of ending single line comments in Python?
Something like
/* This is my comment */ some more code here...
No, there are no inline comments in Python.
From the documentation:
A comment starts with a hash character (#) that is not part of a
string literal, and ends at the end of the physical line. A comment
signifies the end of the logical line unless the implicit line joining
rules are invoked. Comments are ignored by the syntax; they are not
tokens.
Whitespace in Python is too important to allow any other kind of comment besides the # comment that goes to the end of the line. Take this code:
x = 1
for i in range(10):
x = x + 1
/* Print. */ print x
Because indentation determines scope, the parser has no good way of knowing the control flow. It can't reasonably eliminate the comment and then execute the code after it. (It also makes the code less readable for humans.) So no inline comments.
You can insert inline comment.
Like this
x=1; """ Comment """; x+=1; print(x);
And my python version is "3.6.9"
No, there are no inline-block comments in Python.
But you can place your comment (inline) on the right.
That's allows you to use syntax and comments on the same line.
Anyway, making comments to the left of your code turn reading difficult, so...
Ex:
x = 1 # My variable
This is pretty hideous, but you can take any text convert it into a string and then take then length of that string then multiply by zero, or turn it into any kind of invalid code.
example
history = model.fit_generator(train_generator,steps_per_epoch=8,epochs=15+0*len(", validation_data=validation_generator"), validation_steps=8,verbose=2)
I miss inline-comments mainly to temporarily comment out parameters in functions or elements in list/dicts. Like it is possible in other languages:
afunc(x, /*log=True*/, whatever=True)
alist = [1,2,3]
The only workaround, i guess, is to but them on separate lines like:
afunc(
x,
# log=True,
whatever=True,
)
alist = [
1,
# 2,
3,
]
However, as python is often used as rapid prototyping language and functions (due to no overloading) often have lots of optional parameters, this solution does not fell very "pythonic"...
Update
I meanwhile really like the "workaround" and changed my opinion about being not pythonic. Also, some formatters like Black will automatically arrange arguments or elements of an array/dict on seperate lines if you add a comment at the end. This is called Magic Trailing Comma
If you're doing something like a sed operation on code and really need to insert plain text without interfering with the rest of the line, you can try something like:
("This is my comment", some more code here...)[1]
Eg.,
my_variable = obsolete_thing + 100
could be transformed with sed -e 's/obsolete_thing/("replacement for &", 1345)[1]/' giving:
my_variable = ("replacement for obsolete_thing", 1234)[1] + 100
The octaves of a Piano are numbered and note frequencies known
(see wikipedia).
I wanted to inline comment the notes in a list of frequencies
while maintaining standard Human readable sequencing of notes.
Here is how I did it; showing a couple of octaves.
def A(octave, frequency):
"Octave numbering for twelve-tone equal temperament"
return frequency
NOTE=[
155.5635 , 164.8138, 174.6141, 184.9972, 195.9977, 207.6523,
A(3,220.0000), 233.0819, 246.9417, 261.6256, 277.1826, 293.6648,
311.1270 , 329.6276, 349.2282, 369.9944, 391.9954, 415.3047,
A(4,440.0000), 466.1638, 493.8833, 523.2511, 554.3653, 587.3295]
Of course, adjust setup.cfg and comment to satisfy pycodestyle,
pyflakes, and pylint.
I argue that maintaining columns and annotating A4 as A(4,440)
is superior to enforcing rigid style rules.
A function ignoring a formal argument is run once
at list initialization.
This is not a significant cost.
Inline commenting is possible in python.
You just have to be willing to bend style rules.
What is the purpose of the colon before a block in Python?
Example:
if n == 0:
print "The end"
The colon is there to declare the start of an indented block.
Technically, it's not necessary; you could just indent and de-indent when the block is done. However, based on the Python koan “explicit is better than implicit” (EIBTI), I believe that Guido deliberately made the colon obligatory, so any statement that should be followed by indented code ends in a colon. (It also allows one-liners if you continue after the colon, but this style is not in wide use.)
It also makes the work of syntax-aware auto-indenting editors easier, which also counted in the decision.
This question turns out to be a Python FAQ, and I found one of its answers by Guido here:
Why are colons required for the if/while/def/class statements?
The colon is required primarily to enhance readability (one of the results of the experimental ABC language). Consider this:
if a == b
print a
versus
if a == b:
print a
Notice how the second one is slightly easier to read. Notice further how a colon sets off the example in this FAQ answer; it’s a standard usage in English.
Another minor reason is that the colon makes it easier for editors with syntax highlighting; they can look for colons to decide when indentation needs to be increased instead of having to do a more elaborate parsing of the program text.
Consider the following list of things to buy from the grocery store, written in Pewprikanese.
pewkah
lalala
chunkykachoo
pewpewpew
skunkybacon
When I read that, I'm confused, Are chunkykachoo and pewpewpew a kind of lalala? Or what if chunkykachoo and pewpewpew are indented just because they are special items?
Now see what happens when my Pewprikanese friend add a colon to help me parse the list better: (<-- like this)
pewkah
lalala: (<-- see this colon)
chunkykachoo
pewpewpew
skunkybacon
Now it's clear that chunkykachoo and pewpewpew are a kind of lalala.
Let's say there is a person who's starting to learn Python, which happens to be her first programming language to learn. Without colons, there's a considerable probability that she's going to keep thinking "this lines are indented because this lines are like special items.", and it could take a while to realize that that's not the best way to think about indentation.
Three reasons:
To increase readability. The colon helps the code flow into the following indented block.
To help text editors/IDEs, they can automatically indent the next line if the previous line ended with a colon.
To make parsing by python slightly easier.
As far as I know, it's an intentional design to make it more obvious, that the reader should expect an indentation after the colon.
It also makes constructs like this possible:
if expression: action()
code_continues()
since having the code for the if immediately following the colon makes it possible for the compiler to understand that the next line should not be indented.
According to Guido Van Rossum, the Python inventor, the idea of using a colon to make the structure more apparent is inspired by earlier experiments with a Python predecessor, ABC language, which also targeted the beginners. Apparently, on their early tests, beginner learners progressed faster with colon than without it. Read the whole story at Guido's post python history blog.
http://python-history.blogspot.com/2009/02/early-language-design-and-development.html
And yes, the colon is useful in one-liners and is less annoying than the semicolon. Also style guide for long time recommended break on several lines only when it ends with a binary operator
x = (23 +
24 +
33)
Addition of colon made compound statement look the same way for greater style uniformity.
There is a 'colonless' encoding for CPython as well as colon-less dialect, called cobra. Those did not pick up.
Am I correct in thinking that that Python doesn't have a direct equivalent for Perl's __END__?
print "Perl...\n";
__END__
End of code. I can put anything I want here.
One thought that occurred to me was to use a triple-quoted string. Is there a better way to achieve this in Python?
print "Python..."
"""
End of code. I can put anything I want here.
"""
The __END__ block in perl dates from a time when programmers had to work with data from the outside world and liked to keep examples of it in the program itself.
Hard to imagine I know.
It was useful for example if you had a moving target like a hardware log file with mutating messages due to firmware updates where you wanted to compare old and new versions of the line or keep notes not strictly related to the programs operations ("Code seems slow on day x of month every month") or as mentioned above a reference set of data to run the program against. Telcos are an example of an industry where this was a frequent requirement.
Lastly Python's cult like restrictiveness seems to have a real and tiresome effect on the mindset of its advocates, if your only response to a question is "Why would you want to that when you could do X?" when X is not as useful please keep quiet++.
The triple-quote form you suggested will still create a python string, whereas Perl's parser simply ignores anything after __END__. You can't write:
"""
I can put anything in here...
Anything!
"""
import os
os.system("rm -rf /")
Comments are more suitable in my opinion.
#__END__
#Whatever I write here will be ignored
#Woohoo !
What you're asking for does not exist.
Proof: http://www.mail-archive.com/python-list#python.org/msg156396.html
A simple solution is to escape any " as \" and do a normal multi line string -- see official docs: http://docs.python.org/tutorial/introduction.html#strings
( Also, atexit doesn't work: http://www.mail-archive.com/python-list#python.org/msg156364.html )
Hm, what about sys.exit(0) ? (assuming you do import sys above it, of course)
As to why it would useful, sometimes I sit down to do a substantial rewrite of something and want to mark my "good up to this point" place.
By using sys.exit(0) in a temporary manner, I know nothing below that point will get executed, therefore if there's a problem (e.g., server error) I know it had to be above that point.
I like it slightly better than commenting out the rest of the file, just because there are more chances to make a mistake and uncomment something (stray key press at beginning of line), and also because it seems better to insert 1 line (which will later be removed), than to modify X-many lines which will then have to be un-modified later.
But yeah, this is splitting hairs; commenting works great too... assuming your editor supports easily commenting out a region, of course; if not, sys.exit(0) all the way!
I use __END__ all the time for multiples of the reasons given. I've been doing it for so long now that I put it (usually preceded by an exit('0');), along with BEGIN {} / END{} routines, in by force-of-habit. It is a shame that Python doesn't have an equivalent, but I just comment-out the lines at the bottom: extraneous, but that's about what you get with one way to rule them all languages.
Python does not have a direct equivalent to this.
Why do you want it? It doesn't sound like a really great thing to have when there are more consistent ways like putting the text at the end as comments (that's how we include arbitrary text in Python source files. Triple quoted strings are for making multi-line strings, not for non-code-related text.)
Your editor should be able to make using many lines of comments easy for you.