How do you read and quickly edit python code - python

I typically work with C++ but off late have to program a lot in Python. Coming from a C++ background, I am finding dynamic typing to be very inconvenient when I have to modify an existing codebase. I know I am missing something very basic and hence turning to the stackoverflow community to understand best practices.
Imagine, there is a class with a number of methods and I need to edit an existing method. Now, in C++, I could explicitly see the datatype of every parameter, check out the .h files of the corresponding class if need be and could quickly understand what's happening. In python on the other hand, all I see are some variable names. I am not sure if it is a list or a dictionary or maybe some custom datastructure with its getters and setters. To figure this out, I need to look at some existing usages of this function or run the code with breakpoints and see what kind of datastructure am I getting. I find either methods to be very time consuming. Is there a faster way to resolve this problem? How should I quickly determine what's the datatype of a particular variable?
The general impression is that code is easier to read/write in Python, but I am not finding it very quick to read python code because of lack of types. What am I missing here?

I feel your pain, too! I frequently switch between Python and C++, so paradigm shifting does give me paranoia.
However, I've been readjusting my codes with:
Type Annotations
It doesn't improve runtime performance, but it provides sense of comfort when reading through tens of thousands line of codes. Also, you can run your python programs with this to further verify your type annotations:
mypy

These are the following things i follow:
Comment clearly what is being returned and what is the input in the docstring
Use a debug(or a Flag) variable, which is by default set to False, and keep a if block as follows.
if debug:
print(type(variable))
So, in that way, you would be sure to see what is the type of the variable.

In Python, you can see the data type of any variable by using
type(variable_name)
It will show you data type of that variable. Such as int, bool, str, etc.

Related

How to get the expected parameters of another function in python?

I would like to know if it is possible, given a function (as an instance, or a string), to get its paramaters, if defined default values for each paramater and, if possible, the type of each parameters (probably using the type of default value, if defined) in Python 3.5.
Why would you want that ?!
Long story short, I am generating a XML file containing details of different functions in my project. Since the generator has to be future-proof in case someone modifies, add, or delete a function, the next generated file must be updated. I succesfully retrieved the functions I wanted either as instance or a string of the code calling it.
I have two solutions (well, more the beginnings of solutions) to solve this problem, using inspect and jedi.
Inspect
Using inspect.signature(function), I can retrieve the name and default values of all the parameters. The main issue I see here, would be analyzing this function:
def fct(a=None):
# Whatever the function does...
Analyzing the type of the default value will lead to misunderstandigs. Is there a way to fix that ?
Jedi
Jedi is an extremely powerful tool, maybe even too much ! Getting the function in a one line code string, and analyzing it through Jedi gives an extraordinary amount of information, that I am lost with to be completely honest. Plus, I might get bad autocompletion (example: instead of having the paramaters for print, I might get autocompleted to println)
If someone had used one of these tools for this prupose, or even better if you know a better, more "pythonic" way of doing this, I would be really grateful !

Documentation For Specific Functions in Python

What is the optimal way to get documentation about a specific function in Python? I am trying to download stock price data such that I can view it in my Spyder IDE.
The function I am interested in is:
ystockquote.get_historical_prices
How do I know how many inputs the function takes, the types of inputs it accepts, and the date format for example?
Just finding documentation
I suspect this question was super-downvoted because the obvious answer is to look at the documentation. It depends where your function came from, but googling is typically a good way to find it (I found the class here in a few seconds of googling).
It is also very trivialy to just check the source code
In order to import a function, you need to know where the source file it comes from is; open that file: in python, docstrings are what generate the documentation and can be found in triple-quotes beneath the function declaration. The arguments can be inferred from the function signature, but because python is dynamically typed, any type "requirements" are just suggestions. Some good documenters will provide the optimal types, too.
While "how do I google for documentation" is not a suitable question, the question of how to dynamically infer documentation is more reasonable. The answer is
The help function, built in here
The file __doc__ accessible on any python object, as a string
Using inspection
The question is even more reasonable if you are working with python extensions, like from external packages. I don't if the package you specifically asked about has any of those, but they can be tricky to work with if the authors haven't defined docstrings in the module. The problem is that in these cases, the typing can be rigidly inforced. There is no great way to get the tpye requirements in this case, as inspection will fail. If you can get at the source code, though, (perhaps by googling), this is where the documentation would be provided

How to detect assignment to a mis-cased instance variable in Python

