Sorry about that noise in the background! It was freezing in my room so for the first time in my life I turned on the radiator closest to my desk, and when I took off my noise cancelling headphones I realised it was pretty loud.
@rishiraj25488 ай бұрын
👍
@Whatthetrash8 ай бұрын
No worries. Didn't even hear it! :)
@StYxXx8 ай бұрын
Didn't hear anything. Should check my ears...
@Kommentierer8 ай бұрын
With a bare except block, you are also catching KeyboardInterrupt, something you definitely don't want in a console program.
@Indently8 ай бұрын
Beautiful addition, I didn't even think about that.
@schwingedeshaehers8 ай бұрын
sometimes you want, but at least you should check for it specifically, if you catch all
@Pacvalham8 ай бұрын
Catching/excepting KeyboardInterrupt is one step in recreating Vim in Python.
@uuuummm98 ай бұрын
Are you sure? The "input" call is outside of the try catch.
@schwingedeshaehers8 ай бұрын
@@uuuummm9 you have to time it perfectly, probably
@shakapaker8 ай бұрын
1. Use specific exceptions instead of a bare except block. Provide meaningful error messages in exceptions 2. Avoid mutable default arguments in function definitions. Specify function argument types for clarity 3. Use iterators for memory efficiency. Understand the memory implications of data structures Write intentional and efficient code. Always aim for code that's easy to read, maintain, and efficient. Don't settle for quick fixes or lazy practices - that can lead to bugs.
@mudi2000a8 ай бұрын
Tell this to the developers in my company that you should not display “something went wrong”, it has become a running joke already.
@ruidian81578 ай бұрын
I think one of the bad habits that bites me the most is not using "def main():". Not using that means every variable that you defined is in global scope. Sometimes silly mistake happens, and you end up making a function doing not what it was meant to do.
@VinceKully8 ай бұрын
It's not the lack of a `def main()`, it's due to not having the __name__ check.
@ruidian81578 ай бұрын
@@VinceKully Actually no. Even with the “__name__” check, the variable will still be global in the current file. I once wrote a function and forgot to include one of the required variable as the parameter of the function. But the code works with no error since I have a global variable which coincidentally has the same name as the variable. This causes some bugs and cost me a few days to finally found it…
@callbettersaul8 ай бұрын
Can't believe I never thought about the global variable part. I've never done a mistake by using them in functions, but I sure am annoyed every time pycharm suggests those variables to me, when I'm making a function. This would also remove the global variable shadowing warnings. It's decided, I'm going to start using main function as well.
@knut-olaihelgesen36086 ай бұрын
I often use globals - often read only constants, and I've never in my 4 years of using python had a real reason to use the main()/__name__ snippet. Globals aren't evil, but use them carefully
@benjaminelo37098 ай бұрын
For tip 1 I wouldn’t recommend using exceptions for control flow. Instead check that the input is a number first, and then ask the user to in put a valid number. In more complex programs it is not clear when people extend your work that your program is actually expected to throw exceptions.
@victorsago3 ай бұрын
AFAIK, the only reliable way to check whether on input is a number is to try to convert it to a number. And putting this attempt at conversion within a try block is the Pythonic way. :)
@DuncanBooth8 ай бұрын
Sorry but the argument `target: list[T] = None` is itself a bad habit. mypy will flag an error for this and you really should be using a tool like mypy to ensure your type annotations are correct. Either `target: list[T] | None = None` or `target: Optional[list[T]] = None` is needed for valid typing.
@Indently8 ай бұрын
No need to be sorry, you absolutely caught me there. I use Mypy all the time and should have quickly run my code through it before making the video. Thanks for pointing it out :)
@mudi2000a8 ай бұрын
And then it has become an unreadable mess. I find it fascinating that if you use those type hints Python code looks worse than any statically typed language including c++. I do actually think they are a good idea especially for functions as they allow self documenting code but I think they are not well designed and create lots of clutter.
@DuncanBooth8 ай бұрын
@@mudi2000a I don't think adding '| None' makes it unreadable but I used to use the implicit form before mypy started blocking it because it is shorter. Also I dislike that it permits you to actually pass None explicitly while the implicit form says the caller doesn't have to pass an argument but if they do it must be a list. Now to do it properly you have to start using `@override` with all the possible signatures which does quickly become unreadable. This is kind of a contrived example though, I can't think of many situations where I'd have a function with an optional list argument that modified it. If I want an optional list argument and won't be modifying it I'd use `whatever: Sequence[T] = ()` and allow them to pass list, tuple, dict, set, whatever they want. Likewise `Mapping` instead of `dict`.
@callbettersaul8 ай бұрын
Your beloved mypy is mistaken here. Python documentation literally says this about typing.Optional: "Note that this is not the same concept as an optional argument, which is one that has a default. An optional argument with a default does not require the Optional qualifier on its type annotation just because it is optional. On the other hand, if an explicit value of None is allowed, the use of Optional is appropriate, whether the argument is optional or not." Meaning that Optional is not appropriate here as None is not actually a permitted value and is immediately replaced with an actual value. I thought it was common sense.
@Indently8 ай бұрын
But None is permitted, and the whole purpose of None is that it checks whether the user has inserted a list or not, that type annotation is appropriate. Not only is None permitted here, it's also literally the default value. I know you're quoting the docs, but the docs ( docs.python.org/3.12/library/typing.html#typing.Optional ) do not entirely line up with what you're trying to say.
@glorytoarstotzka3308 ай бұрын
I think when it comes to casting ranges/maps/filters to lists, it's important to note that it's still fine to do it for small scripts or low size things that you want to be able to print or have predictable behavior. sometimes you just wanna optimize for writing convenience and have no real consequences if it's something small scale
@SusanAmberBruce8 ай бұрын
My bad habit is I don't practice writing code often enough, even though for me python is just an interesting hobby I still find some that I'm looking on Google to remember simple examples.
@Indently8 ай бұрын
There's nothing wrong with googling no matter how simple it may be, I can do everything from scratch, but sometimes googling reminds me we have built-in functionality for what I'm about to do.
@bhai4318 ай бұрын
@@Indently *Please Make New Video On Making Telegram Bot wich work 24×7 and please must share the Script/Codes otherwise its very very difficult for us*
@oida100008 ай бұрын
The problem with many iterables is that they are one times useables and not subscriptable, range is an exception. Try this: myr=range(10) for m in myr: print(m) print(myr[3]) print(myr[6]) Try the same with map or filter, after the loop they are empty.
@callbettersaul8 ай бұрын
Have you ever needed to iterate map or filter twice? Usually they are needed only once and it would be a waste of memory to not discard them. Like when you do map(filter(...)), it would be a waste to keep filter results in memory after being already used by map.
@oida100008 ай бұрын
@@callbettersaul You would just need to keep the filter/map function in storage, plus a refrence to the **reusable** iterable - that is not that much.
@joshix8338 ай бұрын
Yes, most iterators are not re-usable, but iterables that are not iterators (like range, list, tuple) are re-usable
@atussentinel8 ай бұрын
If you want to frequently subscribe an iterable which it does not support, you are probably using a wrong data structure. Occasional doing something a data structure is not optimized for is considered ok.
@DanielOlatunde-fn3ke3 ай бұрын
On bottle for you. So simple, and understandable, I would have subscribed thousands times if possible. Always learn new thing when I watch your videos 🎉🎉
@phdnk8 ай бұрын
The Habit 2 is actually a consequence of the bad Python language design decision.
@AmitabhGhuwalewala6 ай бұрын
In my experience, depending on the object being returned by the iterator/generator, it might be more computationally efficient to actually force the evaluation of the whole iterator, thereby sacrificing memory for time efficiency. It would depend on the scenario though - obviously not recommended as a rule of thumb. Be very careful about this and document why you think you need to do this when you do need it.
@ProfRoxas8 ай бұрын
I like these examples, they can be quite common With the try-except blocks, i try to minimize the lines it has (bad habit from other languages, exceptions could use more resource than necessary) and be specific with the types, with some exception, but then I usually raise back the exception and only either print or log the exception to be verbose. Sometimes i even make custom exceptions to only catch what i really want to catch and let through what i didnt mean to catch like key or value errors The second one can be quite common, I take extra caution when i see them, because they can be simpler, but only work when the list is not modified, only checked through. One of my flying thought was to create a new variable and use the or operator to append to it (temp = targer or []), but then it would incorrectly append to the new object instead of target if target is an empty list The last example is especially useful on big data sets or even list comprehensions, because if i only need an iterable, then just by changing the [] to () makes it a memory efficient generator that won't create a temporary list (It's one of my must check thing at work, because it can be efficcient and very easy to change)
@jimstanley_493 ай бұрын
#2 isn't so much a habbit as a subtle bug to steal sanity from beginners. My favorite (related to the #3): index = range(big_iterable) for i in index: do_something(big_iterable[i]) Only wastes around 50 bytes, but not Pythonic.
@somnvm378 ай бұрын
I want to ask, is it a good practise to think of tuples as a more default way of making iterables? tuples are more efficient, and i've heard the idea that "by default, things should be immutable, unless you know you will change the data" a few times. what I mean is: is it good to write tuples every time you need a tuple/list, and only use list if it makes more sense or am I overthinking it
@edgeman11358 ай бұрын
Yeah for sure, tuples are pretty great! The changes for efficiency are quite minor when you compare it to switching data structures or straight up switching languages, but overall I'd say it's a good habit to pick up.
@jjggbbjunk8 ай бұрын
I barely know what I am doing, so I make all kinds of silly coding mistakes. Videos like these do help me, so thanks for this. Automating my powerflow studies has made me a much more efficient transmission engineer.
@krzysiekkrzysiek90598 ай бұрын
That's why I subscribe to this channel. Short, simple and very useful tips.
@ProfMonkeys8 ай бұрын
I have taken to using a slightly different variant of your proposed replacement for mutable defaults. I prefer to use the 1 liner of: target = target or [] It is certainly not perfect, but it ends up being so concise that new and old engineers alike can wrap their head around the idiom very easily. In the case where an empty list is explicitly passed in the list that gets appended to will not be the same instance as what was passed in, but if you are running into that little hole because you aren't capturing the output to a variable, then your code usually has bigger problems that should be addressed first.
@schwingedeshaehers8 ай бұрын
the problem is, that there are situations, where you get an empty list, and it expects that these 2 are the same, in the function it will use the same, but another scope may not
@ProfMonkeys8 ай бұрын
@schwingedeshaehers that is absolutely another weakness of the model I tend to use. In nearly all of the cases I have found, however, that distinction has not mattered. In the few cases I have found where I explicitly need to disambiguate between using the default value and passing in an empty object, I tend to switch to using a sentinel obnect and being verbose to make it very clear that this is a place where that distinction matters. My preferred model is not perfect, but the expediency and ease of parsing the resulting code has been serving me very well so far.
@ProfMonkeys8 ай бұрын
@schwingedeshaehers a big part of why I feel this is unambiguous is the fact that such a method allows a default value for a parameter means that the function does not promise that the original object passed in will be modified in place. If I wanted to make a function that made such a promise, I would not allow a default value and would require it to be passed in explicitly. I also generally view modifying mutable arguments in place as a practice to be avoided in most situations because it can lead to other unexpected behaviors, unless that is explicitly designed in. Either the function would modify the list in place and return nothing, or it would create a copy of the list with the appended elements and return the copy but mixing the two behaviors together is something to be avoided.
@kaltaron12847 ай бұрын
@@schwingedeshaehers You would also mask any error where your funtion recieves an unintended value that equates to false like 0.
@egoragapov20338 ай бұрын
Thank you for the video! I believe we can use 'generators' too for memory efficient reasons?
@Indently8 ай бұрын
Definitely
@Hernell128 ай бұрын
For tip 2: target = target or [] is much cleaner than the if target is None: target = []
@swolekhine8 ай бұрын
Not everyone knows about the or-shortcut you used there, so that might be a reason to prefer “if target is None”. But it is definitely a cool trick!
@antonk16208 ай бұрын
much cleaner will be if python allowed to safe init list and dicts in func params :)
@callbettersaul8 ай бұрын
As mentioned in another similar comment, if someone passes in an empty list, then your approach would replace that empty list even though None wasn't given as the argument. That can easily surprise anyone if they'd expect your function to modify their list in place.
@TheJaguar19838 ай бұрын
Funny thing about "range" is I used to use "xrange" in Python 2.7 for this exact reason.
@bart55578 ай бұрын
Great list! Curious about one thing tho. How did you add the "int()" around 1e6 so quickly? Done through a shortcut?
@TurkeyTray6 ай бұрын
highlighting text in PyCharm allows you to press an open parenthesis to enclose the entire thing in parenthesis. Then it's just as simple as pressing the left arrow twice and typing "int." As to how 1e6 was highlighted quickly, you can do ctrl + shift + arrow to highlight everything to the start/end of a word.
@CarlesMateu8 ай бұрын
Albeit, using range and similar objects is great for memory efficiency. Sometimes I feel most of us programmers, get scared by a list using 8 million bytes of memory... but that's *only* 8 Mbytes, out of the 16000 M bytes most of us have on our machines. Memory availability on modern machines has grown quite a lot, laptops with 16G are common, servers with 32, 64, and upwards are not rare things. So, sometimes, we spend too much time optimizing memory usage for things, that, in perspective, don't use so much of the available memory. That being said, in this case, the use of range vs a list is totally justified.
@saitaro8 ай бұрын
Things like `my_list: range = range(10 ** 6)` is an overuse of typing which only clogs up the code. It doesn't provide any information, since it's clear what type the variable is.
@Indently8 ай бұрын
Back then I would agree with you, but personally what is more important for me than a little bit of "clogging", is consistency. Typing 100% of my code is the approach I go for, I don't follow random rules or use special exceptions, I type everything. I constantly read in the comments that people all have their "special" typing rules, and that's great! But none of us will intuitively understand these "rules", so again, I type everything for consistency. You don't have to, but when you're teaching to millions of students, you can't always have the luxury of making up your own special case rules.
@saitaro8 ай бұрын
@@Indently I agree on consistency, though even Guido said that it is not necessary to type everything this way, nor it is theoretically possible for Python due to it's dynamic nature. The common rule is simple: type when it's not obvious right away (you suppose a list to be a list of strings) and when it will help an IDE to check and make suggestions (function signature as an example). `my_range: range = range(10)` looks redundant.
@Indently8 ай бұрын
You're not going to like my objects then xD fruit: Fruit = Fruit() I know we're in Python, and I know I make it look like Java sometimes, but I think this consistent approach will lead to far less issues than letting people decided for themselves what's obvious and what isn't. This is only keeping into account that you plan to share your code with others. If you code for yourself, and don't plan to work with others or show your code to anyone else, obvious documentation and type annotations probably will not matter.
@thomaseb978 ай бұрын
@@Indentlyyou can still be consistant while ignoring typing of certain things, i use typing alot as i feel dynamic typing was a mistake lmao, but for local variables i never use typing so i consistantly dont use typing on local variables, i always type my parameters and return, and always type my global variables/constants most modern languages also lean to this standard of typing, to not type local variables
@landsgevaer8 ай бұрын
The Zen of Python, L2: *Explicit is better than implicit*
@rolandovillcaarias51128 ай бұрын
About bad habit #1, what is the difference using multiple except for multiple exceptions vs only one line for one except and multiple exceptions? Are both same? it is just code readability?
@callbettersaul8 ай бұрын
Not at all, multiple except/catch lines are preferred in the situations where you want to customise the behaviour upon each different exception. Like maybe for ValueError you want to print out "please enter a number", but for IndexError this wouldn't make sense so you print out "incorrect number instead". The customisation is limitless. If you just want to log the error, then there's no reason to use multiple except clauses.
@hikaritsumi21236 ай бұрын
Haha I wish I could correctly handle the error from 3rd party service with no documentation As web dev it really get on my nerve when the team decide to return 400 to Frontend because the code CAN explode for basically any reason try: ...(everything) except Exception as e: return At least I return 500 to indicate that it is ME who need to correct something, and in an ideal scenario it shouldn't happen because I handle every case it could conceivebly happen in a more logical way. ..am I becoming Bob?
@DrDeuteron8 ай бұрын
Catching bare exception is so bad. I worked a 7 figure NASA project that had it, and it went south on an unseen " " (space), that was caught and ignored, and the error it cause wasn't noticed for a month. They had java programmers in charge, so there there so many python violations...it was the only PJ I ever quit in disgust in 40 years. 5 years later they are following ALL my recommendations.
@DogiMetal8 ай бұрын
Learned something new today❤❤ thank you!
@rolandovillcaarias51128 ай бұрын
Hi, for bad habit number 2, is it better to validate: "if target is None" or "if not target"?
@dragweb77258 ай бұрын
It depends if you want your function to accept other falsy values like {}, 0, (), False, "", or if you want it to type check whatever is given and raise an error or a warning when it is the wrong type. The thing is "if target is None" will only catch the None object, and "if not target" will catch any of the falsy values listed above
@Zahlenteufel18 ай бұрын
Is there any reason why the second one exists? Is there any situation where we would want the function to remember in that way? Because it seems like a problem that should be removed from Python instead of forcing us to do the None check every time.
@nahidujjamanhridoy71298 ай бұрын
which ide are you using?
@fireball541108 ай бұрын
this is pycharm
@timschulz95638 ай бұрын
6:59 But isn't the type hint wrong then? Shouldn't it be Optional[list[T]]?
@Indently8 ай бұрын
Yes it's wrong, and it's my fault for not running mypy before sharing the code with you guys.
@auroragb8 ай бұрын
youtube bad habit: have chapter sections but no meaningful title. Clearly you weren't worried about spoiling the video as the thumbnail was a great summary. But with the chapter 1/2/3, it makes it hard for viewers interested in a particular item to jump to it
@barbarosteomankosoglu66028 ай бұрын
What app is this, looks really nice
@Indently8 ай бұрын
We're in PyCharm, my friend :)
@barbarosteomankosoglu66028 ай бұрын
@@Indently Is mac and windows look different? Eventhough I have 24.1, it looks really older.
@rkdeshdeepak41318 ай бұрын
We can also use target = target or []
@emuccino8 ай бұрын
Note that there could be an unintended side affect when done this way. If an empty target list is passed as an argument, then this would replace it with a new empty list. While that probably is fine in most cases, there could be a scenario where a variable outside the scope of the function contains a reference to the original target list and will not be updated unless explicitly reassigned. Just something to keep in mind.
@maxmuster20168 ай бұрын
@@emuccino Thanks for pointing that out. A more safee one-liner would be target = [] if target is None else target. Why a one-liner? The excution is faster, because the processor can look ahead to predict the next lines of code.
@Lanxxe8 ай бұрын
@@maxmuster2016it is also kinda confusing so I would avoid that and just go for the traditional way. Furthermore, you would need to pass in None every time right
@kaltaron12847 ай бұрын
@@Lanxxe The ternary one-liner version of if takes a bit getting used to but IMHO is just as readable as a the normal version as long as all parts are short like in this case. If you can't get it on one line it's probably not a good idea but the same is true for if-statements.
@krzysiekkrzysiek90598 ай бұрын
Perfect tips 👍
@eyesburning3 ай бұрын
6:15 The type hint should now say list[T] | None = None
@ЮрийБ-о6е8 ай бұрын
I often see people using Ellipsis to define abstract method body instead of pass or NotImplemented. I guess this is weird, so use it either to show you need to code there something later or for "there could be anything" purpose. At the same time Ellipsis is ok for using inside the Protocol methods, because you're allowed to call these methods. Sry 4my Eng
@andylem8 ай бұрын
WHat editor is this?
@fireball541108 ай бұрын
pycharm
@_dzudzu_8 ай бұрын
1:28 I have to correct you! I was paid zero dollars actually. It was made for homework
@rezarg6 ай бұрын
I'm not sure if this is as bad as I think it is, but I once saw my friend coding in Python and they had "import os" in almost every function instead of just having it once at the top of the file.
@Indently6 ай бұрын
Now that's overkill xD
@-wx-78-8 ай бұрын
Reminds me of Unix ed, which respond "huh?" to any error (without "huh" part, you know ;-).
@little81388 ай бұрын
make a video for interview practice questions, It will help to so many
@bhai4318 ай бұрын
*Please Make New Video On Making Telegram Bot wich work 24×7 and please must share the Script/Codes otherwise its very very difficult for us*
@bhai4318 ай бұрын
I have need seeing your old video in this topic but unable to make from 10 days! Even the codes are not available there so I need to type all codes from your videos 😨🥲🥲🥲
@6little6fang68 ай бұрын
cool video 😎
@ЕвгенийКрасилов-о9о8 ай бұрын
target: list[T] = None... Meh... Maybe Optional[list[T]] would be better? I don't know why your type checker doesn't complain about your code example, but complains about mutable default in function signature...
@leokiller123able8 ай бұрын
This example for exception handling is not very good because in this case there is only one possible error case: ValueError, and I think in cases like this when there is only one possible exception case it is fine to use an empty except statement.
@Indently8 ай бұрын
If there's only one possible error and you know it's a ValueError, why would you catch a bare Exception instead of a ValueError? Using a bare "except" just says that there's potentially something that will go wrong, and that you have no idea what it is.
@leokiller123able8 ай бұрын
@@Indently for less verbose code, and because I don't want to catch an object that I won't use, anyway people who will read my code will see what type of exception it is just by looking at the error message (in my print statement for example)
@callbettersaul8 ай бұрын
@@leokiller123able You're not forced to catch an object. If you don't plan on using the exception object, you just write "except ValueError" and omit the "as e". And making people look through your code to try to figure out the potential exceptions is not a good idea. And it gets worse as your project's size increases.
@schwingedeshaehers8 ай бұрын
and there is at least one, probably at least 2 other errors possible
@AntonFrolov18 ай бұрын
6:34 target = target or [] is not as good as target = [] if target is None else target see the comments below
@KeithKazamaFlick8 ай бұрын
yes sir!
@rondamon44088 ай бұрын
When you said about bad habits with python I thought that you were going to show visual studio code
@aspizuwastaken8 ай бұрын
i know your watching this mcoding
@Indently8 ай бұрын
I'm a huge fan of mCoding (if you're reading this mCoding) ;)
@Nape4208 ай бұрын
Few suggestions: 1. Use the `typing.List` type annotation instead of python's `list`. It's much more flexible and linter friendly 2. If a parameter is optional (i.e. its None by default) annotate it as such with the `typing.Optional` or use the (>= 3.10) union syntax `|` (e.g. int | None )
@__mrmino__8 ай бұрын
typing.List is deprecated
@Indently8 ай бұрын
I don't understand the first suggestion, in what way is it more flexible? For the second one I messed up, and made the video without running mypy so I accept that I will get roasted for that xD
@coladock8 ай бұрын
Maybe he wants to express that sometimes List can be upcast to Sequence. My work force us pass linting and mypy. Optional is a good habits but some times return Optional may cause mypy warning make it more difficult to fix😅.
@callbettersaul8 ай бұрын
1. Built-in type hints were added in 3.9 and that's the exact reason they deprecated typing.List and others. So no, you should not use it. 2. Optional is not meant to be used with default arguments, as the value None is not actually permitted there, it's merely a placeholder value. Optional is meant to be used when the explicit value of None is allowed. It even says that in the python documentation.
@ЮрийБ-о6е8 ай бұрын
Actually, python core devs improved list to be a type annotation as well despite the fact that typing.List has already existed. So later, they did such thing with tuple. I guess there should be a good reason (imho remove useless import, i dont know). What did you mean about flexible? Sry for my Eng :)
@nickeldan8 ай бұрын
if x == True: This one makes me want to die.
@chestnutmongrel8 ай бұрын
A really bad habit to avoid is create a video with that generic naming - zero new information in five minutes, thankyouverymuch...
@Indently8 ай бұрын
You might not have noticed, but the thumbnail gives you a little *hint* about what will be in the video ;) Thank you for your constructive comment nonetheless! Have a great week :)
@marcellfarkas58898 ай бұрын
This naming convention is very common unfortunately. By the way this video was useful for me.
@callbettersaul8 ай бұрын
@@Indently Probably difficult to find it in a year tho ("I think I remember Indently making an awesome video about x, let me try finding it").
@Indently8 ай бұрын
It's time to create an add-on that allows you to save videos to your own playlist with your own names xD