How To Write Better Functions In Python

Поделиться
HTML-код
  • Опубликовано: 21 дек 2024

Комментарии • 89

  • @Titouan_Jaussan
    @Titouan_Jaussan 3 месяца назад +110

    I was wondering, Could you make some sort of code review type videos ? I know it probably takes more time but at the same time you could also explain a lot of other stuff, like how to handle big sized projects, how to make code more professional on a larger scale ... This could really be cool I think

  • @JeffreyLiss0
    @JeffreyLiss0 3 месяца назад +56

    Eschewing long function names simply makes naming much harder. You end up having to make important distinctions with fewer words, so grammar comes into play. This function, for example, should be named get_discounted_total or get_discounted_price, because that's what it's returning -- not the sum of all discounts to be applied to a product. Playing grammar nazi with code is nobody's idea of a good time, and it's particularly difficult on teams where people have different native languages. Better to make your peace with longer names, especially since any IDE worth the name will offer to autocomplete it for you.

    • @kellymoses8566
      @kellymoses8566 2 месяца назад +4

      I agree. With modern IDEs there isn't a lot of drawback for long function names.

    • @Just.Be.Kind.please
      @Just.Be.Kind.please 2 месяца назад +1

      While I’m opining from a position of extreme novice in coding, I have absolutely noticed myself using more detail/length in my function names when needed. This helps me and my neurodivergence keep things understandable when going back to review or continue working on a project.
      I imagine it would be just as helpful, if not more, for a group/team.

  • @drew.esbssy
    @drew.esbssy 3 месяца назад +22

    I like how I came to watch the video thinking it would just be normal stuff i would already know and ended up learning how to create function documentations

    • @olivergrim7634
      @olivergrim7634 3 месяца назад

      i was disappointed the way i expected to, i knew all of this :c

  • @dingaroo2003
    @dingaroo2003 24 дня назад

    Been programming with Python for 6 years, but after going through your video, I am hoping to elevate my Python skills!

  • @Marc-ElianBegin
    @Marc-ElianBegin Месяц назад +1

    Thanks for the video. There are several standards for documentation. Making a review of those with its pros and cons would be nice.

  • @Heavy_Lvy
    @Heavy_Lvy 3 месяца назад +3

    3:23 this is commonly referred to as Dependency Injection (DI)

  • @frozendude707
    @frozendude707 2 месяца назад +1

    7:23 I'm gonna do a sad frikkin "errm, actually" here, so technically it should drop an exception or segfault if the locale is missing or corrupt, in which case you could return a generic time format like %H:%M:%S (there seems to be no built-in support for standard ISO 8601 formats).

  • @amitshogun
    @amitshogun 3 месяца назад +5

    This function has two responsibilities. Sum and percentage discount. Better to split / extract to 2 simple generic functions and create another one that combines both. Better code reuse.
    And what about validating percentage value?
    Thank you

    • @ziul123
      @ziul123 3 месяца назад

      there is already a generic function for sum: the sum function. It is also faster, because it's implemented in C. The function he wrote already combines both functionalities. There is no need to write a separate one liner function to apply a percentage, it is literally just a multiplication

    • @nuynobi
      @nuynobi 2 месяца назад

      ​@@ziul123 True, but his point still stands. Why pass in a list of prices when you could simply pass in the total already summed? And it should be called something like apply_discount(price, rate).

  • @marcof1430
    @marcof1430 3 месяца назад +5

    I think documentation has a double side: useful but terrible if it's not updated. And it's easy to forget to update, even in the video the documentation needed to be updated. I prefer comments in the hard parts so I understand what the programmer wanted to achieve or do..

    • @nuynobi
      @nuynobi 2 месяца назад +2

      Valid point about documentation needing to be maintained. That's an argument for keeping docstrings simple and concise (unlike in this video), _not_ and argument for not using them at all. Comments and documentation have different purposes. Both are useful and should be employed where appropriate. The convention is that docstrings explain the _what_ while comments explain the _how._

  • @spreadneck2063
    @spreadneck2063 Месяц назад +1

    So you can use : instead of = when defining a variable?

    • @lewie8136
      @lewie8136 20 дней назад

      name: str = ‘bob’
      Variable: type = value
      : allows you to assign the type

  • @Greenbay-bn3yk
    @Greenbay-bn3yk 3 месяца назад +2

    I learnt a lot of Python techniques from this channel. Thanks Mr. Indently 🙂

  • @uruloki
    @uruloki 3 месяца назад +5

    Shouldn’t the discount function be renamed to totalAfterDiscount?

    • @michaelhoffmann2891
      @michaelhoffmann2891 3 месяца назад +1

      totalAfterCalculatedDiscountWithLocalisationAndRebates(), which is overridden in DiscountAndRebateCalculationInstantiationFactory.
      Java.............. 🙄
      But in case, you were serious: Java uses camel case, Python uses snake case. If one of my peers uses the former format in the latter language, I will not approve their PR. I see that a lot among more junior, fresh-out-of-uni coders.

    • @uruloki
      @uruloki 3 месяца назад +1

      @@michaelhoffmann2891 Case is usually shop specific. Good on you for enforcing your standard!

    • @michaelhoffmann2891
      @michaelhoffmann2891 3 месяца назад +1

      @@uruloki True, but I would look *very* askance at a shop that dictated camel case for Python in defiance of PEP.

  • @ArtyomKatsap
    @ArtyomKatsap 3 месяца назад +3

    Why do you need to specify the type of the "now" variable? Even in static type language lile c++ you can write "auto" and let the compiler figure out the variable type. Here - almost any IDE will know that the returned value is "datetime" and will give you same intellisense support without the surplus verbosity.

    • @gJonii
      @gJonii 3 месяца назад

      Compiler wouldn't warn you if the function would start, after some modification, returning strings. If you write it explicitly, then you get proper warning if you modify something and the return type is wrong.

    • @ArtyomKatsap
      @ArtyomKatsap 3 месяца назад

      In this case, either the rest of the code will be compatible with the new type which means the new type has the same protocol or is a subclass of datetyme type, or the intellisense will alert me of incorrect/incompatible usage.

    • @gJonii
      @gJonii 3 месяца назад +2

      ​@@ArtyomKatsapActually, yeah, you're right. I thought you talked about function signatures somehow, but yeah, the variable typing is imo kinda pointless there, the datetime.now() is already a typed function.
      If you were to reassign "now", it would make more sense to type it, but here, it seems purely fluff.

    • @Jason-b9t
      @Jason-b9t 3 месяца назад

      @@gJonii In most cases you do not need to type the variable type. (I wouldn't do it either.)
      But typing variable type is sometimes helpful, like the following code:
      from datetime import datetime
      now = datetime.now()
      today = datetime.date(now) # Get today's date
      if today == now:
      print('today is now')
      else:
      print('today is not now') # Print this line because the type of "now" is different from the type of "today".
      If you type variable type it is easier to understand the type of the variable.

    • @Jason-b9t
      @Jason-b9t 3 месяца назад

      ​@@gJonii If you type variable type it is easier to understand the type of the variable.
      now = datetime.now()
      isoNow = datetime.isoformat(now)
      print(f'{now=}, {isoNow=}')
      if isoNow == now:
      print('isoNow is now')
      else:
      print('isoNow is not now') # Print this line because the type of "isoNow" is different from the type of "now".
      But I usually don't type variable type because it's very troublesome.

  • @popovanatoliy4736
    @popovanatoliy4736 2 месяца назад

    05:46 i'm not sure it's pep but probably you write dosrctring in a wrong way. it starts with a verb. like "get current time" instead of "a function that returns you a current time".

  • @mattinm
    @mattinm 20 дней назад

    The overall idea of this is great, but the example has issues.
    1. You use Iterable, but you iterate over it twice, which is unsafe, because an Iterator, which can only be looped once is also an Iterable.
    2. You declare float as the sub-type for prices, but check for int or float later. Just use SupportsFloat as the hint instead and explicitly cast later, e.g. via map(float, prices). This will also have the benefit of doing the type validation for you and raise if needed, instead of even needing to call isinstance.

  • @lvidarte
    @lvidarte 3 месяца назад +2

    I don't like get methods in Python but I like everything else in the video

    • @MrMaxtng
      @MrMaxtng 3 месяца назад +1

      Its a convention, not a real getter as per Java or similar. You could call a function that calculates coefficients for a neural network get_coefficients. Why do you care?

  • @bismarkosei9656
    @bismarkosei9656 3 месяца назад

    I would also recommend that you make the validation as function.

  • @DuncanBooth
    @DuncanBooth 3 месяца назад +11

    I don't like it when people duplicate the parameter types in the docstring. You have the type clearly specified in the function signature so no need to repeat it. (And if you're using tools to process the docstring that don't use the function signature types get better tools.)

    • @nuynobi
      @nuynobi 2 месяца назад +1

      Amen. It's redundant. And then you need to remember to update it in both places if something changes. DRY.

  • @Desafecto
    @Desafecto Месяц назад

    I would suggest adding one last step: a test for the function. 😊

  • @capnmark4
    @capnmark4 3 месяца назад

    Good tips for any programming language!

  • @baptisteb8910
    @baptisteb8910 3 месяца назад +1

    For the function name I would say:
    1. As short as possible, but as long as needed.
    And if the name is too long, then the function might need to be divided.
    Otherwise LGTM !

  • @cerealport2726
    @cerealport2726 3 месяца назад

    If i put all my functions in 1 file, and the "executable" code in another, is there some general guideline for where I should put fixed variables? like, if i call them in the "executable" file, then put them there, otherwise, put in the function file...?

    • @samagraarohan2513
      @samagraarohan2513 3 месяца назад +4

      put them where they are gonna be used most, and where it makes sense for them to exist

    • @ffggvfg4323
      @ffggvfg4323 3 месяца назад +1

      Putting all your functions in one file makes your code hard to read and makes debugging a pain. If your code is clogged up with util functions then putting those in a file can be ok as far as variables please on behalf of everyone that will read your code define them in the main file

    • @DrDeuteron
      @DrDeuteron 3 месяца назад +1

      but the point of dunder name == dunder main is that you don't need to separate the code like that, unless another script also needs the function--but then you're writing a package.
      "fixed variables" is just not pythonic..."module constants" go after imports, before def's.

    • @gJonii
      @gJonii 3 месяца назад +1

      I'd put all the code in one file, until you identify some island of functionality that you can separate into its own file with a smaller API.

  • @angelou8633
    @angelou8633 Месяц назад

    can you do some tutorial in dart/flutter?

  • @divyakumar8147
    @divyakumar8147 Месяц назад

    thanks

  • @martinmaher8129
    @martinmaher8129 3 месяца назад

    Beautiful!

  • @TheBlueboyRuhan
    @TheBlueboyRuhan 3 месяца назад +4

    my money don't jiggle jiggle, it folds

  • @farzadmf
    @farzadmf 3 месяца назад

    Seems like :type ...: doc is not reflected in the popup (I mean it doesn't mention anything about the type of the params)

  • @BouncingCow
    @BouncingCow 3 месяца назад

    how would I handle a function if I return several value? would I do that as a list and - - > list[Str, into, df. Dataframe()] for example?

    • @michaelhoffmann2891
      @michaelhoffmann2891 3 месяца назад

      tuples! Or a dict.

    • @tw11tube
      @tw11tube Месяц назад +1

      Especially if it's part of a library API, use a NamedTuple or dataclass, so the callers can access members by name.

  • @ferroalloys594
    @ferroalloys594 2 месяца назад

    Only ever abstract over an EXPRESSION, whatever it's arguments...! Simples (:-)

  • @smanzoli
    @smanzoli 3 месяца назад +1

    The first example was not a good choice (ok, it's an example only), because as a rule, we should NEVER write a function which only purpose is call another function.
    get_time() is completelly useless since we can simply use directly datetime.now()
    Also, inside the useless function, we create a useless variable now, where we could return datetime.now() directly.
    Second example is very good.
    Great video!

  • @TellyT-i5e
    @TellyT-i5e 3 месяца назад +1

    Redundant docs just clutter up the code unless you are making a library api

  • @markdillon9588
    @markdillon9588 3 месяца назад

    Brilliant:)

  • @danielrhouck
    @danielrhouck 2 месяца назад +2

    I think you took the short function names too far. Based on the name `get_time`, I expect the *time* and not a string. I’d do `get_time_locale` or something, even with the return type.

  • @DrDeuteron
    @DrDeuteron 3 месяца назад

    also and/or emphasis on what you did:
    1) one point of return (if you must have branches)
    2) don't have branches (except for guard clauses)
    3) Use guard clauses: raise exceptions early.
    Most important:
    Be pure:
    No side-effects. Don't modify arguments! e.g.:
    >>>sorted(list_)
    returns a sorted list w/o modifying the argument. Modify objects only in their one methods:
    >>>list_.sort()
    and don't have a state: same arguments means same result (rand and date time notwithstanding).

  • @jervinevangelista7615
    @jervinevangelista7615 3 месяца назад

    what vs code extensions are you using? thanks

  • @xXherbal1stXx
    @xXherbal1stXx 3 месяца назад

    about the type annotations;
    i think they're use- and surely helpful BUT, for me as a not very experienced coder who's still figuring out how to do stuff the best way and which techniques are available, and whilst discovering new modules and their functionalities, it can be somewhat distracting to already start using type annotations as much as possible, so my take at it is to use them as long as it stays simple, so to at least get used to them for now and to have a base to build up on later, specially once my scripts start to become bigger. same for docstrings btw..

  • @justliberty4072
    @justliberty4072 15 дней назад

    I don't like calling fractions "percents"; that is a source of self-documenting error or ambiguity.

  • @dadogwitdabignose
    @dadogwitdabignose 3 месяца назад

    Which IDE are you using?

  • @curtisharwood6626
    @curtisharwood6626 Месяц назад +1

    your first tip of not naming things thoroughly is definitely just an opinion, and arguably a bad one.

  • @GreyHatGenX
    @GreyHatGenX 2 месяца назад

    comment

  • @vadimkorniychuk665
    @vadimkorniychuk665 3 месяца назад

    Error handling is ok basically, but your example so overloaded

  • @JohnUrbanic-m3q
    @JohnUrbanic-m3q 3 месяца назад +6

    Use Python because it it quick and pithy. Once you start adding in this pseudo-typing, error handling and extensive documentation you lose that, and it is a sign that you should be choosing a different language. Right tool for the job.

    • @michealakinkuotu8637
      @michealakinkuotu8637 3 месяца назад +20

      This is not true. Documentation and error handling is a crucial part of any software, whether it's statically typed or dynamically typed.

    • @DrDeuteron
      @DrDeuteron 3 месяца назад +1

      @@michealakinkuotu8637 but LBYL type checking?

    • @michealakinkuotu8637
      @michealakinkuotu8637 3 месяца назад

      @@DrDeuteron Look before you leap is not left out of the discussion in terms of error handling. While LBYL can be redundant or expensive in terms of performance, it doesn't nullify the fact that if done correctly, it gives you a "safer code" and in some cases, a much cleaner or clearer error handling through provision of meaningful feedback.

    • @DrDeuteron
      @DrDeuteron 3 месяца назад

      @@michealakinkuotu8637 I get the POV, but that gets back to OP's point: this is python: Lighten up!
      The only place I allow branchy code is in error handling. When everything is working, I want minimal cyclomatic complexity.

    • @DrDeuteron
      @DrDeuteron 3 месяца назад +2

      I do find the excessive hints annoying, the worst is type hinting strongly typed magic methods, like:
      init(self) -> None:
      str(self) -> str:
      I just can't....

  • @smanzoli
    @smanzoli 3 месяца назад

    The G you pronounce at the end of words (due to accent) is easy to fix... it's silent, simply do not say it! And bingo, your pronounce will get even better!

    • @creed404yt9
      @creed404yt9 2 месяца назад

      I can't hear the G you talked about?

  • @gregd1218
    @gregd1218 3 месяца назад

    If your functions is simple enough and had a proper name, a documentation is not needed. Besides keeping documentation up to date double your work load (rewrite the doc, update the example,... every time you refactor) Most IDE can infer input and output so that's a complete waste of time. Documentation is only useful in a library and only for exposed methods.

  • @baptisteb8910
    @baptisteb8910 3 месяца назад +10

    For the function name I would say:
    1. As short as possible, but as long as needed.
    And if the name is too long, then the function might need to be divided.
    Otherwise LGTM !

    • @michaelhoffmann2891
      @michaelhoffmann2891 3 месяца назад +1

      I agree. If my func/method is getting to be more than a screen (and I use a big screen) or around 50 lines (incl copious whitespace), I refactor. Even if it's a helper method used once, with a leading '_' ( to make it "Python Private(tm)").