Python looping PEP8 rule [duplicate] - python

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, ...)

Related

Setting a variable to a parameter value inline when calling a function

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?

How to check for redundant parentheses with flake8?

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.

Why use pass instead of something shorter like 0 in Python?

Why use pass instead of something shorter like 0 in Python?
E.g.:
for i in range(10): pass
vs.
for i in range(10): 0
The only two upsides of using pass are:
If using the Python interactive interpreter, it will output 0
pass is more understandable than 0
Is there any other reason behind the use of pass?
Answer: It's probably just there for readability.
I dug through an old version of python's source code (version 0.9.1) and found this in a file called doc/tut.tex:
\subsubsection{Pass Statements}
The {\tt pass} statement does nothing.
It can be used when a statement is required syntactically but the
program requires no action.
For example:
\bcode\begin{verbatim}
>>> while 1:
... pass # Busy-wait for keyboard interrupt
...
\end{verbatim}\ecode
And then this reference to it (without much other documentation) in a file called src/graminit.c:
{269, "pass_stmt", 0, 3, states_13,
"\000\000\000\000\002\000\000\000\000\000\000\000"},
which I guess is just adding pass to a pretty base-level vocabulary of python.
this as well, in src/compile.c:
case pass_stmt:
break;
and an incredibly cool file called src/Grammar which makes some references to it and has a changelog at the top which labels itself "Grammar for Python, version 4" but logs no changes to the pass_stmt.
And I couldn't find anything else. So it seems like pass has been in python since forever, and the only documentation from the beginning of the python project says that it 'does nothing.' So I think we can conclude that it's to do nothing, readably.
Looking at the Zen of Python, you can see some reasons;
Readability counts.
Explicit is better than implicit.
In the face of ambiguity, refuse the temptation to guess.
There is no mistaking what pass is.
While a 0 could mean an integer or a null operation depending on the context. That makes the code harder to read and ambiguous.

Function Call Variables Same as In Function

I am somewhat new to Python--beginner moving to intermediate--and would like to know how more experienced Python coders name their call and function variables.
Specifically, I like to name the call variables the same as the called function's 'receive' variables. Ditto the return variables.
Works fine, but are there problems I could run into, outside of changing a variable to global in the future?
An example call: v_Array = f_InitSpecified2DArray(v_Width,v_Length)
The example called or 'receiving' function: def f_InitSpecified2DArray(v_Width, v_Length):
And I do the same in the return as well: return v_Array
def f_InitSpecified2DArray(v_Width, v_Length):
v_Array = [v_Width, v_Length]
return v_Array
v_Array = f_InitSpecified2DArray(v_Width,v_Length)
The question is: Shall I expect any conflict resulting from reuse of name v_Array inside the function return and later in the calling code, where it goes assigned into variable with the same name v_Array?
Thanks.
No, this will not cause you difficulties, and doesn't cause confusion - for you, your readers, or the Python interpreter. Certainly it's less confusing than making up a new name just to differ from the parameter name, which is unnecessary. In fact, you'll often encounter the same name being used for both a named parameter and its argument, as in
runner = DocTestRunner(verbose=verbose, optionflags=optionflags)
which comes from doctest.py in the standard library (for Python 3.3).
It's instructive to search the standard library for this pattern, <name>=<same_name> (abuse of notation which I'll rectify in a moment), as its occurrences are examples of just what you're asking about. On OS X and Linux, the following command will show all lines in the standard library (plus site-packages) with occurrences of the pattern:
grep -Er --include=*.py '(\b[[:alnum:]]+\b)=\1\b' /path/to/pythonlib
On a Mac, for example, /path/to/pythonlib for Python 3.3 is usually /Library/Frameworks/Python.framework/Versions/3.3/lib/python3.3.
This command shows how many lines feature the construct, many of which have multiple occurrences:
grep -Er --include=*.py '(\b[[:alnum:]]+\b)=\1\b' /path/to/pythonlib | wc -l
I get a count of 1129, which includes a few dozen in my site-packages subdirectory. In other words, it's quite common.
Read PEP 008 titled "Style Guide for Python Code"
You seem to search for something more precise and systematic, this I appreciate, but you will safe a lot of effort and confusion to yourself and others dealing with your code, if you try to folow the PEP 008.
As usual, you will not find it followed everywhere, but that is life.
To your question about function names and variables - PEP 008 recommends using lowercase names with words separated by underscore.
local variable names are irrelevant, it really does not matter what variable name you use for return.
And do not plan moving variables into global scope too early, you shall in fact working in the other direction.

