11:48 As you mentioned, a vim plugin makes the annotations work :) But even without a plugin, when I read library/someone's code it's much much easier to understand what's going on with type annotations
Who said you don't need to "warm up an interpreter"? Yeah you do. Optimizations and branch prediction of your internal hardware such as the CPU still very much apply, regardless of the language. This however is NOT a clean way to test actual run times. You'd run each test X number of times and then perform statistical analysis, such as using only the 95th percentile in a Gausian Distribution to ensure that outliers are below a certain cutoff point and don't affect the performance.
just for fun, circa 7:00, you said "sum up until n", which would be interpreted by a native speaker as "sum up to n", your code sums to n-1, which the fix would be to initialize result = n...though that is kinda ugly for those who like ordered math sums, but so is range(n+1) for those who like nice code.
I must admit I have a problem with overuse of typing in Python. Python is supposed to be a language in which you write code quickly and conveniently. However, annotating just about anything turns it into Pascal or Java 7. Even C++ creators came to their senses and introduced the auto type. If you're going to turn Python into ancient Java, then just use Java in the first place (and preferably its modern version). There's a reason Python is the way it is so why bother with it if you're averse to its basic design principles? Personally I use typing in functions definitions (which I find much more expressive than docs) and inside functions when the interpreter can't infer a type on its own (because hints are nice). However, I'm more than willing to make an exception and NOT use typing if typing were to interfere with Python's dynamic nature, which makes it so versatile and fun to use, for example with SQL queries or some networking applications. Also, typing in Python is just extremely complicated and breaks all the rules which Python was built on, most importantly "easy is better than complicated" and "no exception is important enough to break a rule". Gradual typing would be difficult to implement on its own, but this strange mix of dynamic, gradual and static is unmanageable, especially when introduced into a developed language. There's something seriously wrong if 25% of a Python - an allegedly dynamic language - textbook is dedicated to typing and all those exceptions and exceptions to exceptions. So my advise would be: if you need static typing, use one of the very many statically typed languages. If, however, you're using Python, then use it in the way it was designed for and which makes it great.
5:25 My problem with this code is less to do with performance, and more to do with visuals. No need to waste 4 lines to return a value that's already a boolean and can be returned directly.
Neovim user here. Most people use some sort of language server protocol plugin so we get autocomplete, squiggly lines, etc. the same as vscode. But even when I was just starting Python and didn’t realize you could even DO type annotations, I was putting in comments to remind of type patterns and function signatures. I find it just so much easier to read. Particularly with more complex stuff.
About types: I program in Ada which is statically and very strongly typed; it would not cast an integer to a float unless you explicitly ask for it; actually, it would not implicitly convert a port number to, say, a serial number even if they are both integers and.... I just love it! It saves you tons of silly bugs (and let's face it: most bugs are just silly mistakes)
The problem with type annotations is that it doesn't work all that fluidly yet: a: int, b: int = (1,2) SyntaxError: invalid syntax so it can hurt your work flow to constantly fight it
There are going to be some moments where you're going to have to sacrifice the annotations for sugar syntax (such as multiple assignment), but the cases aren't that many to hurt my workflow.
@@bahmoudd The annotation should be tuple[int, int]. tuple expects a type for each element. You can also use tuple[int, ...] for a variable-length tuple.
What confuses me is that in my editor, if I do a, b = (1, 2) it will automatically infer the type. The same for a = 1, and even a = foo(), if foo is annotated. This means that I have to manually annotate only the functions. Everything else is auto inferred and checked. Does this not happen in other editors? I am using pyright, which should be supported in vscode
You're getting the main-name check stuff wrong, though. You don't need a "main()" function in your bob script at all, you just need the name check. If you put the tests under a main-name check, then the tests will only be executed if you run bob's script directly. They won't be executed when you run the main script. The name "__main__" is the name python attributes to the scope that is run first -- the entry point of the program. (That name is a key to an internal hash table.) And it's redundant to put that check in the main or in a standalone script that is always going to be the entry point of the program, because that script will always be named __main__, and the check will always return true. You only ever need that check in other scripts, for tests.
I specified in the video that the "main()" function wasn't necessary, but a personal preference. Standalone or not, I'd always recommend it for understanding which part of the script was made to be run.
Having the main function allows an entry point in pyproject.toml for you package manager…. Entry points allow you to run your code in your development virtual environment., ex: poetry run main - my-args
my biggest mistake is being a software engineer and not a farmer, I should have listened to the call of the wild but unfortunately, now I am stuck getting tortured by zeros and ones
Eons ago, before we had personal computers and we had to walk to and from school uphill in 20 feet of snow, we had to sketch out the UI (and where necessary a print chart) and then plan the overall program flowchart to link to the UI/print chart before getting approved to make punch cards (yeah, I'm that old). With modern IDEs I find that my students (I teach CompSci at uni) use RAD too often and just don't think things out.
Not directly about the topic, but what do you think would be the best way to find these arithmatic options / how to improve at being aware of them? I‘ve had my fair share of maths but i wouldn‘t think about this immediately
You dont recognize it, you have to make a conscious effort to find it. When trying to optimize functions that have to do with numbers in any way, thr first thing that should come to your mind is, "Let's try to come up with a formula for this." And then it becomes a math problem. So its not pattern recognition, it's just being able to transform the programming problem into a maths one
Another idea might be to print out the first 10 or so results and see if you see any pattern. Or heck, put the sequence into OEIS, it's an online database of number sequences
I noticed Pycharm has the option to select "Current file" in the toolbar. Every time you run, it runs the current file. I'm pretty sure it wasn't there before.
Regarding vim editor. There is a plug-in CoC that allows you to configure python auto completion and also warm you when the hint doesn't match with what you wrote
@@DrDeuteron You don't *need* to wrap anything in Python. It's a choice that some make for ease of use and rapid development, but it always introduces the performance bottleneck that is Python. It's a balancing act. Once you get to the point that performance is a critical issue and you're trying to squeeze a few milliseconds out here and there, step one is to just cut Python out of the equation.
@@simonmasters3295 C++ is certainly an option, and the option I'd choose personally, but it's by no means the only option. Plenty of languages outperform Python. You don't have to write everything from scratch in languages other than Python - they've all got their ecosystems and usually plenty of library support. Python being easy to use doesn't imply that other languages are impossible to use.
@@simonmasters3295 If a job requires a screwdriver, being inexperienced with a screwdriver doesn't magically make a hammer a good choice. Learning to use a screwdriver might even require some effort. That's life I'm afraid.
Tbh, I mostly use Sublime Text or Jupyter Notebook. I use Linux so I'll just run pylint from the terminal and it will yell at me when I mess things up. Like typing. I'm trying to pivot to using PyCharm, because I too can see the benefits of having those squigglies staring at you in the editor.
Type annotations in Python are odd to me putting the variable name before the variable type while most every other language declares the variable type, then the name.
Super useless point, but in 7:07, you don't actually need to use floor division. (n * (n - 1)) / 2 works fine because either n or n - 1 is even, so n * (n - 1) is even, so the floor division by 2 is the same as regular division Edit: I am wrong haha
No. Regular division returns a float even if the result is supposed to be an integer, so 4 / 2 = 2.0, not 2. Conversely, integer division returns, well, an integer.
Python will name whatever scope (aka file) it is currently running as “__main__”. So if you check that scope name (if __name__ == “__main__”:) you can put stuff after that that you only want to run if you run the file directly.
A type system was introduced a few years ago, which does not affect the code and is not obligatory to use as python does not enforce it, but the type hints help with finding errors when using VS Code or other Python IDE‘s. Some use it, some don‘t and it‘s honestly just personal preference. I for example like it and find it quite helpful in some cases.
The worst mistake, IMHO, is code without documentation. Try maintaining 400 KSLOC program where 95% of the files have no comments…. As a minimum every module’s docstring should say what this module does or in other words, why this module exists. Bonus points for how and usage…
Ages are natural numbers. Python has no unsigned type, so int is the most appropriate type. If your code requires a more precise measurement of age, you don't store it in a float, instead you store the age in days, which is still an int.
Nobody older than six cares about the fractional part of their age. Integers are a perfectly reasonable type for representing a person's age for almost all purposes. Besides which, you shouldn't be storing ages in the first place. Store date of birth, calculate age if and when necessary.
"...post it on stackoverflow, where you can get roasted..." is such a true statement lmfao
Premature optimisation is a particular issue of mine. Probably more when I'm doing C/C++ code than Python, but I still do it.
You can't suffer from premature optimisation if you never optimise
11:48 As you mentioned, a vim plugin makes the annotations work :)
But even without a plugin, when I read library/someone's code it's much much easier to understand what's going on with type annotations
¡Viva NeoVim!
This is true. A huge part of type annotations is the documentation it provides. It helps others, and yourself, read the code.
Who said you don't need to "warm up an interpreter"? Yeah you do. Optimizations and branch prediction of your internal hardware such as the CPU still very much apply, regardless of the language. This however is NOT a clean way to test actual run times. You'd run each test X number of times and then perform statistical analysis, such as using only the 95th percentile in a Gausian Distribution to ensure that outliers are below a certain cutoff point and don't affect the performance.
just for fun, circa 7:00, you said "sum up until n", which would be interpreted by a native speaker as "sum up to n", your code sums to n-1, which the fix would be to initialize result = n...though that is kinda ugly for those who like ordered math sums, but so is range(n+1) for those who like nice code.
I'm personally with you by 100%. Maybe he was using the pythonic way ... ;-)
I must admit I have a problem with overuse of typing in Python. Python is supposed to be a language in which you write code quickly and conveniently. However, annotating just about anything turns it into Pascal or Java 7. Even C++ creators came to their senses and introduced the auto type. If you're going to turn Python into ancient Java, then just use Java in the first place (and preferably its modern version). There's a reason Python is the way it is so why bother with it if you're averse to its basic design principles?
Personally I use typing in functions definitions (which I find much more expressive than docs) and inside functions when the interpreter can't infer a type on its own (because hints are nice). However, I'm more than willing to make an exception and NOT use typing if typing were to interfere with Python's dynamic nature, which makes it so versatile and fun to use, for example with SQL queries or some networking applications.
Also, typing in Python is just extremely complicated and breaks all the rules which Python was built on, most importantly "easy is better than complicated" and "no exception is important enough to break a rule". Gradual typing would be difficult to implement on its own, but this strange mix of dynamic, gradual and static is unmanageable, especially when introduced into a developed language. There's something seriously wrong if 25% of a Python - an allegedly dynamic language - textbook is dedicated to typing and all those exceptions and exceptions to exceptions. So my advise would be: if you need static typing, use one of the very many statically typed languages. If, however, you're using Python, then use it in the way it was designed for and which makes it great.
5:25 My problem with this code is less to do with performance, and more to do with visuals. No need to waste 4 lines to return a value that's already a boolean and can be returned directly.
12:28 I definitely didn't mentally autocomplete that sentence with completely the wrong definition of execute...
Neovim user here. Most people use some sort of language server protocol plugin so we get autocomplete, squiggly lines, etc. the same as vscode. But even when I was just starting Python and didn’t realize you could even DO type annotations, I was putting in comments to remind of type patterns and function signatures. I find it just so much easier to read. Particularly with more complex stuff.
About types: I program in Ada which is statically and very strongly typed; it would not cast an integer to a float unless you explicitly ask for it; actually, it would not implicitly convert a port number to, say, a serial number even if they are both integers and.... I just love it! It saves you tons of silly bugs (and let's face it: most bugs are just silly mistakes)
The problem with type annotations is that it doesn't work all that fluidly yet:
a: int, b: int = (1,2)
SyntaxError: invalid syntax
so it can hurt your work flow to constantly fight it
There are going to be some moments where you're going to have to sacrifice the annotations for sugar syntax (such as multiple assignment), but the cases aren't that many to hurt my workflow.
Or, for example, you can't use types in lambda arguments.
just do this:
a: tuple[int] = 1,2
@@bahmoudd The annotation should be tuple[int, int]. tuple expects a type for each element. You can also use tuple[int, ...] for a variable-length tuple.
What confuses me is that in my editor, if I do a, b = (1, 2) it will automatically infer the type. The same for a = 1, and even a = foo(), if foo is annotated.
This means that I have to manually annotate only the functions. Everything else is auto inferred and checked.
Does this not happen in other editors?
I am using pyright, which should be supported in vscode
I’m convinced. Never thought that the advantages are that rich. Thx.
"Bob's age, which is obviously 1209" - without laughing, that was a good one!
Types are important even when they are not enforced
You're getting the main-name check stuff wrong, though. You don't need a "main()" function in your bob script at all, you just need the name check. If you put the tests under a main-name check, then the tests will only be executed if you run bob's script directly. They won't be executed when you run the main script. The name "__main__" is the name python attributes to the scope that is run first -- the entry point of the program. (That name is a key to an internal hash table.)
And it's redundant to put that check in the main or in a standalone script that is always going to be the entry point of the program, because that script will always be named __main__, and the check will always return true. You only ever need that check in other scripts, for tests.
I specified in the video that the "main()" function wasn't necessary, but a personal preference. Standalone or not, I'd always recommend it for understanding which part of the script was made to be run.
Wasn't the main() function useful to avoid cluttering the global namespace!?
@@landsgevaeryes. With the main others can import it from the main and run stuff before and after.
@@joshix833 Is it common practice to include the main() function in most modules? I thought it wasn't? Is there a PEP on this per-chance?
Having the main function allows an entry point in pyproject.toml for you package manager…. Entry points allow you to run your code in your development virtual environment., ex: poetry run main - my-args
my biggest mistake is being a software engineer and not a farmer, I should have listened to the call of the wild but unfortunately, now I am stuck getting tortured by zeros and ones
Eons ago, before we had personal computers and we had to walk to and from school uphill in 20 feet of snow, we had to sketch out the UI (and where necessary a print chart) and then plan the overall program flowchart to link to the UI/print chart before getting approved to make punch cards (yeah, I'm that old). With modern IDEs I find that my students (I teach CompSci at uni) use RAD too often and just don't think things out.
Not directly about the topic, but what do you think would be the best way to find these arithmatic options / how to improve at being aware of them? I‘ve had my fair share of maths but i wouldn‘t think about this immediately
You dont recognize it, you have to make a conscious effort to find it.
When trying to optimize functions that have to do with numbers in any way, thr first thing that should come to your mind is, "Let's try to come up with a formula for this." And then it becomes a math problem. So its not pattern recognition, it's just being able to transform the programming problem into a maths one
@@novamc7945Gotcha, thank you.
Another idea might be to print out the first 10 or so results and see if you see any pattern. Or heck, put the sequence into OEIS, it's an online database of number sequences
I think, biggest of biggest mistake is Running Wrong Script. 🙄
I noticed Pycharm has the option to select "Current file" in the toolbar. Every time you run, it runs the current file. I'm pretty sure it wasn't there before.
@@rudiklein Yeah. That's why we shouldn't IDE dependent.
Regarding vim editor. There is a plug-in CoC that allows you to configure python auto completion and also warm you when the hint doesn't match with what you wrote
I can't shake the feeling that if you want high performance and a robust type system, Python might be the wrong tool for the job.
yes you need to python to wrap your C/C++/FORTRAN, which is what numpy and scipy do.
@@DrDeuteron You don't *need* to wrap anything in Python. It's a choice that some make for ease of use and rapid development, but it always introduces the performance bottleneck that is Python. It's a balancing act.
Once you get to the point that performance is a critical issue and you're trying to squeeze a few milliseconds out here and there, step one is to just cut Python out of the equation.
Nah. Your comment assumes that
1. C++ experience exists for the programmer and
2. You can write all those library functions at little or no cost
@@simonmasters3295 C++ is certainly an option, and the option I'd choose personally, but it's by no means the only option. Plenty of languages outperform Python.
You don't have to write everything from scratch in languages other than Python - they've all got their ecosystems and usually plenty of library support. Python being easy to use doesn't imply that other languages are impossible to use.
@@simonmasters3295 If a job requires a screwdriver, being inexperienced with a screwdriver doesn't magically make a hammer a good choice. Learning to use a screwdriver might even require some effort. That's life I'm afraid.
Getting roasted in stackoverflow is a scientific journal.
Tbh, I mostly use Sublime Text or Jupyter Notebook. I use Linux so I'll just run pylint from the terminal and it will yell at me when I mess things up. Like typing.
I'm trying to pivot to using PyCharm, because I too can see the benefits of having those squigglies staring at you in the editor.
All these Bobs remind me of Bobby Watson, the commercial traveller and his family, Bobby his wife, and Bobby and Bobby their kids.
love the vids! keep it up
Type annotations in Python are odd to me putting the variable name before the variable type while most every other language declares the variable type, then the name.
evil indently be like:
"Top 10 python mistakes that you should always make"
to prevent the problem of running the wrong script, switch to VS code
Super useless point, but in 7:07, you don't actually need to use floor division. (n * (n - 1)) / 2 works fine because either n or n - 1 is even, so n * (n - 1) is even, so the floor division by 2 is the same as regular division
Edit: I am wrong haha
No. Regular division returns a float even if the result is supposed to be an integer, so 4 / 2 = 2.0, not 2. Conversely, integer division returns, well, an integer.
@@mikoaj1349 Oh, I didn't consider that. Good point
It took me hours to code and a lifetime to program.
why benchmarking yourself when you have python -m timeit?
yes, you can run mypy in vim
sum of n natural numbers is ( n * ( n + 1 )) // 2
range(n) is 0..n-1 :)
21:18 it's "Fool Proof", not "Full Proof". The latter applies to whiskey.
Is it spelled somewhere "full proof"? Because I couldn't find it and full and fool are often pronounced very similarly...
Did you name your python version bob?
Your type annotation paradigm gets really old sometimes
Poor Bob, always taking the blame! 😁
13:54 Why was bob not capitalised ??
Chapter 1: Bad bencharks.
Chapter 2: Premature optimisation, with bad benchmarks to prove your point 😅
Even bad BM is enough to distinguish O(n) and O(1) 🐱
Thanks
Awesome.
What is "if name is equal to main"
Python will name whatever scope (aka file) it is currently running as “__main__”. So if you check that scope name (if __name__ == “__main__”:) you can put stuff after that that you only want to run if you run the file directly.
pythono looks a lot different than a few years ago... it looks like a typed language... what's going on?
A type system was introduced a few years ago, which does not affect the code and is not obligatory to use as python does not enforce it, but the type hints help with finding errors when using VS Code or other Python IDE‘s. Some use it, some don‘t and it‘s honestly just personal preference. I for example like it and find it quite helpful in some cases.
The worst mistake, IMHO, is code without documentation. Try maintaining 400 KSLOC program where 95% of the files have no comments…. As a minimum every module’s docstring should say what this module does or in other words, why this module exists. Bonus points for how and usage…
I like random Bob
Bob is very old 😅
hi 5th person
Arguably age should not be an integer, because ages aren't.
Ages are natural numbers. Python has no unsigned type, so int is the most appropriate type. If your code requires a more precise measurement of age, you don't store it in a float, instead you store the age in days, which is still an int.
@@terra_creeper You miss the point, ages are not natural numbers and you cannot perform arithmetic with them. Int is a poor choice of type.
What should it be then?
@@AshleyPOliver You do perform arithmetic with ages. Or is for example calculating the mean age not arithmetic?
Nobody older than six cares about the fractional part of their age. Integers are a perfectly reasonable type for representing a person's age for almost all purposes.
Besides which, you shouldn't be storing ages in the first place. Store date of birth, calculate age if and when necessary.
I like type annotations cause my objects maintain its methods and attributes tips.
cars: list[Cars].