1. raise NotImplementedError instead of "pass" or "..." 2. always specify return types 3. use docstrings for extra info 4. force keyword args for complex functions with *, 5. use *args to collect variable arguments
@@vamastah1737 i don't want a statically typed python. i want to force typing on input variables and return. it just makes debugging developing and documentation easier. i have used python, but only in a project for my master (i don't count the projects in which you use python to do ai or image processing and similar things, i am talking about application development). i like the language. it is easy to work with. easy to prototype. it is a great language. however the amount of times that i have suffered debugging line 1003 on a random library because i was allowed to call a function with the wrong input variables is let's say not zero. having the ability to force the type of variables in when a function expect specific function from the object in the input is a good thing, that makes the code more readable
@@hellNo116 well, true, but there are more issues like that in Python and they are solved in statically typed languages by simple syntax checking before actual run. Python got adopted to applications it was not designed in the first place and hence the issue.
@@vamastah1737i will not argue on that. it is true python was not meant to be a application language. however it happened to be because of circumstances. and it is really strong and capable. so i don't know if we can simply ignore it. also its syntax and some other feature that are inherited to the language seem to be the favorites of many python programmers. all i am trying to say is that python has legs and it is not the worst language for what we are using it for.
There's a German book called "Weniger schlecht programmieren" (How to program less badly) that has quite a few fun examples of useless comment. Not sure if there's an English version.
Since you didn't ask, here are my tips for functions: docstring for users comment for devs pass arguments as keywords (for devs--from Raymond Hettinger--If you don't know who that is, you're not a pystro) single point return for successful use-cases use guard clause to catch errors early and raise/return early minimize branches (cyclic complexity). only ONE purpose per function: break it down, use private helpers if needed) so devs never scroll to see the whole function. all functions should be PURE: if it depends on state or mutates parameters, make it a class method....and don't mutate someone else's state. only 'type(self) should mutate 'self's attributes.
disagree with the "devs shouldn't have to scroll to read the whole function". It is much better to scroll a little and read the whole function, than to jump around the file trying to find the helper function implementations. Internal functionality should only be abstracted to another function if it is going to be used more than once. If not, it just makes the code harder to read.
I'm always trying to find more "pythonic" ways to do things since behavior is different in C or Java. Even a simple for loop isn't the same in Python it's a "for each" and so much easier to use than for(i==0,i
It is not always the best idea to use a for-each approach. I developed on python for 2 years and this type of loops implies that you cannot use the full potential of a condition. For example: if you want to execute a for loop only on certain conditions you can't do that in python without declaring before or inside the loop an if statement. This could seem better in terms of readability but if you want efficient code this is not the best. I had to solve this problem with a function called takewhile that takes a predicate and the list of items, but calling a function everytime i need a value is not a good option if I already have all data
Most of the time i use an iterable instead of the *args and **kwargs thingy in those types of situations.I feel it's more readable. I used *args , **kwargs when i needed to pass a function and some of it's arguments to a class instance to execute while a method was sleeping .
@Indently Basically I would rather use "strings : typing.Iterable[str]" instead of "*strings" because it's less complicated and I think it's more readable . As for the second part of my comment I just wanted to ramble about how I last used the *args thingy .Not actually relevant to the discussion..... I automated some browser game and i wanted to be able to do thing while the program was executing a "time.sleep" . So the easiest way to do it that came to my mind was "a="spU9INjHN " . And i generate those functions this way : b="7XDxKTXWN" .Links on "onlinegdb" because i have no idea how to link stuff on yt .
It means I would rather use "strings :typing.Iterable[str]" instead of "*strings" because it is more readable in my opinion . As for the second part of my comment it's kind of irrelevant , i just wanted to talk about how i last used the feature . I automated some browser game and i wanted to do something while the code was executing a time.sleep . So i wrote this : oEOt6J0JM . And i generate the code this way az2r951Ss . The code snippet is hosted on onlinegdb , i dunno how to share links on yt.
@@IndentlyI think @hriscuvalerica4814 want to say that its more readable when a function accept a list for example instead of accepting an infinite amount of arguments because it is more explicit for the user
Good stuff. For docstring Sphinx conformant :param: or :return: statements I wouldn't just repeat the type hint you put in the def statement as it is generally redundant, and even if it wasn't the place that should go is in :type: or :rtype:. The only time you might want :type: or :rtype: there is if you want to add ",optional" just in case you didn't want to use the type hint typing.Optional[] in the def statement. Pycharm and for that matter Sphinx generated documentation picks everything up well if you have type hints in the def and ignore :type: + :rtype:. Oh, for up to date versions of Sphinx, at the end of the :param:, use for default values ", defaults to [DefaultParamVal]". The older syntax was something like (Default: ``'Default Value'``). I'm sure everyone can handle that, as we are all coping with how type hinting has changed from Python 3.6 to 3.12.
My tips for passing parameters to functions: - like you said, use type annotations - if possible avoid passing/returning dictionaries of base types. Better use classes. In most cases this means docstrongs are not really necessary because the class name should convey the meaning. In your example, it could have been an dict[Index, User] where Index and User are classes. Or even a class "UserData" wrapping the dict.
Great vid. We need a video on naming things. So different case styles for variables, function names, classes etc, to be more descriptive in the names, and just common practices for naming things. So many people name things with the wrong case, a video would help clear them up 😊
You can avoid putting what a variable is into a docstring by creating aliases for even the simplest types. You can get away with just assigning types to a variable if you are on a version of Python that doesn't support some of the newer type aliasing methods): from typing import Tuple Vec2 = Tuple[int, int] You can go a bit further and say: Xint = Yint = int Vec2 = Tuple[Xint, Yint] Why do this? Well maybe you are working with a different convention. e.g. when working with output to the terminal you often have rows as the leading axis: Loc = Tuple[Yint, Xint] Now when an argument expects a Loc, you know which way around the values inside need to be. Loc and Vec2 are the same type, but you are signalling to the reader of the code their context. And if you ever change it, there's no docstring(s) to keep up to date and you can easily find all the places in the code that the change needs to be checked (provided you named the alias sensibly).
9:14 I see no point in specifying types in docstrings when your function is already type annotated, not only is it redundant but it makes the codebase less maintainable since if the function's arguments and return types were to ever change you might fail to update the documentation
@@lydellackerman800 That's a really niche case for whoever uses the subpar docgen specifically. It's not so much to do with forgetting to update documentation but more so propagating bad practices, it's like specifying the types in documentation in a statically typed language it's just redundant, remember DRY.
I wish the ellipsis would raise NotImplementedError (the way ??? does in Scala) instead of effectively being a synonym for "pass" when outside slice context.
Why not just using a Strongly typed language like C#, Swift instead ?! these stuff are always guarantied by the compiler then, and since they are compiled they run significantly faster!
1. Disagree about pass. Using it is very helpful if you want to prepare a mocked business logics without skipping any required function which will be much more terrific if you lose something. Logic debugging sometimes very dufficult. So i would say do using pass ever. Searching by word pass is simple, but it impossible if you lose logic call because you go step by step implementation.
Nice tips. Python is comment oriented language. What I mean is code should look like comments or easily readable. Extra commenting should be less. By looking at code, you should be able to make out what is happening.
Know args typing it's NOT saving time. Exemple : you know to pass a int, but which value can have ? Absolute ? maximun ? Return type... help for IDE but... can be the same problem that args if native type (int, str, dict, etc.).
Your videos are really helpful. As you are always stressing for annotations could you point me to any video of yours where you have discussed about the annotations of async await and other complex return type and variables. If you have not talked about it a new video on it would be great
Slash means that the name of arguments after the slash don't matter. I'd use it for anywhere the names do not provide any meaning, like for example with mathematical functions: while the argument is typically named x, a, val, arg etc., this name is completely useless for the caller. exp(x=2) is much worse than simple exp(2)
I feel silly asking this, and I'm sure the answer is obvious ... but I've searched high and low and can't find the answer: How did you get your editor to show the usage count next to the function def? Also, how did you get your VSCode layout to look like this (especially the split sidebar)? I see you are using a Mac - perhaps this is the difference? I am on Windows. Grateful for your help! :)
Did you notice that in the final tip joining strings, when you printed the second tuple that the print statement displayed ('A,') and not just ('A'). It's that a potential bug?
Question why do you write users: dict[int, str] = {1: ‘bob’, 2: ‘jeff ’, 3: ‘tom’} when I think you could just write this users = {1: ‘bob’, 2: ‘jeff ’, 3: ‘tom’} I’m new to python btw
He's using type hints. Lookup explicit typing for more in depth information. But by specifying the types within this dictionary you can gain af advantages. First. The code becomes easier you read. You explicitly stated what the types of variable will be, instead of letting python infer it at runtime and thus it never being mentioned directly in your code. Second, if you were to screw up later and try to pass a string into the dictionary key, (where an int was specified) a good modern IDE should warn you about it. Potentially saving debug time later. I'm probably missing more stuff but that's what comes to mind.
Well, considering A has an invalid type annotation "dict[str: int]", I'd have to select B in this case (if you're curious about how annotations work I recommend checking out the Mypy docs for correct typing :) ).
@@Indently thx, but I'm secure af and only use 3.8 on the job. Higher version aren't approved so I can't check the newer features. Haven't had the time to get 3 on the to-be-replaced Mac at home, since my personal lib in 2x is huge.
@@Indently Well I use them in 3.8, just the nested ones aren't implemented. I think they are good if you have functiond that takes a custom class, but that really only happens when two classes are cooperating (dangers of inappropriate intimacy notwithstanding), since classes have method to work with their attributes. So far, I'm 30/70 on whether to use them with primitives.
Is there a way of declaring a type like the typedef in C ? E.g. typedef mytype1 dict[str: int]; Then you could refer to mytype1 in all relevant places...
Most of the time I get an analysis paralysis because of the docstrings. Here is a example. A function returns dict[int, str] (as in video). Why does it matter to duplicate the same ":return: dict[int, str]"? In my vision it clutters the code. Is there any value to do that duplication? Or, if function name is already self explanatory, why to paraphrase the same words which makes up the function name in the docstring?
@@Indently Sorry for using your example as my example. I understood your point about commenting. What bothers me more that I cant formulate a coherent rule of when documenting a function is redundant. Or, does it bring some kind of help somewhere I'm not aware of?
@@Mefodii Documenting a function is never redundant. Think of it that way. You have a very simple function and you think it is obvious what it does, right? Well, from experience, to some people, it really isn't that obvious and they really do need that documentation in a language they are more accustomed to (beginners, usually). It also teaches them how to start documenting their own code as they read simple functions and progress to more difficult ones. Basically, you aren't documenting a function for yourself, but for others, who might not be on your level of coding knowledge. *P.S. Documenting variables is always important, even for you. User_info might be clear enough now, but if you come back to it some time later... @param user_info: Dictionary with personal information, example (example has to be valid): { name: Tony, age: 23, address: USA} is much clearer than no info at all and a debugging session. (For other people as well!) P.S.2. This now means that you have a lot of stuff to update if you change something...so as always, its about tradeoffs. In a team, it is usually very much worth it.
What if my function does a different thing depending on the parameter type. For example open a file if the type is Path but first convert to Path if it’s a string. How would i define the parameter type then?
I recommend not doing it because you don't find it beneficial for your own purposes. Otherwise not doing something just because people recommend it is a bit silly :)
I noticed that you have a codeium AI attached, right? Does it explain 400-500 lines of code or more than that? I haven't tried it yet. And is that enough for most of the cases or other AI are better?
Type hints are just for static code analysis. If you want to perform real type checks and throw exceptions when they don't match, you have to do them yourself. Like using assertions or throwing exceptions when a type doesn't match.
Type hints are the same as comments, they do nothing when you execute the code. If you're using a powerful IDE it'll warn you when the types don't match but it will execute anyway
He didn't mean that you never implement it, just that you can have defined several empty functions, for example to name them in the main function and have a global picture of the code in it, and after you write the code of each function independently to make them reusable. It is then possible to forget implementing one of the functions in the process, it is then useful to have the code tell you that when testing
@@dragweb7725 When testing, won’t the expected value not be present because you passed the function and therefore the test would fail causing you to inspect the function causing the failed test?
@@Nerdimo it's not that easy sometimes, I've seen functions using either "pass" or "..." in an SDK of my company, which in turn uses some third party APIs, and debugging that can get hard since there are many layers and you don't know what kind of error is gonna be raised (if any).
@@juanjosefarina Aha, so it's really an issue as a code base grows larger and larger. I can see how that gets annoying. I've only used NotImplementedError for abstract classes, but I can see we're it's useful in general SWE.
1. raise NotImplementedError instead of "pass" or "..."
2. always specify return types
3. use docstrings for extra info
4. force keyword args for complex functions with *,
5. use *args to collect variable arguments
thx, saved me 15 minutes
thanks, 15 minutes saved
*1. raise NotImplementedError instead of …
*EDIT: this was fixed*
*args instead of *strings
Not all heroes wear capes
as a c/c++ enjoyer i must say that it warms my heart that specifying the return type not only is a thing, but a recommended practice
I am a C/C++ enjoyer and I do not like that. If you need a statically typed language, you should just use one instead changing Python to resemble C++.
@@vamastah1737 i don't want a statically typed python. i want to force typing on input variables and return.
it just makes debugging developing and documentation easier. i have used python, but only in a project for my master (i don't count the projects in which you use python to do ai or image processing and similar things, i am talking about application development). i like the language. it is easy to work with. easy to prototype. it is a great language. however the amount of times that i have suffered debugging line 1003 on a random library because i was allowed to call a function with the wrong input variables is let's say not zero.
having the ability to force the type of variables in when a function expect specific function from the object in the input is a good thing, that makes the code more readable
@@hellNo116 well, true, but there are more issues like that in Python and they are solved in statically typed languages by simple syntax checking before actual run.
Python got adopted to applications it was not designed in the first place and hence the issue.
@@vamastah1737i will not argue on that. it is true python was not meant to be a application language.
however it happened to be because of circumstances. and it is really strong and capable. so i don't know if we can simply ignore it. also its syntax and some other feature that are inherited to the language seem to be the favorites of many python programmers.
all i am trying to say is that python has legs and it is not the worst language for what we are using it for.
@@vamastah1737 no. Python with types is the best way to program.
raise NotImplementedError("Too drunk to think this through atm")
There's a German book called "Weniger schlecht programmieren" (How to program less badly) that has quite a few fun examples of useless comment. Not sure if there's an English version.
Real.
Since you didn't ask, here are my tips for functions:
docstring for users
comment for devs
pass arguments as keywords (for devs--from Raymond Hettinger--If you don't know who that is, you're not a pystro)
single point return for successful use-cases
use guard clause to catch errors early and raise/return early
minimize branches (cyclic complexity).
only ONE purpose per function: break it down, use private helpers if needed) so devs never scroll to see the whole function.
all functions should be PURE: if it depends on state or mutates parameters, make it a class method....and don't mutate someone else's state. only 'type(self) should mutate 'self's attributes.
disagree with the "devs shouldn't have to scroll to read the whole function". It is much better to scroll a little and read the whole function, than to jump around the file trying to find the helper function implementations. Internal functionality should only be abstracted to another function if it is going to be used more than once. If not, it just makes the code harder to read.
I'm always trying to find more "pythonic" ways to do things since behavior is different in C or Java. Even a simple for loop isn't the same in Python it's a "for each" and so much easier to use than for(i==0,i
It is not always the best idea to use a for-each approach. I developed on python for 2 years and this type of loops implies that you cannot use the full potential of a condition. For example: if you want to execute a for loop only on certain conditions you can't do that in python without declaring before or inside the loop an if statement. This could seem better in terms of readability but if you want efficient code this is not the best. I had to solve this problem with a function called takewhile that takes a predicate and the list of items, but calling a function everytime i need a value is not a good option if I already have all data
Most of the time i use an iterable instead of the *args and **kwargs thingy in those types of situations.I feel it's more readable. I used *args , **kwargs when i needed to pass a function and some of it's arguments to a class instance to execute while a method was sleeping .
Do you mind sharing a snippet here regarding what you mean? I didn't quite understand, but am curious to see what it looks like!
yes please I also curious about that thing how you use the iterable. ?
@Indently Basically I would rather use "strings : typing.Iterable[str]" instead of "*strings" because it's less complicated and I think it's more readable . As for the second part of my comment I just wanted to ramble about how I last used the *args thingy .Not actually relevant to the discussion..... I automated some browser game and i wanted to be able to do thing while the program was executing a "time.sleep" . So the easiest way to do it that came to my mind was "a="spU9INjHN " . And i generate those functions this way : b="7XDxKTXWN" .Links on "onlinegdb" because i have no idea how to link stuff on yt .
It means I would rather use "strings :typing.Iterable[str]" instead of "*strings" because it is more readable in my opinion . As for the second part of my comment it's kind of irrelevant , i just wanted to talk about how i last used the feature . I automated some browser game and i wanted to do something while the code was executing a time.sleep . So i wrote this : oEOt6J0JM . And i generate the code this way az2r951Ss . The code snippet is hosted on onlinegdb , i dunno how to share links on yt.
@@IndentlyI think @hriscuvalerica4814 want to say that its more readable when a function accept a list for example instead of accepting an infinite amount of arguments because it is more explicit for the user
Good stuff.
For docstring Sphinx conformant :param: or :return: statements I wouldn't just repeat the type hint you put in the def statement as it is generally redundant, and even if it wasn't the place that should go is in :type: or :rtype:. The only time you might want :type: or :rtype: there is if you want to add ",optional" just in case you didn't want to use the type hint typing.Optional[] in the def statement.
Pycharm and for that matter Sphinx generated documentation picks everything up well if you have type hints in the def and ignore :type: + :rtype:.
Oh, for up to date versions of Sphinx, at the end of the :param:, use for default values ", defaults to [DefaultParamVal]". The older syntax was something like (Default: ``'Default Value'``).
I'm sure everyone can handle that, as we are all coping with how type hinting has changed from Python 3.6 to 3.12.
My tips for passing parameters to functions:
- like you said, use type annotations
- if possible avoid passing/returning dictionaries of base types. Better use classes. In most cases this means docstrongs are not really necessary because the class name should convey the meaning.
In your example, it could have been an dict[Index, User] where Index and User are classes. Or even a class "UserData" wrapping the dict.
Great vid. We need a video on naming things. So different case styles for variables, function names, classes etc, to be more descriptive in the names, and just common practices for naming things. So many people name things with the wrong case, a video would help clear them up 😊
Pep8
@@replikvltyoutube3727 but so are all of his other videos. Doesnt make a difference. A video form of ideas reaches more beginners then pep8
@@replikvltyoutube3727 *a summary of PEP 8.
Finally people are realising that a proper syntax with explicit variable types, return types, etc actually makes programming easy.
Yesss, it's fundamental to add typing in Python, or as a matter of fact, in any programming language (yes including you Javascript :o)
join text function example is absolutely great. Thank you
As a beginner, this was great. Thank you.
I like to write all my functions as classes that define the call dunder; just makes it more explicit.
word
@@Indentlysentence
@@dionnixparagraph
You can avoid putting what a variable is into a docstring by creating aliases for even the simplest types. You can get away with just assigning types to a variable if you are on a version of Python that doesn't support some of the newer type aliasing methods):
from typing import Tuple
Vec2 = Tuple[int, int]
You can go a bit further and say:
Xint = Yint = int
Vec2 = Tuple[Xint, Yint]
Why do this? Well maybe you are working with a different convention. e.g. when working with output to the terminal you often have rows as the leading axis:
Loc = Tuple[Yint, Xint]
Now when an argument expects a Loc, you know which way around the values inside need to be. Loc and Vec2 are the same type, but you are signalling to the reader of the code their context.
And if you ever change it, there's no docstring(s) to keep up to date and you can easily find all the places in the code that the change needs to be checked (provided you named the alias sensibly).
9:14
I see no point in specifying types in docstrings when your function is already type annotated, not only is it redundant but it makes the codebase less maintainable since if the function's arguments and return types were to ever change you might fail to update the documentation
some documentation generators cant infer types based on hints, and you have bigger issues if you forget to update docs accordingly, in my opinion.
@@lydellackerman800 That's a really niche case for whoever uses the subpar docgen specifically.
It's not so much to do with forgetting to update documentation but more so propagating bad practices, it's like specifying the types in documentation in a statically typed language it's just redundant, remember DRY.
@@senzmakithats a fair point. I was wrong
Yeah, instead of writing ":return: bool" inside the docstring I'd rather write ":return: Whether or not the user's password is correct"
@@Nicoder6884 exactly!!!
I wish the ellipsis would raise NotImplementedError (the way ??? does in Scala) instead of effectively being a synonym for "pass" when outside slice context.
I must say I love your tutorial so many new concept I thought that never exist 👌🏽
As a data scientist, I appreciate these tips to write better code. 😅
Very helpful video. Thank you!
[ 11:04]:
Why private cat video?
Now me angry!
Me want cat!
Why not just using a Strongly typed language like C#, Swift instead ?! these stuff are always guarantied by the compiler then, and since they are compiled they run significantly faster!
1. Disagree about pass. Using it is very helpful if you want to prepare a mocked business logics without skipping any required function which will be much more terrific if you lose something. Logic debugging sometimes very dufficult. So i would say do using pass ever. Searching by word pass is simple, but it impossible if you lose logic call because you go step by step implementation.
Why not use mocks instead? That way you can separate what's ready and working and what's just for testing.
Nice tips. Python is comment oriented language. What I mean is code should look like comments or easily readable. Extra commenting should be less. By looking at code, you should be able to make out what is happening.
which is why you should never write a function that returns a complicated interface, unless it has a leading underbar in its name, and even then....
Python is executable pseudocode. Same with Haskell.
Know args typing it's NOT saving time. Exemple : you know to pass a int, but which value can have ? Absolute ? maximun ?
Return type... help for IDE but... can be the same problem that args if native type (int, str, dict, etc.).
Your videos are really helpful. As you are always stressing for annotations could you point me to any video of yours where you have discussed about the annotations of async await and other complex return type and variables. If you have not talked about it a new video on it would be great
Those were some great tips. Thanks!
What's the editor you using?
When is it a good practice to put a slash after the arguments you want to pass instead of an asterisk?
Slash means that the name of arguments after the slash don't matter. I'd use it for anywhere the names do not provide any meaning, like for example with mathematical functions: while the argument is typically named x, a, val, arg etc., this name is completely useless for the caller. exp(x=2) is much worse than simple exp(2)
Thanks, @@vytah.
Great tutorial videos. You really get me thinking. My head hurts!
Excellent! 💯
thank you so much!
I feel silly asking this, and I'm sure the answer is obvious ... but I've searched high and low and can't find the answer: How did you get your editor to show the usage count next to the function def? Also, how did you get your VSCode layout to look like this (especially the split sidebar)? I see you are using a Mac - perhaps this is the difference? I am on Windows. Grateful for your help! :)
That is not VSCode, it's PyCharm or IntelliJ Idea. I think the usages come default in that editor.
Inlay hints on PyCharm
Thanks. I found your setup video.
Very useful. Thanks!
Did you notice that in the final tip joining strings, when you printed the second tuple that the print statement displayed ('A,') and not just ('A'). It's that a potential bug?
Question why do you write users: dict[int, str] = {1: ‘bob’, 2: ‘jeff ’, 3: ‘tom’} when I think you could just write this users = {1: ‘bob’, 2: ‘jeff ’, 3: ‘tom’} I’m new to python btw
He's using type hints. Lookup explicit typing for more in depth information. But by specifying the types within this dictionary you can gain af advantages. First. The code becomes easier you read. You explicitly stated what the types of variable will be, instead of letting python infer it at runtime and thus it never being mentioned directly in your code. Second, if you were to screw up later and try to pass a string into the dictionary key, (where an int was specified) a good modern IDE should warn you about it. Potentially saving debug time later.
I'm probably missing more stuff but that's what comes to mind.
12:26 Yay
It had to be made public eventually
Good video! Thanks a lot
Excellent!
Very nice 🙂
Hi, which extension do you use in VSCode to show how many times your functions were executed?
thanks
Hello, nice video!
For the last function "joint_text", how do you type "*strings"? object , strings or maybe something in the typing library?
generally when using this you don't type annotate it, but if you want to, i guess you can just type it as typing.Tuple[str]
*strings: str (answer)
please, which extension do you use to get all this help in visual code
how to give type annotation for return self object in method?
class MyClass:
def func1(self) :
return self
def func1(self) -> MyClass:
return self
@@archardor3392 It gives not implemented error
which code do you find clearer:
A:
numbers: dict[str: int] = {'one': 1, 'two': 2}
B:
numbers = dict(one=1, two=2)
Well, considering A has an invalid type annotation "dict[str: int]", I'd have to select B in this case (if you're curious about how annotations work I recommend checking out the Mypy docs for correct typing :) ).
@@Indently thx, but I'm secure af and only use 3.8 on the job. Higher version aren't approved so I can't check the newer features. Haven't had the time to get 3 on the to-be-replaced Mac at home, since my personal lib in 2x is huge.
That's completely fair, if I had your certainty I'd probably also skip on annotations completely.
@@Indently Well I use them in 3.8, just the nested ones aren't implemented. I think they are good if you have functiond that takes a custom class, but that really only happens when two classes are cooperating (dangers of inappropriate intimacy notwithstanding), since classes have method to work with their attributes. So far, I'm 30/70 on whether to use them with primitives.
Is there a way of declaring a type like the typedef in C ?
E.g. typedef mytype1 dict[str: int];
Then you could refer to mytype1 in all relevant places...
Most of the time I get an analysis paralysis because of the docstrings.
Here is a example. A function returns dict[int, str] (as in video). Why does it matter to duplicate the same ":return: dict[int, str]"? In my vision it clutters the code. Is there any value to do that duplication?
Or, if function name is already self explanatory, why to paraphrase the same words which makes up the function name in the docstring?
What's important is that you return something meaningful. dict[int, str] might have been a bad example :)
@@Indently Sorry for using your example as my example. I understood your point about commenting.
What bothers me more that I cant formulate a coherent rule of when documenting a function is redundant. Or, does it bring some kind of help somewhere I'm not aware of?
@@Mefodii Documenting a function is never redundant. Think of it that way. You have a very simple function and you think it is obvious what it does, right? Well, from experience, to some people, it really isn't that obvious and they really do need that documentation in a language they are more accustomed to (beginners, usually). It also teaches them how to start documenting their own code as they read simple functions and progress to more difficult ones. Basically, you aren't documenting a function for yourself, but for others, who might not be on your level of coding knowledge.
*P.S. Documenting variables is always important, even for you.
User_info might be clear enough now, but if you come back to it some time later...
@param user_info: Dictionary with personal information, example (example has to be valid):
{ name: Tony,
age: 23,
address: USA}
is much clearer than no info at all and a debugging session. (For other people as well!)
P.S.2. This now means that you have a lot of stuff to update if you change something...so as always, its about tradeoffs. In a team, it is usually very much worth it.
What if my function does a different thing depending on the parameter type. For example open a file if the type is Path but first convert to Path if it’s a string. How would i define the parameter type then?
You should use abstract method and ABC instead of NotImplementedErrors.
Would be nice, but that's only valid if you're using an OOP approach.
Nice
How do you typehint the *strings parameter in the final tip ?
I will not do dot the return type thing, regardless how 'useful' people say it is
I recommend not doing it because you don't find it beneficial for your own purposes. Otherwise not doing something just because people recommend it is a bit silly :)
🔥
for the last one, I think I prefer the code:
>>>join_text = str.join
it's more pythonic, since functions are 1st class, and: don't reinvent the wheel.
That's absolutely fair, but as usual, my example was just for demonstration purposes.
I noticed that you have a codeium AI attached, right?
Does it explain 400-500 lines of code or more than that?
I haven't tried it yet.
And is that enough for most of the cases or other AI are better?
Can someone explain this:
>>> def p(*v: str, s: int):
... print(s.join(v))
...
>>> p("a", "5", s='/')
a/5
Why isn’t the type int for s enforced?
It's type hints
Just hints, they do not provide any contact over the actual variable type
Type hints are just for static code analysis. If you want to perform real type checks and throw exceptions when they don't match, you have to do them yourself. Like using assertions or throwing exceptions when a type doesn't match.
Type hints are the same as comments, they do nothing when you execute the code.
If you're using a powerful IDE it'll warn you when the types don't match but it will execute anyway
If you pass a function and never implement it, did you even need it in the first place?
He didn't mean that you never implement it, just that you can have defined several empty functions, for example to name them in the main function and have a global picture of the code in it, and after you write the code of each function independently to make them reusable. It is then possible to forget implementing one of the functions in the process, it is then useful to have the code tell you that when testing
@@dragweb7725 When testing, won’t the expected value not be present because you passed the function and therefore the test would fail causing you to inspect the function causing the failed test?
@@Nerdimo it's not that easy sometimes, I've seen functions using either "pass" or "..." in an SDK of my company, which in turn uses some third party APIs, and debugging that can get hard since there are many layers and you don't know what kind of error is gonna be raised (if any).
@@juanjosefarina Aha, so it's really an issue as a code base grows larger and larger. I can see how that gets annoying. I've only used NotImplementedError for abstract classes, but I can see we're it's useful in general SWE.
How many vs code python extension? I like comment 1 usage.
I'm learning English. I'd like to know where are you or where come from your accent. Please.
Thanks a lot.
His UA-cam profile says he's from Denmark if that helps
🥇🎉🎉🎉
Can you explain the **kwargs thing?
kwargs allows you to pass a variable number of arguments that you haven't explicitly defined in your code yet
*args get transformed into tuples, **kwargs into a dict. As per usual you aren't allowed to use positional arguments after keyword arguments.
Which IDE is being used here?
Pycharm
What's this color scheme?
"pro tip" comes across as bring the exact opposite.
what does it mean?
What ide is that
Pycharm
#1 Ctrl f pass later if this becomes an issue for you
where was all that hiding from me all the time?
You can write much better python functions using C/C++.
Thank you.
not none but NoReturn if no retyrning