Just some traps and pitfalls that took me a while to get used to in Python.
List methods vs. built-in methods
# sort(), sorted(), r...
For further actions, you may consider blocking this person and/or reporting abuse
Oh my god, the import/package system.
My senior thesis project was a Python project, and I was coming from the Ruby world. Dear lord, I never got used to the import system. The fact that you have to throw in something like this to import anything local astounded me:
Circular dependencies tripped me up quite a bit too, but I can probably put that down to lack of experience in Python. But man, coming from a world where you could just do this, it was a bit of a shock:
how about having the
__init__.py
file in the foo/ ?The path insert is fairly horrible but I don't believe it's recommended.
Setting the
PYTHONPATH
environment variable can be useful in a local project (e.g.export PYTHONPATH=.
in the root of your project), then using packages and absolute imports if you've got a lot of modules.You can also import local modules just by using their name e.g.
import my_module
to importmy_module.py
from the same directory.I find the Ruby require system a bit too close to PHP for my liking. I prefer that Python and Java abstract away the file system. However, using Bundler to manage your dependencies and put them onto the Ruby path at runtime is better than anything Python has.
In Python3 it's a lot saner (still not perfect though)
To add to that last one. You can actually change manipulate the integer cache using the module ctypes. Do this, if you want to get fired from you job :D
Now we have replaced 7 by 13.
Source: kate.io/blog/2017/08/22/weird-pyth...
Let's not do that with PHP or JavaScript, otherwise it'll never end :smile:
For the string.join, it makes sense, although both choice (
string.join
orlist.join
) have inconvenient.If you look at every single
str
methods (.title()
,.lower()
,.format()
,.strip()
, it returns a new string. It never mutate the original one.For the
list
objects, it's the opposite. It always mutates the original list, and always returnsNone
.So, if they implemented the
.join()
method on thelist
objects, they would have had to break this "convention". If they didn't, this would have append:(I'm not even sure it's possible change the type of an existing object)
So, the choice they made doesn't break any conventions and is logic, although it might not be the prettiest. IMHO, it's right choice. And in the zen's opinion too, I guess:
(guess they didn't respect this one for your last example though).
Good post anyway, learned something about python's
int
, thanks! :+1:Python does not forbid many things so try this:
:smiley: Never thought of this before... That's cool! Thanks!
Wow, thank you for your elaborate response! :)
Here's a gotcha I once saw someone post involving dictionary keys:
This program:
Yields this output:
It never bit me in any production code, but still, I thought it was interesting enough to share.
I find Python's name-bindings to be especially confusing at times.
In the following code:
The output will be:
Because the name
i
is bound to the loop, and not to the function. To get a sequence of numbers, we'd have to do as follows:The function
make_f(n)
creates a new binding. A newn
is bound at every call tomake_f(n)
, so the values are kept.When I first started writing Python I couldn't get over the lack of braces. Having written a lot of Ruby and read a lot of unreadable Perl I now think it's a great feature. Readability as a language feature!
I also had a challenge with it until I realized that I basically indented this way anyways with other languages for readability. I am now to the point that all the extra stuff just feels like noise. I have to do a fair amount of JS and I feel like I have to make an effort to ignore all the brackets and semicolons.
Another thing that I learned recently
Because a and b are referencing same memory
It's the case for every single thing in python except for
int
,float
andstr
. These last three ones are passed by value (meaning we copy their value), everything else is passed by reference (meaning, as you said, the pass the "reference to the memory", the value isn't duplicated).Have a look at this:
Quick tip:
If you don't want a list to be passed by reference, you can do that by calling
.copy()
.The same works with
dict
. And obviously, for your custom object, you have to implement it yourself.Gotcha
This copy methods on
list
anddict
are only shallow copies. That means you don't duplicate the values too, they are passed my reference:But if you want to do a deep copy:
Note: when you pass a variable by reference, it's a 2 way thing of course. If you edit the original on, it'll change the reference, and if you edit the reference, you change the original too.
Basically, all types in Python are passed-by-reference. The distinction is between mutable and immutable types. I recommend reading Python's Data Mode. The first couple of paragraphs are really helpful.
When to use self in classes and methods