Analogue of devar in Python

When writing Python code, I often find myself wanting to get behavior similar to Lisp's defvar. Basically, if some variable doesn't exist, I want to create it and assign a particular value to it. Otherwise, I don't want to do anything, and in particular, I don't want to override the variable's current value.
I looked around online and found this suggestion:
try:
some_variable
except NameError:
some_variable = some_expensive_computation()
I've been using it and it works fine. However, to me this has the look of code that's not paradigmatically correct. The code is four lines, instead of the 1 that would be required in Lisp, and it requires exception handling to deal with something that's not "exceptional."
The context is that I'm doing interactively development. I'm executing my Python code file frequently, as I improve it, and I don't want to run some_expensive_computation() each time I do so. I could arrange to run some_expensive_computation() by hand every time I start a new Python interpreter, but I'd rather do something automated, particularly so that my code can be run non-interactively. How would a season Python programmer achieve this?
I'm using WinXP with SP3, Python 2.7.5 via Anaconda 1.6.2 (32-bit), and running inside Spyder.
It's generally a bad idea to rely on the existence or not of a variable having meaning. Instead, use a sentinel value to indicate that a variable is not set to an appropriate value. None is a common choice for this kind of sentinel, though it may not be appropriate if that is a possible output of your expensive computation.
So, rather than your current code, do something like this:
# early on in the program
some_variable = None
# later:
if some_variable is None:
some_variable = some_expensive_computation()
# use some_variable here
Or, a version where None could be a significant value:
_sentinel = object()
some_variable = _sentinel # this means it doesn't have a meaningful value
# later
if some_variable is _sentinel:
some_variable = some_expensive_computation()
It is hard to tell which is of greater concern to you, specific language features or a persistent session. Since you say:
The context is that I'm doing interactively development. I'm executing my Python code file frequently, as I improve it, and I don't want to run some_expensive_computation() each time I do so.
You may find that IPython provides a persistent, interactive environment that is pleasing to you.
Instead of writing Lisp in Python, just think about what you're trying to do. You want to avoid calling an expensive function twice and having it run two times. You can write your function do to that:
def f(x):
if x in cache:
return cache[x]
result = ...
cache[x] = result
return result
Or make use of Python's decorators and just decorate the function with another function that takes care of the caching for you. Python 3.3 comes with functools.lru_cache, which does just that:
import functools
#functools.lru_cache()
def f(x):
return ...
There are quite a few memoization libraries in the PyPi for 2.7.
For the use case you give, guarding with a try ... except seems like a good way to go about it: Your code is depending on leftover variables from a previous execution of your script.
But I agree that it's not a nice implementation of the concept "here's a default value, use it unless the variable is already set". Python does not directly support this for variables, but it does have a default-setter for dictionary keys:
myvalues = dict()
myvalues.setdefault("some_variable", 42)
print some_variable # prints 42
The first argument of setdefault must be a string containing the name of the variable to be defined.
If you had a complicated system of settings and defaults (like emacs does), you'd probably keep the system settings in their own dictionary, so this is all you need. In your case, you could also use setdefault directly on global variables (only), with the help of the built-in function globals() which returns a modifiable dictionary:
globals().setdefault("some_variable", 42)
But I would recommend using a dictionary for your persistent variables (you can use the try... except method to create it conditionally). It keeps things clean and it seems more... pythonic somehow.
Let me try to summarize what I've learned here:
Using exception handling for flow control is fine in Python. I could do it once to set up a dict in which I can store what ever I want.
There are libraries and language features that are designed for some form of persistence; these can provide "high road" solutions for some applications. The shelve module is an obvious candidate here, but I would construe "some form of persistence" broadly enough to include #Blender's suggest to use memoization.

Categories

Resources