PyCharm has a nice feature that lints the following code
if (a == b):
# ...
with "Remove redundant parentheses" concerning the (a == b) expression.
Running flake8 on the same code doesn't complain about anything by default. Is it possible to configure flake8 in a way to detect unnecessary parentheses?
I have found this list of flake8 rules, but on first glance I cannot find a setting that might be related. If it is not possible with flake8, what does PyCharm use to perform this check?
Sadly, this check is not built into flake8. But due to its flexible plugin system, it's not hard to add a plugin that performs said check.
Since I couldn't find any plugin that does the job, I went ahead and, together with other people, created a plugin for flake8 that serves this exact purpose.
https://pypi.org/project/flake8-picky-parentheses
The used method is inspired by SebDieBln's comment:
To figure out whether a pair of parentheses is redundant, try removing it and parsing the new code. If the parsing fails, they were necessary. If not, compare the ASTs of the original and the altered code. If they are the same, the code is semantically equivalent and the parentheses are redundant. On top of that, add some (maybe opinionated) exceptions where redundant parentheses help readability (e.g., a = (1, 2) or a = 1 + (n % 2)) and that's it.
Is switching to Pylint an option? The reason is that this rule:
superfluous-parens (C0325):
Unnecessary parens after %r keyword Used when a single item in parentheses follows an if, for, or other keyword.
would address your issue.
Also, found this extension for Flake8:
https://gist.github.com/snoack/e78963516d93e55add32fc1f8237b0e4
Hope this helps, otherwise, don't mind me.
Related
In other languages, like Java, you can do something like this:
String path;
if (exists(path = "/some/path"))
my_path = path;
the point being that path is being set as part of specifying a parameter to a method call. I know that this doesn't work in Python. It is something that I've always wished Python had.
Is there any way to accomplish this in Python? What I mean here by "accomplish" is to be able to write both the call to exists and the assignment to path, as a single statement with no prior supporting code being necessary.
I'll be OK with it if a way of doing this requires the use of an additional call to a function or method, including anything I might write myself. I spent a little time trying to come up with such a module, but failed to come up with anything that was less ugly than just doing the assignment before calling the function.
UPDATE: #BrokenBenchmark's answer is perfect if one can assume Python 3.8 or better. Unfortunately, I can't yet do that, so I'm still searching for a solution to this problem that will work with Python 3.7 and earlier.
Yes, you can use the walrus operator if you're using Python 3.8 or above:
import os
if os.path.isdir((path := "/some/path")):
my_path = path
I've come up with something that has some issues, but does technically get me where I was looking to be. Maybe someone else will have ideas for improving this to make it fully cool. Here's what I have:
# In a utility module somewhere
def v(varname, arg=None):
if arg is not None:
if not hasattr(v, 'vals'):
v.vals = {}
v.vals[varname] = arg
return v.vals[varname]
# At point of use
if os.path.exists(v('path1', os.path.expanduser('~/.harmony/mnt/fetch_devqa'))):
fetch_devqa_path = v('path1')
As you can see, this fits my requirement of no extra lines of code. The "variable" involved, path1 in this example, is stored on the function that implements all of this, on a per-variable-name basis.
One can question if this is concise and readable enough to be worth the bother. For me, the verdict is still out. If not for the need to call the v() function a second time, I think I'd be good with it structurally.
The only functional problem I see with this is that it isn't thread-safe. Two copies of the code could run concurrently and run into a race condition between the two calls to v(). The same problem is greatly magnified if one fails to choose unique variable names every time this is used. That's probably the deal killer here.
Can anyone see how to use this to get to a similar solution without the drawbacks?
Why is this a valid statement in Python?
"Guido"
This tripped me up with a multi-line string where I did not properly use parens:
# BAD
message = "Guido"
" van Rossum"
# GOOD
message = ("Guido"
" van Rossum")
Is it purely for the repl or is there some other reasoning for it?
Expressions are statements in Python (and most other imperative languages) for several good reasons:
What if a function, like foo() does something useful but also returns a value? foo() would be an invalid statement if the language didn't allow us to implicitly discard the return value.
Docstrings! They are just strings that happen to be the first statement of a module/class/function, so no special syntax was needed to support them.
In general, it's hard for the interpreter to determine whether an expression might have side effects. So it's been designed to not even try; it simply evaluates the expression, even if it's a simple constant, and discards the result.
To check for such mistakes as you mentioned, and many others, pylint can be helpful. It has a specific warning for this very case. However, it seems to not catch the mistake in your exact example code (using PyLint version 2.4.4); might be a bug.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Is it possible to implement a Python for range loop without an iterator variable?
just want to do something multiple times so I write
for i in range(1, 10):
print 'something'
print 'do not use i'
so when I run PyLint it says : "Unused variable 'i'" of course.
So what would be correct way to write this type of loop where I just want to loop multiple times.
i = 0
while i < 10:
print 'test'
i += 1
is this only way?
While you could substitute i with _, writing the loop as you have in the first place is perfectly fine, and writing it any other way would probably be considered strange to most Python programmers.
PyLint is checking too aggressively, and sometimes it should be ignored. Perhaps consider pyflakes if what you want is a checker that tells you if your code is likely to break; or pep8 if you want your style checked (variable naming etc).
The for i in range(..) loop (use xrange() in python2 though) is the correct way to loop over a range of numbers in python. The pylint warning should be ignored in this case. However, in case of an unused variable it's often named _ to make it clearer that it's not used.
While there are other ways to loop those are less efficient since they usually involve function calls. Besides that doing so would just not be what people expect to see when reading your code.
The version of PyLint I'm using right now oddly enough doesn't seem to cry about unused variables in this particular example. Be that as it may, there are several options:
Work with the iterator directly:
i = iter(range(1, 10))
try:
while i.next():
pass
except StopIteration:
pass # safely ignore
Add a PyLint comment at the top of your file to disable the warning:
# pylint: disable=X0123
# NOTE: X0123 is just an example, I don't know the exact warning code
Potentially append an _ to the unused variable. I'm not sure whether or not this naming convention is respected, but it is mentioned in the official user manual:
In our project we just accepted that we have to make some modifications in our code to please PyLint:
stick to more naming conventions (unused variables ending in underscores, ...)
So I have understood what exec and eval and also compile do. But why would I need to use them? I am being unclear on the usage scenario.
Can anyone give me some examples so that I can better appreciate the concept. Cause right I know it is all theory.
I'll give an example in which I have used eval and where I think it was the best choice.
I was writing a simple software testing utility ... something to test whether student exercises were conforming to the assignment requirements. The goal was to provide a way for a simple configuration file to serve as a test specification (to get around a "chicken-and-egg" issue of using a programming language to describe/document/implement the test cases for elementary programming assignments).
I based my harness on the ConfigParser in the standard libraries. However, I did want the ability to represent arbitrary Python strings (including interpolations of \n, \t, and especially any interpolated hex encoded ASCII characters in the values read therefrom.
My solution was a try around an parsed_string=eval('''%s''' % cfg_read_item) followed by a try of the triple double-quoted version ("""%s""") of the same.
This is a case where the alternative would have been to write (or find a pre-written) Python language parser and figure out how to include and adapt it to my program. The risks are minimal (I'm not worried that student submitted code is going to trick my parser, break out if its jail, delete all my files, send my credit card numbers to Romania and so on)*
*(In part because I was testing them under Linux from an untrusted headless user account).
As here others have said, there are other use cases where you're building code from a template based on input data and need to execute that code (meta programming). You should always be able to accomplish those tasks in another way. However, whenever that alternative entails coding effort that approaches writing a general programming language parser/compiler/interpreter .... then eval may be the better approach.
The standard library has an instructive example of how to use exec. collections.namedtuple uses it to build a class dynamically.
template = '''class %(typename)s(tuple):
'%(typename)s(%(argtxt)s)' \n
__slots__ = () \n
_fields = %(field_names)r \n
def __new__(_cls, %(argtxt)s):
'Create new instance of %(typename)s(%(argtxt)s)'
return _tuple.__new__(_cls, (%(argtxt)s)) \n
...'''
namespace = dict(_itemgetter=_itemgetter, __name__='namedtuple_%s' % typename,
OrderedDict=OrderedDict, _property=property, _tuple=tuple)
try:
exec template in namespace
except SyntaxError, e:
raise SyntaxError(e.message + ':\n' + template)
ast uses compile to generate abstract syntax trees from Python source code. These are used by modules such as pyflakes to parse and validate Python.
def parse(expr, filename='<unknown>', mode='exec'):
"""
Parse an expression into an AST node.
Equivalent to compile(expr, filename, mode, PyCF_ONLY_AST).
"""
return compile(expr, filename, mode, PyCF_ONLY_AST)
You don't need to use them, and in my opinion you should avoid them.
They are only useful in cases where you are generating the code itself, which in the end is going to most likely be considered bad practice.
If you are considering using eval() for things like mathematical expressions, you would be better sanitizing the input before evaluating it. You never know what kind of 'text' the user sends in that might screw up the application itself.
I think I have a valid use. I am using Python 3.2.1 inside Blender 2.6.4 to modify a set of points with x,y coordinates (in the z-plane).
The goal is to add concentric rings of new points around each existing point, with the rings behaving as ripples, (like when you drop a stone in a pond). The catch is that I want the ripples to constructively/destructively interfere with one another, so first I'm going through and constructing a 'ripple equation' centered at each point, and summing all the ripple equations together into one gigantic mathematical equation, which I will then feed the original points into in order to generate the correct z-value to assign each one to.
My plan is to append each additional term in the equation to the previous as a string, and then use eval() to calculate the z-value for the new set of points.
Are you just asking for an example? You could write a simple app that reads from standard in and allows the user to input various expressions, like (4*2)/8 - 1. In other languages (Java, C++, etc.) this would be close to impossible to evaluate, but in python it is simple, just:
eval((4*2)/8 - 1)
That being said, unless you are careful, using these things can be very dangerous as they (essentially)allow the user a huge amount of access.
This is used in meta-programming (when the program writes itself). For example, you have animals of different species, which are described with different classes: Lion, Tiger, Horse, Donkey. And you want to simulate crossbreeding between them, for exampe, between Lion and Tiger. When you write the program, you can not determine how the user will cross the animals, but you can create new classes of animals on the fly:
new_class_name = boy.class.to_str() + girl.class.to_str()
eval("class " + new_class_name + " extends " + boy.class.to_str() + ", " + girl.class.to_str())
P. S. Sorry, I forgot Python some. So there is a bunch of pseudo-code.
Here's a valid use case. In the python paste middleware (for web programming) when an exception is raised it creates a command line within the browser. This works be using methods like these. Also, in Blender there is an option to animate values using python expressions and this works using eval.
Regarding the "standard" way to put comments inside Python source code:
def func():
"Func doc"
... <code>
'TODO: fix this'
#badFunc()
... <more code>
def func():
"Func doc"
... <code>
#TODO: fix this
#badFunc()
... <more code>
I prefer to write general comments as strings instead of prefixing #'s.
The official Python style guide doesn't mention using strings as comments (If I didn't miss it while reading it).
I like it that way mainly because I think the # character looks ugly with comment blocks. As far as I know these strings don't do anything.
Are there disadvantages in doing this?
Don't misuse strings (no-op statements) as comments. Docstrings, e.g. the first string in a module, class or function, are special and definitely recommended.
Note that docstrings are documentation, and documentation and comments are two different things!
Documentation is important to understand what the code does.
Comments explain how the code does it.
Documentation is read by people who use your code, comments by people who want to understand your code, e.g. to maintain it.
Using strings for commentation has the following (potential) disadvantages:
It confuses people who don't know that the string does nothing.
Comments and string literals are highlighted differently in code editors, so your style may make your code harder to read.
It might affect performance and/or memory usage (if the strings are not removed during bytecode compilation, removing comments is done on the scanner level so it's definitively cheaper)
Most important for Python programmers: It is not pythonic:
There should be one—and preferably only one—obvious way to do it.
Stick to the standards, use comments.
I think that only the first string literal in a definition (or class) is "special", i.e. gets stored by the interpreter into the defined object's (or class') docstring.
Any other string literals you place in the code will, at the worst, mean the interpreter will build the string value at run-time, and then just throw it away. This means that doing "comments" by littering the code with string constants might cost, performance-wise.
Of course, I have not benchmarked this, and also don't know the Python interpreter well enough to say for sure.
The disadvantage, of course, is that someone else reading it will find that the code strings and comment strings are interleaved, which could be confusing.