I just ran into a somewhat hard to detect issue in Python. We're using the xml module (xml.etree.ElementTree.Element), where you have elements and the elements have a "text" instance variable. But someone used "Text" (note, uppercase "T"). The generated XML of course did not contain the expected string.
This didn't throw any errors or anything, other than the program just not working properly, and I think I understand why.
My question is, is there a good way to detect this problem? I feel like if there were I'd probably find a few similar mistakes if I were able to scan all of our files.
I've tried pylint and pyflakes but neither tool seems to detect this.
I remember in some other language there was an option you could set to require explicit declaration before usage (it's funny, I forget which language that was now, Ada maybe?), and I know declaration isn't very Pythonic, but it would seem adding "names" to an instance of a class shouldn't be very standard usage either.

Would optional static typing benefit Python API-design or be a disadvantage? (type checking decorator example included)

I'm a long time Python developer and I really love the dynamic nature of the language, but I wonder if Python would benefit from optional static typing.
Would it be beneficial to be able to apply static typing to the API of a library, and what would the disadvantages of this be?
I quickly sketched up a decorator implementing runtime-static type checking on pastebin and it works like this:
# A TypeError will be thrown if the argument "string" is not a "str" and if
# the returned value is not an "int"
#typed(int, string = str)
def getStringLength(string):
return len(string)
Would it be practical to use a decorator like this on the API-functions of a library? In my point of view type checking is not needed in the internal workings of a domain specific module of a library, but on the connection points between the library and it's client a simple version of design by contract by applying type checking could be useful. Especially as a type of enforced documentation which clearly states to the client of the library what it expects and returns.
Like this example where addObjectToQueue() and isObjectProcessed() are exposed for use by the client and processTheQueueAndDoAdvancedStuff() is an internal library function. I think type checking could be useful on the outward facing functions but would only bloat and restrict the dynamicness and usefulness of python if used on the internal functions.
# some_library_module.py
#typed(int, name = string)
def addObjectToQueue(name):
return random.randint() # Some object id
def processTheQueueAndDoAdvancedStuff(arg_of_library_specific_type)
# Function body here
#typed(bool, object_id = int)
def isObjectProcessed(object_id):
return True
What would the disadvantages of using this technique be?
What would the disadvantages of my naive implementation on pastebin be?
I don't want answers discussing the conversion of Python to a statically typed language, but thoughts about API design-specific pros/cons. (please move this to programmers.stackexchange.com if you consider it not a question)
Personally, I don't find this idea attractive for Python. This is all just my opinion, of course, but for context I'll tell you that Python and Haskell are probably my two favourite programming languages - I like languages at both extreme ends of the static vs dynamic typing spectrum.
I see the main benefits of static typing as follows:
Increased likelihood that your code is correct once the compiler has accepted it; if I know I've threaded my values through all the operations I invoked in such a way that the result type of one always matches the input type of another, and the final result type is the one I wanted, it increases the probability that I've selected the correct operations. This point is of deeply arguable value, since it only really matters if you're not testing very much, which would be bad. But it is true that, when programming in Haskell, when I sit back and say "there, done!" I am actually done a lot of the time, whereas that's almost never true of my Python code.
The compiler automatically points out most of the places that need changing when I make an incompatible change to a data structure or interface (most of the time). Again, tests are still needed to actually be sure you've caught all the implications, but most of the time the compiler's nagging is actually sufficient, in my experience, which deeply simplifies such refactoring; you can go straight from implementing the core of the refactoring to testing that the program still works okay, because the actual work of making all the flow-on changes is almost mechanical.
Efficient implementation. The compiler gets to use all the knowledge it has about types to do optimisation.
Your suggested system doesn't really provide any of these benefits.
Having written a program making use of your library, I still don't know if it contains any type-incorrect uses of your functions until I do extensive testing with full code coverage to see if any execution path contains a bad call.
When I refactor something, I need to go through many many rounds of "run full test suite, look for exception, find where it came from, fix the code" to get anything at all like a static-typing compiler's problem detection.
Python will still be behaving as if those variables could be anything at any time.
And to get even that much, you've sacrificed the flexibility of Python duck-typing; it's not enough that I provide a sufficiently "list-like" object, I have to actually provide a list.
To me, this sort of static typing is the worst of both worlds. The main dynamic typing argument is "you have to test your code anyway, so you may as well use those tests to catch type errors and free yourself from having to work around the type system when it doesn't help you". That may or may not be a good argument with respect to a really good static type system, but it absolutely is a compelling argument with respect to a weak partial static type system that only detects type errors at runtime. I don't think nicer error messages (which is all it really buys you most of the time; a type error not caught at the interface is almost certainly going to throw an exception deeper in the call stack) is worth the loss of flexibility.

haskell vs python typing

I am looking for example where things in python would be easier to program just because it is dynamically typed?
I want to compare it with Haskell type system because its static typing doesn't get in the way like c# or java. Can I program in Haskell as I can in python without static typing being a hindrance?
PS: I am a python user and have played around little bit with ML and Haskell.. ... I hope it is clear now..
Can I program in Haskell as I can in python without static typing being a hindrance
Yes.
To elaborate, I would say the main gotcha will be the use of existential types in Haskell for heterogeneous data structures (regular data structures holding lists of variously typed elements). This often catches OO people used to a top "Object" type. It often catches Lisp/Scheme programmers. But I'm not sure it will matter to a Pythonista.
Try to write some Haskell, and come back when you get a confusing type error.
You should think of static typing as a benefit -- it checks a lot of things for you, and the more you lean on it, the less things you have to test for. In addition, it enables the compiler to make your code much faster.
Well for one you can't create a list containing multiple types of values without wrappers (like to get a list that may contain a string or an int, you'd have to create a list of Either Int String and wrap each item in a Left or a Right).
You also can't define a function that may return multiple types of values (like if someCondition then 1 else "this won't compile"), again, without using wrappers.
Like Chris said, this is one objective question (what can a dynamically typed language do that a statically typed one can't?) and one subjective question (can I use Haskell without static typing being a hindrance). So you're going to get mostly subjective answers, because the first question is not as interesting.
For me, the biggest hindrance was Haskell's IO type, because I had to stop and think about what code does I/O and what code doesn't, and explicitly pass information between the two. Everything else was pretty easy. If you commonly write
if someCondition:
return 1
else:
return "other"
Then you're making your own problems, Python just doesn't stop you from doing it. Haskell will, and that's about the only difference. The only exception is that this is sort of common in Python:
if someErrorCondition:
return None
else:
return NewItem(Success)
You can't do that in Haskell because there is no common None object. But there are easy ways to work around it.
I did find the type errors confusing at first, but I learned to read them in about a week.
I want to echo Don's advice: just try writing some Haskell and come back when you get a confusing type error.

Categories

Resources