On 2022-10-10 12:40:44 +1300, dn wrote: > On 10/10/2022 05.56, Peter J. Holzer wrote: > > On 2022-10-09 12:18:09 -0400, Avi Gross wrote: > > > Some would argue for a rule related to efficiency of execution. When you > > > have multiple blocks as in an if-else or case statement with multiple > > > choices, that you order the most common cases first. Those shorten > > > execution more often than the rarer cases especially the ones that should > > > never happen. > > > > Those of us who started programming on 8 bit homecomputers of course > > have efficiency always at the back of their heads, but I find this > > ... for mainframes just as much as micro-computers!
I knew this would be coming :-). > Regarding execution-efficiencies, I'm sure @Avi knows better than I: It > seems likely that Python, as an interpreted language, will create 'blocks' > of its virtual-machine code in the same order as they appear in the > Python-source. However, aren't there optimising compilers which do something > intelligent with the equivalent clauses/suites in other languages? They can certainly move the code around. So something like if a: long block a elif b: long block b else: long block c could be compiled into (pseudo-python): if a: goto label_a elif b: goto label_b long block c goto end label_a: long block a goto end label_b: long block b end: pass If they can prove that it makes no difference they can also change the order of checking conditions: def f(a: int) -> str: if a < 0: return "negative" elif a > 100: return "big" else: return "meh" could be compiled into the equivalent of: def f(a: int) -> str: if a > 100: return "big" elif a < 0: return "negative" else: return "meh" since an int cannot be simultaneously less then 0 and larger than 100. But if the order does matter, as in def f(a: bool, b: bool) -> int: if a: return 1 elif b: return 2 else: return 3 it can't do any transformations which would change the result. (note that this is a point where it's really important what a language does or does not guarantee) > > Regardless, is a Jump-instruction which transfers else-control to a block > five machine-instructions 'down', any less efficient than a jump which spans > 50-instructions? That depends on the CPU. Some CPUs have different jump instructions for different sizes (for example, for a typical risc cpu the instruction and the offset have to fit in a 32 bit word. So you would be limited to direct jumps of plus or minus a few hundred megabytes. For longer jumps you need to load the address into a register and jump indirectly. CISC CPUs with variable length instructions may have finer distinctions.) A very short jump may continue within the same cache line or maybe even on an instruction which has already been decoded. A longer jump may have to load the next instruction from RAM. Or a jump to the beginning of a cache line may be faster than one to the middle. And then of course there is branch prediction ... So lots of variability there. > > There is of course the opposite view that you should just get all of the > > confounding factors out of the way first, so that the default is also > > the common case. I also do that sometimes, but then I don't hide this in > > in an else: clause but do something like this: > > > > for item in whatever: > > if not_this_one(item): > > continue > > if neither_this_one(item): > > continue > > if cant_continue(item): > > break > > if oopsie(): > > raise SomeError() > > > > do_something_with(item) > > and_some_more(item) > > we_are_done(item) > > > > which shows visually what the main purpose of the loop (or function or > > other block) is. > > Nicely stated! > > NB I've seen sufficient of @Peter's posts to know that this was never (even > implied to be) intended as a snippet for all occasions! > > > It also illustrates why such is less readable: because we have to scan four > if-statements before we can 'see' the purpose of the loop. My 'itch' would > be to extract this code 'out' to a function - that way the name will convey > the somewhat-obscured purpose of the loop. > > > Alternately, reduce the 'distractions':- > > try: > for item in whatever: > inspect_the_data( item ) > do_something_with(item) > and_some_more(item) > we_are_done(item) > except SomeError: > ... > except CustomBreakException: > ... ?pass? # same effect as break > > by 'hiding' in: > > def inspect_the_data( item ): > if not_this_one(item): > continue This doesn't work. You can't continue (or break) a loop in a calling function. (I think it works (or used to work) in Perl, but you'll get a warning.) You could raise CustomContinueExcection() and add a «try ... catch CustomContinueExcection: pass» block in the loop. > In some ways, (IMHO) there are reasons to feel disquiet over this style of > coding. Learning "Modular Programming", and slightly-later "Structured > Programming", when they were still new (?fresh, ?exciting), we were > inculcated with the 'one way in, one way out' philosophy-of-correctness. > This applied to "blocks" of code (per "module"), as well as formal units, eg > functions. Yeah, there is a fine line between using exceptions to hide unnecessary detail and using exceptions to make a program impenetrable. Or maybe it's not a fine line but a wide grey area? hp -- _ | Peter J. Holzer | Story must make more sense than reality. |_|_) | | | | | h...@hjp.at | -- Charles Stross, "Creative writing __/ | http://www.hjp.at/ | challenge!"
signature.asc
Description: PGP signature
-- https://mail.python.org/mailman/listinfo/python-list