There exist static analysis tools for Python, but compile time checks tend to be diametrically opposed to the run-time binding philosophy that Python embraces. It\'s possibl
Well, I'm not much of a python programmer, but I'd say that the answer is 'YES'.
Any dynamic language that lets you create a variable with any name at any time, could use a 'strict' pragma.
Strict vars (one of the options for strict in Perl, 'use strict' turns them all on at once) in Perl requires that all variables are declared before they are used. Which means that this code:
my $strict_is_good = 'foo';
$strict_iS_good .= 'COMPILE TIME FATAL ERROR';
Generates a fatal error at compile time.
I don't know of a way to get Python to reject this code at compile time:
strict_is_good = 'foo';
strict_iS_good += 'RUN TIME FATAL ERROR';
You will get a run-time exception that strict_iS_good
is undefined. But only when the code is executed. If your test suite does not have 100% coverage, you can easily ship this bug.
Any time I work in a language that does not have this behavior (PHP for example), I get nervous. I am not a perfect typist. A simple, but hard to spot, typo can cause your code to fail in ways that may be hard to track down.
So, to reiterate, YES Python could use a 'strict' pragma to turn on compile time checks for things that can be checked at compile time. I can't think of any other checks to add, but a better Python programmer probably could think of some.
Note I focus on the pragmatic effect of stict vars in Perl, and am glossing over some of the details. If you really want to know all the details see the perldoc for strict.
Update: Responses to some comments
Jason Baker : Static checkers like pylint are useful. But they represent an extra step that can be and often is skipped. Building some basic checks into the compiler guarantees that these checks are performed consistently. If these checks are controllable by a pragma, even the objection relating to the cost of the checks becomes moot.
popcnt : I know that python will generate a run time exception. I said as much. I advocate compile time checking where possible. Please reread the post.
mpeters : No computer analysis of code can find all errors--this amounts to solving the halting problem. Worse, to find typos in assignments, your compiler would need to know your intentions and find places where your intentions differ from your code. This is pretty clearly impossible.
However this does not mean that no checking should be done. If there are classes of problems that are easy to detect, then it makes sense to trap them.
I'm not familiar enough with pylint and pychecker to say what classes of errors they will catch. As I said I am very inexperienced with python.
These static analysis programs are useful. However, I believe that unless they duplicate the capabilities of the compiler, the compiler will always be in a position to "know" more about the program than any static checker could. It seems wasteful not to take advantage of this to reduce errors where possible.
Update 2:
cdleary - In theory, I agree with you, a static analyzer can do any validation that the compiler can. And in the case of Python, it should be enough.
However, if your compiler is complex enough (especially if you have lots of pragmas that change how compilation occurs, or if like Perl, you can run code at compile time), then the static analyzer must approach the complexity of the compiler/interpreter to do the analysis.
Heh, all this talk of complex compilers and running code at compile time shows my Perl background.
My understanding is that Python does not have pragmas and can not run arbitrary code at compile time. So, unless I am wrong or these features are added, a relatively simple parser in the static analyzer should suffice. It certainly would be helpful to force these checks at every execution. Of course, the way I'd do this is with a pragma.
Once you add pragmas to the mix, you have started down a slippery slope and the complexity of you analyzer must grow in proportion to the power and flexibility you provide in your pragmas. If you are not careful, you can wind up like Perl, and then "only python can parse Python," a future I wouldn't want to see.
Maybe a command line switch would be a better way to add forced static analysis ;)
(In no way do intend to impugn Python's capabilities when I say that it can't futz with compile time behavior like Perl can. I have a hunch that this is a carefully considered design decision, and I can see the wisdom in it. Perl's extreme flexibility at compile time is, IMHO, a great strength and a terrible weakness of the language; I see the wisdom in this approach as well.)
Python has no true lexical scoping, so strict vars wouldn't be very sensible. It has no symbolic references AFAIK, so it has not need for strict refs. It has not barewords, so it has no need for strict vars.
To be honest, it's only lexical scoping I miss. The other two I'd consider warts in Perl.
"the run-time binding philosophy that Python embraces... makes "use strict" behavior unnecessary [and] especially undesirable"
Pretty good summary. Thanks.
That is essentially it. Static analysis tools don't help Python enough to be worthwhile.
Edit
"I'm asking for us to introspect on why we don't need it and, relatedly, why Perl programmers think they do need it."
The reason why is precisely the reason you already gave. We don't need it because it doesn't help. Clearly, you don't like that answer, but there's not much more to be said. Compile-time or pre-compile time checking simply does not help.
However, since you took the time to asked the question again, I'll provide more evidence for the answer you already gave.
I write Java almost as much as I write Python. Java's static type checking does not prevent any logic problems; it doesn't facilitate meeting performance requirements; it doesn't help meet the use cases. It doesn't even reduce the volume of unit testing.
While static type checking does spot the occasional misuse of a method, you find this out just as quickly in Python. In Python you find it at unit test time because it won't run. Note: I'm not saying wrong types are found with lots of clever unit tests, I'm saying most wrong type issues are found through unhandled exceptions where the thing simply won't run far enough to get to test assertions.
The reason why is Pythonistas don't waste time on static checking is simple. We don't need it. It doesn't offer any value. It's a level of analysis that has no economic benefit. It doesn't make me any more able to solve the real problems that real people are having with their real data.
Look at the most popular SO Python questions that are language (not problem domain or library) related.
Is there any difference between "foo is None" and "foo == None"? -- ==
vs. is
. No static checking can help with this. Also, see Is there a difference between `==` and `is` in Python?
What does ** (double star) and * (star) do for parameters? -- *x
gives a list, **x
gives a dictionary. If you don't know this, your program dies immediately when you try to do something inappropriate for those types. "What if your program never does anything 'inappropriate'". Then your program works. 'nuff said.
How can I represent an 'Enum' in Python? -- this is a plea for some kind of limited-domain type. A class with class-level values pretty much does that job. "What if someone changes the assignment". Easy to build. Override __set__
to raise an exception. Yes static checking might spot this. No, it doesn't happen in practice that someone gets confused about an enum constant and a variable; and when they do, it's easy to spot at run time. "What if the logic never gets executed". Well, that's poor design and poor unit testing. Throwing a compiler error and putting in wrong logic that's never tested is no better than what happens in a dynamic language when it's never tested.
Generator Expressions vs. List Comprehension -- static checking doesn't help resolve this question.
Why does 1+++2 = 3? -- static checking wouldn't spot this. 1+++2 in C is perfectly legal in spite of all the compiler checking. It's not the same thing in Python as it is in C, but just as legal. And just as confusing.
List of lists changes reflected across sublists unexpectedly -- This is entirely conceptual. Static checking can't help solve this problem either. The Java equivalent would also compile and behave badly.
This original answer is correct, but does not perhaps explain the situation in a practical sense.
There exist static analysis tools for Python, but compile time checks tend to be >diametrically opposed to the run-time binding philosophy that Python embraces.
What 'use strict' provides in Perl is the ability to ensure that a mis-spelled or variable name is (usually) caught at compile-time. This does improve code reliability, and speeds up development. But in order to make such a thing worthwhile, you need to declare variables. And Python style seems to discourage that.
So in Python, you never find out about a mis-spelled variable until you notice at run-time that the assignment you thought you made is not being made, or that an expression seems to resolve to an unexpected value. Catching such errors can be time-consuming, especially as programs get large, and as people are forced to maintain code developed by others.
Java and C/C++ take it a step further, with type checking. The motivation is practical, rather than philosophical. How can you catch as many errors as possible as soon as possible, and be sure that you eliminate all of them before releasing code to production? Each language seems to take a particular strategy and run with it, based upon what they think is important. In a language like Perl, where run-time binding isn't supported, it makes sense to take advantage of 'use strict' to make development easier.
I consider the 'use strict'
in Perl more like a pragma as you hinted at: it changes the behavior of the compiler.
Perl language philosophy is different from python philosophy. As in, you are given more than enough rope to hang yourself repeatedly, in Perl.
Larry Wall is big into linguistics, so we have from Perl what is referred to as the TIMTOWTDI (say tim-toe-dee
) principle vs. Zen of python:
There should be one-- and preferably only one --obvious way to do it.
you could very easily use pylint and PyChecker to come up with your own flavor of use strict
for python (or something analogous to perl -cw *scriptname*
) but because of the different philosophies in the language design, you will not encounter this in practice widely.
Based on your comment to the first poster, you are familiar with python's import this
. There are a lot of things in there which illuminate why you do not see an equivalent of use strict
in Python. If you meditate on the koan found in the Zen of Python, you may find enlightenment for yourself. :)
Perl is a unrestrained language as they said :) . So you can use the variable before announced ; Eg : If you use a var name "is_array" but type in "is_arrby" ,the compiler won't report error without "use strict" . So when coding long program in perl ,better use "use strict" statement. Of course, less than 50 lines for running one time script, there is no need :)