Also, do y’all call main() in the if block or do you just put the code you want to run in the if block?

    • HiddenLayer555@lemmy.mlOP
      link
      fedilink
      English
      arrow-up
      0
      ·
      edit-2
      7 days ago

      Luckily Python is one step ahead:

      Python 3.13.3 (main, Apr 22 2025, 00:00:00) [GCC 15.0.1 20250418 (Red Hat 15.0.1-0)] on linux
      Type "help", "copyright", "credits" or "license" for more information.
      >>> if __name__ = "__main__":
      ... 
      ...    main()
      ...    
          File "<python-input-0>", line 1
          if __name__ = "__main__":
              ^^^^^^^^^^^^^^^^^^^^^
      SyntaxError: invalid syntax. Maybe you meant '==' or ':=' instead of '='?
      

      Also TIL that := is a thing in Python.

  • _____@lemm.ee
    link
    fedilink
    English
    arrow-up
    0
    ·
    9 days ago

    Python people explaining fail to see the point: Yes we know dunders exist. We just want you to say: “Yeah, that is a bit hacky, isn’t it?”

    • namingthingsiseasy@programming.dev
      link
      fedilink
      arrow-up
      0
      ·
      8 days ago

      Is it? I really don’t think so. What can you propose that’s better? I think if __name__ == __main__ works perfectly fine and can’t really think of anything that would be better.

      And you don’t have to use it either if you don’t want to anyway, so no, I don’t think it’s that much of a hack. Especially when the comic compares C as an example, which makes no sense to me whatsoever.

    • Dr. Moose@lemmy.world
      link
      fedilink
      English
      arrow-up
      0
      ·
      edit-2
      8 days ago

      Tbh reserving “main” is just a hacky if not more so than checking __name__ if you actually understand language design.

      • bastion@feddit.nl
        link
        fedilink
        arrow-up
        0
        ·
        8 days ago

        Yeah, this is it.

        What’s hacky about an introspective language providing environment to all of the executing code, so that the coder can make the decision about what to do?

        It would by hacky if Python decided “We’ll arbitrarily take functions named “main” and execute them for you, even though we already started execution at the top of the file.”

        For C, this is less so. The body of the file isn’t being executed, it’s being read and compiled. Without a function to act as a starting point, it doesn’t get executed.

          • bitfucker@programming.dev
            link
            fedilink
            arrow-up
            0
            ·
            8 days ago

            I don’t understand. What do you mean by deciding what the code should do in the context of language design? Can you give a concrete example? I am confused because the “main” function is required when you make an executable. Otherwise, a library will not contain any main function and we could compile it just fine no? (Shared library)

            • _stranger_@lemmy.world
              link
              fedilink
              arrow-up
              0
              ·
              8 days ago

              Python is an interpreted language that doesn’t need a main function explicitly. You can define any package entry points you want at the package config level. (setup.py, etc)

              example: What I meant was I prefer language that treat developers like adults. If I want ptrhon’s “ux” to hide some functions or objects I can do that with underscores, but nothing is private, a developer using my library can do whatever they want with it, access whatever internals they want (at their own risk of course)

      • namingthingsiseasy@programming.dev
        link
        fedilink
        arrow-up
        0
        ·
        8 days ago

        Reserving main is definitely more hacky. Try compiling multiple objects with main defined into a single binary - it won’t go well. This can make a lot of testing libraries rather convoluted, since some want to write their own main while others want you to write it because require all kinds of macros or whatever.

        On the other hand, if __name__ == "__main__" very gracefully supports having multiple entrypoints in a single module as well as derivative libraries.

      • TheNamlessGuy@lemmy.world
        link
        fedilink
        arrow-up
        0
        ·
        7 days ago

        Both are indeed equally terrible, even if it is for different reasons.

        The one true choice is of course letting the programmer choose the main function in compile/interpretation-time.

        I.e. python main.py --start "main" would start by calling the main function in main.py

    • HiddenLayer555@lemmy.mlOP
      link
      fedilink
      English
      arrow-up
      0
      ·
      edit-2
      9 days ago

      Basically, when you compile a program written in Rust or C/C++ (the first and second panels respectively), the compiler needs to know what’s supposed to be executed first when the program is run directly (i.e. when you click on the executable), which in these languages, is denoted by a special function called main(). Executable files can also contain functions and data structures that can be called by other programs, and when they are, you wouldn’t want to run an entire complex and resource intensive program if another program only needs to call a single function from it, so in that case the other program will call the function it wants but not main, so only that function executes and not the entire program.

      However, Python is a scripting language that’s interpreted. So every Python source file is executable provided you have the Python runtime. Python also doesn’t have native support for main functions in the same way Rust and C/C++ does, and it will execute every line of code as it reads the source file. This is why a single line Python file that just calls print is valid, it doesn’t need to be wrapped in a main function to execute. However, what if your Python file is both meant to be executed directly and provides functions that other Python files can call? If you just put the main routine in the root of the file, it would be executed every time another program tries to import the file in order to call functions from it, since the import causes the file to be interpreted and executed in its entirety. You can still just have a main function in your file, but since Python doesn’t natively support it, your main function won’t do anything if you run the file directly because as far as Python is concerned, there is no executable code at the root of the file and you haven’t called any functions.

      The workaround is to have a single if statement at the root of the file that looks like this:

      if __name__ == '__main__':
          main()
      

      It checks a special variable called __name__. If the Python file is directly executed, __name__ will have the value of the string '__main__', which satisfies the if statement so main() is called. If another Python file is calling a function, the value of __name__ will be the name of that file, so main() is not called. It’s clunky and not that efficient, but, 1, it works, and 2, if you cared about efficiency, you wouldn’t be writing it in Python.

    • FooBarrington@lemmy.world
      link
      fedilink
      arrow-up
      0
      ·
      9 days ago

      Python has a bunch of magic variables, like __name__. This one contains the name of the module you’re currently in (usually based on the file name), so if your file is called foo.py, it will have the value foo.

      But that’s only if your module is being imported by another module. If it’s executed directly (e.g. python foo.py), it will instead have a __name__ of __main__. This is often used to add a standalone CLI section to modules - e.g. the module usually only defines functions that can be imported, but when executed it runs an example of those functions.

    • bastion@feddit.nl
      link
      fedilink
      arrow-up
      0
      ·
      edit-2
      8 days ago

      All code needs to have an entry point.

      For Python and some other languages, this is the start of the file.

      For other languages, this is a special function name reserved for this purpose - generally, “main”.

      In the first kind of language, the thought process is basically: I have the flow of execution, starting at the top of the file. If I want to make a library, I should build the things I want to build, then get out of the way.

      In the other kind of language, the thought process is basically: I am building a library. If I want to make an executable, I should create an entry point they the execution starts at.

      The debate is honestly pretty dumb.

      • _stranger_@lemmy.world
        link
        fedilink
        arrow-up
        0
        ·
        8 days ago

        Python doesn’t need the name main check to function at all. that’s just a convenience feature that lets developers also include arbitrary entry points into modules that are part of a library and expected to be used as such. If you’re writing a script, a file with a single line in it reading print("hello world") will work fine when run: python thescript.py

    • bastion@feddit.nl
      link
      fedilink
      arrow-up
      0
      ·
      8 days ago

      I always use

      if "__main__" == main:
          __main__()
      

      …and earlier in the code:

      def __main__():
          while True:
              pass
      main = "__main__"
      

      This helps to prevent people from arbitrarily running my code as a library or executable when I don’t went them to.

        • bastion@feddit.nl
          link
          fedilink
          arrow-up
          0
          ·
          edit-2
          8 days ago

          It simply swaps some things around to make things more confusing, then goes into an infinite loop (whether or not you import or execute it standalone). it’s no different than just including in the global scope:

          while True:
              pass
          

          I was kinda lazy with the fuckery, tbh. I could have gotten much more confusing, but don’t have too much time today. :-)

          Maybe I should do a post in programmer humor about preventing arbitrary execution of your python code, and make it sound like it prevents security flaws. …which, technically, it does - if your code isn’t executing, and instead a useless infinite loop is executing, there’s nothing to exploit.

    • wise_pancake@lemmy.ca
      link
      fedilink
      arrow-up
      0
      ·
      9 days ago

      Why would you waste a function call on something so completely redundant?

      ~For real though, arg parsing goes in the if, then gets dispatched to whatever function call is needed to run the proper script.~

    • LeninOnAPrayer@lemm.ee
      link
      fedilink
      English
      arrow-up
      0
      ·
      edit-2
      9 days ago

      If the file is just a class I usually put example usage with some default arguments in that block by itself. There is no reason for a “main” function. It’s a nice obvious block that doesn’t run when someone imports the class but if they’re looking at the class there is a really obvious place to see the class usage. No confusion about what “main()” is meant to do.

      if __name__ == '__main__':
          # MyClass example Usage
          my_object = MyClass()
          my_object.my_method()
      
        • HiddenLayer555@lemmy.mlOP
          link
          fedilink
          English
          arrow-up
          0
          ·
          edit-2
          9 days ago

          Heard of it, was too lazy to do it that way.

          To be fair I now do it that way, but not when I was learning Python.

        • grrgyle@slrpnk.net
          link
          fedilink
          arrow-up
          0
          ·
          9 days ago

          I remember how weird this looked the first time I saw it and while I may now understand it, it still looks jank af

          • frezik@midwest.social
            link
            fedilink
            arrow-up
            0
            ·
            8 days ago

            Python: I’m so readable that I’m practically executable pseudo-code

            Also Python: if __name__ == '__main__': . . .

          • Anomalocaris@lemm.ee
            link
            fedilink
            arrow-up
            0
            ·
            8 days ago

            I still wonder why.

            unless it’s for something that you want to work as an importable module and a standalone tool, then why do you need that?

            • Archr@lemmy.world
              link
              fedilink
              arrow-up
              0
              ·
              8 days ago

              The main two reasons that I can think of to include this even when you have no intention of importing this as a library are:

              1. For unit testing you will need to import as a module.
              2. Sometimes I will run a python interactive interpreter and then import my script so that I can do some manual testing without needing to change my main function or if stmt.
          • bane_killgrind@slrpnk.net
            link
            fedilink
            English
            arrow-up
            0
            ·
            9 days ago

            Now think about this, you have logic that doesn’t make sense when run directly, but you need it to be a library.

            You have multiple name=main statements in some of your functions

            • grrgyle@slrpnk.net
              link
              fedilink
              arrow-up
              0
              ·
              8 days ago

              I’m not sure I’m following the implication. Name=main is for scripts primary, is it not?

              I’ve never thought to add more than one of these conditionals anyway…

              • bane_killgrind@slrpnk.net
                link
                fedilink
                English
                arrow-up
                0
                ·
                8 days ago

                So you might have a script that does stuff as a library, and it should get environment variables and other info from the calling script. You use the same script for doing one off stuff on different computers.

                So you make it do something slightly different or make it set it’s path and look into the current folder when you run it directly. This change in logic could be in a few points in the script.

            • IronKrill@lemmy.ca
              link
              fedilink
              arrow-up
              0
              ·
              8 days ago

              And scope. Variables declared in the if can be read everywhere, variables declared in the function are limited to that function.

    • NeatNit@discuss.tchncs.de
      link
      fedilink
      arrow-up
      0
      ·
      9 days ago

      I definitely do for quick scripts, but I try to break this habit. The biggest advantage of def main() is that variables are local and not accessible to other functions defined in the same script, which can sometimes help catch bugs or typos.

    • Eager Eagle@lemmy.world
      link
      fedilink
      English
      arrow-up
      0
      ·
      edit-2
      9 days ago

      I work in an academic / research environment. Depending who wrote it, even seeing a __name__ == "__main__" is a bit of a rare thing…

      • brian@programming.dev
        link
        fedilink
        arrow-up
        0
        ·
        8 days ago

        python isn’t the only language to do “execute everything imported from a particular file and all top level statements get run”. both node and c# (but with restrictions on where top level statements can be) can do that type of thing, I’m sure there’s more.

        python conventions are unique because they attempt to make their entrypoint also importable itself without side effects. almost no one needs to do that, and I imagine the convention leaked out from the few people that did since it doesn’t hurt either.

        for instance in node this is the equivalent, even though I’ve never seen someone try before:

        if (path.resolve(url.fileURLToPath(import.meta.url)).includes(path.resolve(process.argv[1])))
        {
          // main things
        }
        
      • SpaceNoodle@lemmy.world
        link
        fedilink
        arrow-up
        0
        ·
        9 days ago

        Academic code is absolutely horrific.

        Fortunately, it is possible to translate it for practical applications.

      • ℍ𝕂-𝟞𝟝@sopuli.xyz
        link
        fedilink
        English
        arrow-up
        0
        ·
        9 days ago

        Do you also have nothing but love for those 50+ cell Jupyter notebooks that don’t use a single function and have everything in the global scope?

        • Eager Eagle@lemmy.world
          link
          fedilink
          English
          arrow-up
          0
          ·
          9 days ago

          the best thing is when not even the author knows the correct order of running the cells; because of course it isn’t top-to-bottom.

          • ℍ𝕂-𝟞𝟝@sopuli.xyz
            link
            fedilink
            English
            arrow-up
            0
            ·
            9 days ago

            Yeah, and also zero dependency management, so you are free to figure out what combination of Python, Tensorflow and Keras will make it not throw random exceptions.

            And don’t forget the number one rule: you must use all the graphing libraries, all the time.

  • Laurel Raven@lemmy.zip
    link
    fedilink
    English
    arrow-up
    0
    ·
    8 days ago

    One thing I really dislike about Python is the double underscore thing, just really looks ugly to me and feels excessive. Just give me my flow control characters that aren’t whitespace

    • atx_aquarian@lemmy.world
      link
      fedilink
      arrow-up
      0
      ·
      8 days ago

      I’m at peace with balanced underscores (like “dunder name equals dunder main”) and the internal ones for snake case, but in the unbalanced ones (prefixing unders and dunders for pseudo-private) still bug me. But at least, conventionally, it’s visually the same idea as Hungarian notation.

    • jacksilver@lemmy.world
      link
      fedilink
      arrow-up
      0
      ·
      9 days ago

      The point of the name==main logic is that it checks if that is the file that was invoked (like running python filename.py). If you just put a main() in the global scope it will be called either when the file is invoked or loaded (which can cause unintended consequences).

      • littlewonder@lemmy.world
        link
        fedilink
        arrow-up
        0
        ·
        8 days ago

        Dumb person question: if it’s good practice to do this so things don’t go sideways, shouldn’t it be a built-in feature/utility/function/whatever?

        • jacksilver@lemmy.world
          link
          fedilink
          arrow-up
          0
          ·
          edit-2
          8 days ago

          It is “built-in” as the name is part of python. However, Python runs top to bottom, rather than having a special entrypoint. So name is just a utility you can use in your design.

          While it can be a good practice to define a main entrypoint, that’s more of a design decision and not hard rule. Many applications would not benefit from it because there is only one way to actually call the application to begin with.

          Edit: Also not a dumb question. All programming languages have unique elements to them due to how they were envisioned and or developed over time (Pythons 30 years old)

  • 10001110101@lemm.ee
    link
    fedilink
    English
    arrow-up
    0
    ·
    7 days ago

    I’ve always found needing to manually add a class instance parameter (i.e. self) to every object method really weird. And the constructors being named __init__. Not having multiple dispatch is kinda annoying too. Needing to use decorators for class methods, static methods, and abstract classes is also annoying. Now that I think about it, Python kinda sucks (even though it’s the language I use the most, lol).

    • sebsch@discuss.tchncs.de
      link
      fedilink
      arrow-up
      0
      ·
      7 days ago

      Nah self is quite important. The main part of a method is to access the state of the object. self is just the interface to it.

      • 10001110101@lemm.ee
        link
        fedilink
        English
        arrow-up
        0
        ·
        7 days ago

        Guess I just prefer languages that do it this way:

        class AClass {
          var aProp = 0
        
          fun aMethod() {
            aProp++
          }
        }
        

        Though I suppose confusion and bugs can happen when you do something like:

        class AClass {
          var aProp = 0
        
          fun aMethod(aProp: Int) {
            // `this.aProp` is needed to access the property
          }
        }
        
  • Eager Eagle@lemmy.world
    link
    fedilink
    English
    arrow-up
    0
    ·
    9 days ago

    The if block is still in the global scope, so writing the code in it is a great way to find yourself scratching your head with a weird bug 30 minutes later.

  • driving_crooner@lemmy.eco.br
    link
    fedilink
    arrow-up
    0
    ·
    8 days ago

    Does everyone call the function of the script main? I never use main(), just call the function what the program is supposed to do, this program calculates the IBNR? The function is called calculate_IBNR(), then at the end of the script if name = ‘main’: calculate_IBNR(test_params) to test de script, then is imported into a tkinter script to be converter to an exe with pyinstaller

    • Whelks_chance@lemmy.world
      link
      fedilink
      arrow-up
      0
      ·
      7 days ago

      All of mine are called do_thing() because after a few days of working on it, the scope creep always means the original name was wrong anyway.