This idea was proposed to me at the core sprints last month by Larry
Hastings. I've discussed it with a few people, who seem generally
positive about it, and we've tweaked it a little bit. I've spent some
time implementing it, and I think it's doable. I thought I'd post it
here for any additional feedback.
Here’s the idea: for f-strings, we add a !d conversion operator, which
is superficially similar to !s, !r, and !a. The meaning of !d is:
produce the text of the expression (not its value!), followed by an
equal sign, followed by the repr of the value of the expression. So:
value = 10
s = 'a string!'
print(f'{value!d}')
print(f'next: {value+1!d}')
print(f'{s!d}')
produces:
value=10
next: value+1=11
s='a string!'
I’m not proposing this for str.format(). It would only really make sense
for named arguments, and I don’t think
print('{value!d}'.format(value=value) is much of a win.
The result is a string, so if you really wanted to, you could use a
string formatting spec. So:
print(f'*{value!d:^20}*'
would produce:
* value=10 *
Although I don’t think that would be very useful in general.
The mnemonic is !d for “debugging”. I’d wanted to use !=, because
there’s an equal sign involved in the result, but = is the one character
that can’t be used after ! (it’s “not equal” in expressions, and
f-strings look specifically for that case). I also mentioned !!, but I
think I prefer !d as being less confusing.
This would be used in debugging print statements, that currently end up
looking like:
print(f'value={value!r}')
and would now be:
print(f'{value!d}')
There have been discussions about ways to specify str() vs. repr(),
using characters other than '=', adding spaces, etc. But they all end up
over-complicating what should be a simple tool, not a Swiss Army knife.
Thoughts?
Eric
I'd like to suggest what I think would be a simple addition to `def` and
`class` blocks. I don't know if calling those "Assignment Blocks" is
accurate, but I just mean to refer to block syntaxes that assign to a name.
Anyway, I propose a combined return-def structure, and optionally also
allowing a return-class version. Omitting the name would be allowable, as
well.
This would only apply to a `def` or `class` statement made as the last part
of the function body, of course.
def ignore_exc(exc_type):
return def (func):
@wraps(func)
return def (*args, **kwargs):
try:
return func(*args, **kwargs)
except exc_type:
pass
Thanks for considering and for any comments, thoughts, or feedback on the
idea!
Dear all,
Who might also be interested in setting up a project that supports localization for Unicode block description and character description.
Translations are available from https://github.com/unicode-table/unicode-table-data/tree/master/loc
<https://github.com/unicode-table/unicode-table-data/tree/master/loc> If possible, use a gettext approach similar to https://pypi.org/project/pycountry/ <https://pypi.org/project/pycountry/>
Implementing this feature will allow users to read Unicode descriptions in their own language, other than English.
For example, now is possible only in English:
from unicodedata import name
print(name('ß'))
LATIN SMALL LETTER SHARP S
So unicodedata could provide a way to translate LATIN SMALL LETTER SHARP S to e.g. German with:
from unicodedata import name
from unicodedata_l10n import LOCALED_DIR
from gettext import translation
german = translation('UnicodeData' LOCALED_DIR, languages=['de'])
german.install()
print(_(name('ß')))
LATEINISCHER KLEINBUCHSTABE SCHARFES S
and something similar for unicodedata.category
Best,
Pander
Hello,
During the last 10 years, Python has made steady progress in convenience to
assemble strings. However, it seems to me that joining is still, when
possible, the cleanest way to code string assembly.
However, I'm still sometimes confused between the different syntaxes used
by join methods:
0. os.path.join takes *args
1. str.join takes a list argument, this inconsistence make it easy to
mistake with the os.path.join signature
Also, I still think that:
'_'.join(['cancel', name])
Would be more readable as such:
['cancel', name].join('_')
Not only this would fix both of my issues with the current status-quo, but
this would also be completely backward compatible, and probably not very
hard to implement: just add a join method to list.
Thanks in advance for your reply
Have a great day
--
∞
Hey List,
this is my very first approach to suggest a Python improvement I'd think
worth discussing.
At some point, maybe with Dart 2.0 or a little earlier, Dart is now
supporting multiline strings with "proper" identation (tried, but I can't
find the according docs at the moment. probably due to the rather large
changes related to dart 2.0 and outdated docs.)
What I have in mind is probably best described with an Example:
print("""
I am a
multiline
String.
""")
the closing quote defines the "margin indentation" - so in this example all
lines would get reduces by their leading 4 spaces, resulting in a "clean"
and unintended string.
anyways, if dart or not, doesn't matter - I like the Idea and I think
python3.x could benefit from it. If that's possible at all :)
I could also imagine that this "indentation cleanup" only is applied if the
last quotes are on their own line? Might be too complicated though, I can't
estimated or understand this...
thx for reading,
Marius
I keep coming back to this great video <https://vimeo.com/74316116> about
coding style, and one point in particular rings true to me:
ALL_CAPS_IS_OBNOXIOUS
It destroys the visual flow of code and for what? To signify a global,
constant, or Enum? Is that really so important? I don't think so. I think
the all caps style has out-lived its usefulness and needs to go the way of
the dodo.
The last time I saw all caps used appropriately was in a YouTube comment
where some guy was ranting about the communist Jewish banker conspiracy to
control the world. In that case, all caps clearly communicated to me that
the person was a frothing lunatic (thought find the idea of communist
bankers intriguing).
Currently PEP-8 prescribes all caps for constants
<https://www.python.org/dev/peps/pep-0008/#constants> and uses the all cap
variable "FILES" as an example in a different section.
<https://www.python.org/dev/peps/pep-0008/#when-to-use-trailing-commas> It
also appears to be the defacto-standard for enums (based on the
documentation <https://docs.python.org/3/library/enum.html#creating-an-enum>
)
I don't think it's necessary to make any breaking changes. Just pep-8 and
(of less importance) spurious documentation examples.
I've found that almost any time I'm writing a 'with' block, it's doing
something that could throw an exception. As a result, each of those
'with' blocks needs to be nested within a 'try' block. Due to the
nature of 'with', it is rarely (if ever) the case that the try block
contains anything other than the with block itself.
As a result, I would like to propose that the syntax for 'with' blocks
be changed such that they can be accompanied by 'except', 'finally',
and/or 'else' blocks as per a standard 'try' block. These would handle
exceptions that occur in the 'with' block, including the execution of
the applicable __enter__ and __exit__ methods.
Example:
try:
with open(path) as myfile:
... # Do stuff with file
except (OSError, IOError) as err:
logger.error("Failed to read/open file {}: {}".format(path, err)
The above would turn into simply:
with open(path) as myfile:
... # Do stuff with file
except (OSError, IOError) as err:
logger.error(...)
I think this is rather straightforward in meaning and easy to read,
and simplifies some unnecessary nesting. I see this as the natural
evolution of what 'with'
is all about - replacing necessary try-finally blocks with something
more elegant. We just didn't include the 'except' portion.
I'm a bit hesitant to put this out there. I'm not worried about it
getting shot down - that's kind of the point here. I'm just pretty
strongly against to unnecessary syntactical additions to the language.
This though, I think I can except. It introduces no new concepts and
requires no special knowledge to use. There's no question about what
is going on when you read it.
--
Paul Ferrell
pflarr(a)gmail.com
This thought is motivated by this bug report:
https://bugs.python.org/issue35857
If you import a module, then edit the .py file that goes with it, and
then an exception occurs, the stack trace can show the wrong line.
It doesn't happen very often, but when it does happen, it can be very
perplexing. Here's a proposal:
When a stack trace is printed, before printing each line, the
interpreter checks whether the file's modification time is later than
the time recorded in the .pyc file. If the times are different, the
stack trace can flag the line and print an addition line stating that
the file may have changed and the stack trace may not be accurate.
Something like this perhaps?
Traceback (most recent call last):
File "spam.py", line 99, in <spam>
eggs.foo()
File "eggs.py", line 123, in <eggs>
? for obj in sequence:
File "cheese.py", line 456, in <cheese>
n = len(x)
*** one or more files may have changed
*** lines starting with ? may be inaccurate
TypeError: object of type 'NoneType' has no len()
I don't think performance will matter. Generating stack traces are
rarely performance critical, so I don't think that a few extra file
system checks will make any meaningful difference.
Thoughts?
--
Steve
I know this is going to get rejected, but I want to speak out the idea
nevertheless:
I love kwargs and named arguments from the beginning (roughly 18 years now)
I guess you came across this several times before:
In the first version of the API one variable gets returned:
Example:
status = backend.transmit_data()
But later you want to add something to the API.
For the input part of a method this is solved. You
can add an optional kwarg.
But for the output part of a method, there you can't change
the interface easily up to now.
Use case: you want to add an optional list of messages which
could get returned.
You want to change to
status, messages = backend.transmit_data()
If you have 10 different backend implementations,
then you need to change all of them.
This is difficult, if the backends reside in different
repos and maybe you even don't own some of these repos.
Current draw-back: you need to change all of them at once.
Of course you could work around it be using this
status_messages = backend.transmit_data()
And then do some fancy guessing if the variable contains
only the status or a tuple containing status and messages.
Some days ago I head the idea that kwargs for return would
help here.
This should handle both cases:
Case1: The old backend returns only the status, and the caller
wants both status and messages. Somehow the default
for messages needs to be defined. In my case it would
be the empty list.
Case2: The new backends returning the status
and messages. The old caller just gets the
status. The messages get discarded.
Above is the use case.
How could kwargs for return look like?
Maybe like this:
.....
Sorry, I could not find a nice, clean and simple syntax
for this up to now.
Maybe someone else is more creative than I am.
What do you think about this?
Regards,
Thomas Güttler
--
Thomas Guettler http://www.thomas-guettler.de/
I am looking for feedback: https://github.com/guettli/programming-guidelines
Hello,
I'd like to discuss an idea I had to shorten the syntax for the common case of having a try/except/finally/else block where all of the following conditions are met:
* There is only one except block, no finally or else
* The exception is not captured in the except block, i.e. `except KeyError:` not `except KeyError as e:`
* The contents of the except block is only a single expression
* Perhaps, the expression starts with a control word such as pass, break, continue, return, raise. As it happens, everything useful I can think to do with this right now currently uses these. Unclear to me if this should be a requirement.
The syntax I envisioned would be something like the following:
try on ValueError pass:
��� some_list.remove('value')
I'm not at all attached to the `on` token specifically, but I think something is necessary there.
Other examples:
def func():
��� try on KeyError, ValueError return False:
������� dict_of_lists['key'].remove('value')
key = 'foo'
try on KeyError raise MyApplicationError(f'{key} not found'):
��� a_dict[key]
for i in range(100):
��� try on TypeError continue:
������� a_list[i] += 1
������� etc()
I realize this could be accomplished with context managers, but that seems like overkill to simply throw away the exception, and would increase the overall required code length.
Thanks for your input!
Alex