Re: Friday Finking: Source code organisation
On 3/01/20 7:36 AM, Terry Reedy wrote: On 1/2/2020 2:46 AM, Cameron Simpson wrote: Inline code under the if...__main__ stuff cannot be called as a function; Which makes it difficult to test app startup. I usually consider the main() function a reusable component. Which, if called (at least optionally) with a list of string arguments (sys.argv) as Cameron suggested, makes it easy to test with various lists of strings. NB I agree with suggestion that 'important stuff' is better placed at 'top' of source-code. Preceding comment assumes that main() is to be a word/name which catches the eye and has 'importance' attached. However, the Python idiom is "if __name__ == '__main__'" and (paradoxically?) that usually goes at the 'bottom'. I think we've previously discussed if __name__ == '__main__' and/vs main(). Continuing the discussion, above:- def start_up( args ): etc def do_it( args ): etc def close_down( args ): etc if __name__ == '__main__': start_up( sys.argv ) do_it( etc ) close_down( etc ) 1. app startup remains test-able 2. each component is reusable 3. sys.argv may be passed with all flexibility 4. separation of concerns, etc, observed NB above for casual illustration only - if start_up() is more than trivial, seems likely that others would be better implemented as context manager, etc, etc... -- Regards =dn -- https://mail.python.org/mailman/listinfo/python-list
Re: Friday Finking: Source code organisation
On 1/2/2020 2:46 AM, Cameron Simpson wrote: Inline code under the if...__main__ stuff cannot be called as a function; Which makes it difficult to test app startup. I usually consider the main() function a reusable component. Which, if called (at least optionally) with a list of string arguments (sys.argv) as Cameron suggested, makes it easy to test with various lists of strings. -- Terry Jan Reedy -- https://mail.python.org/mailman/listinfo/python-list
Re: Friday Finking: Source code organisation
On 02Jan2020 18:01, DL Neil wrote: On 29/12/19 5:49 PM, Cameron Simpson wrote: For main, i have the opposite habit. If a module has a main() function for command line use I usually want that right up the front: #!/usr/bin/env python3 import... def main(argv=None): ... main command line ... classes, functions, etc if __name__ == '__main__': sys.exit(main(sys.argv)) My reasoning here is that I want the main programme obvious up front. But then I loosely follow "define before use" after that. OK, I'll bite: 1 the reader (one assumes) starts at the top, then scrolls all the way to the bottom to find if...__main___, but is then directed to search for the def main... which is all the way back up to the top! If they scrolled, they'd have seen the main() function. I consider it akin to the opening comment/docstring: I want the reader to know pretty immediately that this has a meaningful command line mode. 2 if instead of a main(), that code was under if ... __main__ would that be an equally reasonable and "obvious" place to find it? Well... Inline code under the if...__main__ stuff cannot be called as a function; I usually consider the main() function a reusable component. The boilerplate under if...__main__ at the bottom is just the call to it for when the module is used with "python -m". But main itself is standalone. So it won't be under the if...__main__; the only real discussion is where to put it. Cheers, Cameron Simpson -- https://mail.python.org/mailman/listinfo/python-list
Re: Friday Finking: Source code organisation
On 29/12/19 5:49 PM, Cameron Simpson wrote: On 29Dec2019 09:49, Chris Angelico wrote: "Define before use" is a broad principle that I try to follow, even when the code itself doesn't mandate this. This generally means that "if name is main" is the very last thing in the file, and if there's a main() function or equivalent, that's usually just before that. Any metaprogramming goes right at the top; sometimes this is mandated (if I write a decorator function, it has to be above the functions it's decorating), but even if it's not, metaprogramming goes before the mainline. For main, i have the opposite habit. If a module has a main() function for command line use I usually want that right up the front: #!/usr/bin/env python3 import... def main(argv=None): ... main command line ... classes, functions, etc if __name__ == '__main__': sys.exit(main(sys.argv)) My reasoning here is that I want the main programme obvious up front. But then I loosely follow "define before use" after that. OK, I'll bite: 1 the reader (one assumes) starts at the top, then scrolls all the way to the bottom to find if...__main___, but is then directed to search for the def main... which is all the way back up to the top! 2 if instead of a main(), that code was under if ... __main__ would that be an equally reasonable and "obvious" place to find it? -- Regards =dn -- https://mail.python.org/mailman/listinfo/python-list
Re: Friday Finking: Source code organisation
On 31/12/19 3:47 am, Barry Scott wrote: "define before use" is basically email top-posting for code isn't it? It means that the first things that you read in a module are the least interesting. That's not a big problem for top-level code, since you can easily scroll down to the bottom of the file and work backwards. But it's not so easy for classes if you have more than one class in a file. That might be part of the reason I do things the opposite way in classes. -- Greg -- https://mail.python.org/mailman/listinfo/python-list
Re: Friday Finking: Source code organisation
> On 30 Dec 2019, at 15:35, Chris Angelico wrote: > > On Tue, Dec 31, 2019 at 1:47 AM Barry Scott wrote: >> >> >> >>> On 28 Dec 2019, at 22:49, Chris Angelico wrote: >>> >>> On Sun, Dec 29, 2019 at 9:37 AM DL Neil via Python-list >>> wrote: Is it helpful to, and thus, do you have a style/convention for ordering the methods within each class in your code? A major difference however, is that if our mythical collection of module-functions has an internal-reference, eg b() requires a(), then function a() MUST exist, ie be defined, 'before' function b(). Whereas a class's methods may be defined in any (complete) sequence. So, do you have an orderly method [hah!] for presenting/locating class-methods (and module-functions) within your code? - why bother, the editor does 'the heavy lifting' - dunders to the fore - alphanumeric sequence by name - order of appearance/use in 'mainline code' - as they sprang to mind during TDD-creation - most-used first, least-used last - my code 'at the top', their stuff later... - names of Monty Python characters by TV appearance date or, - some combination of ideas and, - how do you vary the above when dependencies intrude? >>> >>> "Define before use" is a broad principle that I try to follow, even >>> when the code itself doesn't mandate this. This generally means that >>> "if name is main" is the very last thing in the file, and if there's a >>> main() function or equivalent, that's usually just before that. Any >>> metaprogramming goes right at the top; sometimes this is mandated (if >>> I write a decorator function, it has to be above the functions it's >>> decorating), but even if it's not, metaprogramming goes before the >>> mainline. >> >> >> >> "define before use" is basically email top-posting for code isn't it? > > Kinda the opposite - it means that you get the context before you get > something that refers to it. But its not context its the low level detail that I should be able to ignore when trying to understand the goals of the code. I'll only need to know about the lower level detail if I have a need to change the code. Another analogy would ne how a journalist writes a story. You can take a well written article and stop reading at any point, but still know what the story is about. The more paragraphs you read the more informed you are about the story. (Editors exploit this property of a story to shorten it if it does not fit on the page). Barry > > ChrisA > -- > https://mail.python.org/mailman/listinfo/python-list > -- https://mail.python.org/mailman/listinfo/python-list
Re: Friday Finking: Source code organisation
On Tue, Dec 31, 2019 at 3:08 AM Barry Scott wrote: > > > > > On 30 Dec 2019, at 15:35, Chris Angelico wrote: > > > > On Tue, Dec 31, 2019 at 1:47 AM Barry Scott wrote: > >> > >> > >> > >>> On 28 Dec 2019, at 22:49, Chris Angelico wrote: > >>> > >>> On Sun, Dec 29, 2019 at 9:37 AM DL Neil via Python-list > >>> wrote: > > Is it helpful to, and thus, do you have a style/convention for ordering > the methods within each class in your code? > > A major difference however, is that if our mythical collection of > module-functions has an internal-reference, eg b() requires a(), then > function a() MUST exist, ie be defined, 'before' function b(). Whereas a > class's methods may be defined in any (complete) sequence. > > So, do you have an orderly method [hah!] for presenting/locating > class-methods (and module-functions) within your code? > > - why bother, the editor does 'the heavy lifting' > - dunders to the fore > - alphanumeric sequence by name > - order of appearance/use in 'mainline code' > - as they sprang to mind during TDD-creation > - most-used first, least-used last > - my code 'at the top', their stuff later... > - names of Monty Python characters by TV appearance date > or, > - some combination of ideas > and, > - how do you vary the above when dependencies intrude? > > >>> > >>> "Define before use" is a broad principle that I try to follow, even > >>> when the code itself doesn't mandate this. This generally means that > >>> "if name is main" is the very last thing in the file, and if there's a > >>> main() function or equivalent, that's usually just before that. Any > >>> metaprogramming goes right at the top; sometimes this is mandated (if > >>> I write a decorator function, it has to be above the functions it's > >>> decorating), but even if it's not, metaprogramming goes before the > >>> mainline. > >> > >> > >> > >> "define before use" is basically email top-posting for code isn't it? > > > > Kinda the opposite - it means that you get the context before you get > > something that refers to it. > > But its not context its the low level detail that I should be able to ignore > when trying to understand the goals of the code. I'll only need to know > about the lower level detail if I have a need to change the code. > > Another analogy would ne how a journalist writes a story. You can take > a well written article and stop reading at any point, but still know what > the story is about. The more paragraphs you read the more informed > you are about the story. (Editors exploit this property of a story to shorten > it if it does not fit on the page). > Sure, but that's not what top-posting in emails is like. With a top-posted reply, truncation means you lack context; with the journalistic style of "front-load the important info", truncation means you lack detail. So in coding, I would say the journalistic style corresponds to a broad notion of "first docstring, then main function, then support code", which is an absolutely legit way to do things (but not my preferred way). ChrisA -- https://mail.python.org/mailman/listinfo/python-list
Re: Friday Finking: Source code organisation
On Tue, Dec 31, 2019 at 1:47 AM Barry Scott wrote: > > > > > On 28 Dec 2019, at 22:49, Chris Angelico wrote: > > > > On Sun, Dec 29, 2019 at 9:37 AM DL Neil via Python-list > > wrote: > >> > >> Is it helpful to, and thus, do you have a style/convention for ordering > >> the methods within each class in your code? > >> > >> A major difference however, is that if our mythical collection of > >> module-functions has an internal-reference, eg b() requires a(), then > >> function a() MUST exist, ie be defined, 'before' function b(). Whereas a > >> class's methods may be defined in any (complete) sequence. > >> > >> So, do you have an orderly method [hah!] for presenting/locating > >> class-methods (and module-functions) within your code? > >> > >> - why bother, the editor does 'the heavy lifting' > >> - dunders to the fore > >> - alphanumeric sequence by name > >> - order of appearance/use in 'mainline code' > >> - as they sprang to mind during TDD-creation > >> - most-used first, least-used last > >> - my code 'at the top', their stuff later... > >> - names of Monty Python characters by TV appearance date > >> or, > >> - some combination of ideas > >> and, > >> - how do you vary the above when dependencies intrude? > >> > > > > "Define before use" is a broad principle that I try to follow, even > > when the code itself doesn't mandate this. This generally means that > > "if name is main" is the very last thing in the file, and if there's a > > main() function or equivalent, that's usually just before that. Any > > metaprogramming goes right at the top; sometimes this is mandated (if > > I write a decorator function, it has to be above the functions it's > > decorating), but even if it's not, metaprogramming goes before the > > mainline. > > > > "define before use" is basically email top-posting for code isn't it? Kinda the opposite - it means that you get the context before you get something that refers to it. ChrisA -- https://mail.python.org/mailman/listinfo/python-list
Re: Friday Finking: Source code organisation
> On 28 Dec 2019, at 22:49, Chris Angelico wrote: > > On Sun, Dec 29, 2019 at 9:37 AM DL Neil via Python-list > wrote: >> >> Is it helpful to, and thus, do you have a style/convention for ordering >> the methods within each class in your code? >> >> A major difference however, is that if our mythical collection of >> module-functions has an internal-reference, eg b() requires a(), then >> function a() MUST exist, ie be defined, 'before' function b(). Whereas a >> class's methods may be defined in any (complete) sequence. >> >> So, do you have an orderly method [hah!] for presenting/locating >> class-methods (and module-functions) within your code? >> >> - why bother, the editor does 'the heavy lifting' >> - dunders to the fore >> - alphanumeric sequence by name >> - order of appearance/use in 'mainline code' >> - as they sprang to mind during TDD-creation >> - most-used first, least-used last >> - my code 'at the top', their stuff later... >> - names of Monty Python characters by TV appearance date >> or, >> - some combination of ideas >> and, >> - how do you vary the above when dependencies intrude? >> > > "Define before use" is a broad principle that I try to follow, even > when the code itself doesn't mandate this. This generally means that > "if name is main" is the very last thing in the file, and if there's a > main() function or equivalent, that's usually just before that. Any > metaprogramming goes right at the top; sometimes this is mandated (if > I write a decorator function, it has to be above the functions it's > decorating), but even if it's not, metaprogramming goes before the > mainline. "define before use" is basically email top-posting for code isn't it? It means that the first things that you read in a module are the least interesting. I prefer to follow the a top-down design approach. Start with what is important and put what that depends on further down the file/class. With classes, __init__, __new__ then the public API and last the supporting code. Barry > > Other than that, I don't have any consistent logic other than a loose > idea of trying to keep related things together. > > ChrisA > -- > https://mail.python.org/mailman/listinfo/python-list > -- https://mail.python.org/mailman/listinfo/python-list
Re: Friday Finking: Source code organisation
On 28Dec2019 19:19, Tim Chase wrote: Inside a class, I tend to roughly follow __new__ (if present) __init__ other dunder methods subsequent methods alphabetically I put the factory methods up near __init__, ahead of other methods. But after most dunders. Here I mean things like this: class Foo: def __init__(): @classmethod def from_bytes(cls, bs, ...): ... parse out of `bs` and then finish with something like ... return cls(parsed-stuff) which calls the "conventional" __init__ as normal. And I often group methods of similar purpose together, rather than alphabetically. For example, if there's a few methods for transribing the object, they might land together. Cheers, Cameron Simpson -- https://mail.python.org/mailman/listinfo/python-list
Re: Friday Finking: Source code organisation
On 29Dec2019 09:49, Chris Angelico wrote: "Define before use" is a broad principle that I try to follow, even when the code itself doesn't mandate this. This generally means that "if name is main" is the very last thing in the file, and if there's a main() function or equivalent, that's usually just before that. Any metaprogramming goes right at the top; sometimes this is mandated (if I write a decorator function, it has to be above the functions it's decorating), but even if it's not, metaprogramming goes before the mainline. For main, i have the opposite habit. If a module has a main() function for command line use I usually want that right up the front: #!/usr/bin/env python3 import... def main(argv=None): ... main command line ... classes, functions, etc if __name__ == '__main__': sys.exit(main(sys.argv)) My reasoning here is that I want the main programme obvious up front. But then I loosely follow "define before use" after that. Cheers, Cameron Simpson -- https://mail.python.org/mailman/listinfo/python-list
Re: Friday Finking: Source code organisation
On 29/12/19 2:19 PM, Tim Chase wrote: On 2019-12-29 12:52, Greg Ewing wrote: I tend to do this too, although it's probably just a habit carried over from languages such as Pascal and C where you have to go out of your way to get things in a different order. Apparently I'm not alone in my Pascal/C-derived habits of define-before-use. I didn't expect to be the only one who would bring 'prior experience' into it... Inside a class, I tend to roughly follow __new__ (if present) __init__ other dunder methods subsequent methods alphabetically +1 Should __new__() and __init__() break with convention because its/their method/function signature is (really) part of the class's signature, and thus there's a need for proximity? (aka is "expected") -- Regards =dn -- https://mail.python.org/mailman/listinfo/python-list
Re: Friday Finking: Source code organisation
"Define before use" is a broad principle that I try to follow, even when the code itself doesn't mandate this. IMO it makes the code easier to navigate even when it's not strictly necessary. As others have said, Python mandates that the functions be defined before they're CALLED, but I find that it's worth being stricter. As a general rule, any global name in my code (that includes constants, module-level functions, etc, etc) will have its definition as the textually-first instance of that name. Or, at worst, the first instance will be a comment immediately above the definition. ('Anonymised' because this is not 'aimed' at any particular individual) I was somewhat amused at being 'corrected' in the "defined" cf "called" discussion. The 'corrections' are more precise. However such distinctions are machine-related, ie how does the Python interpreter behave? The central topic of this (ideally, thought-provoking) discussion, is on the person (not the machine). Yes, the author. Although, if you subscribe to the philosophy that program(me)s should be written with human-readers in-mind, then the likes of "beauty is in the eye of the beholder" and "readability counts", apply! Various 'gurus', probably even before the Agile/Gang-of-Four/OOP, have talked of code craftsmanship having a number of characteristics. One of which is that *my* code should appear pretty-much as *you* expect the solution. When we were asked to discuss this, over-the-teacups (on Friday, hence the "FF" moniker) the young fellow's question was phrased "what do you guys expect [from me]". (yes, he was quoting/abstracting from 'Uncle Bob' and "Clean Code" [Prentice-Hall, 2009]). We have a number of 'what do you expect'-s in Python. For example, there is no "law" saying that we must use "self" within classes. Other languages use similar but alternate terminology, eg "this". I could decide to use "dn_was_here" and the interpreter will be perfectly happy - but because you don't expect it and would be made to (unnecessarily) comprehend, I doubt it would promote our friendship/mutual-respect! So, do you hold any 'expectation' relating to the organisation of class methods? -- Regards =dn -- https://mail.python.org/mailman/listinfo/python-list
Re: Friday Finking: Source code organisation
On 2019-12-29 12:52, Greg Ewing wrote: > On 29/12/19 11:49 am, Chris Angelico wrote: > > "Define before use" is a broad principle that I try to follow, > > even when the code itself doesn't mandate this. > > I tend to do this too, although it's probably just a habit > carried over from languages such as Pascal and C where you > have to go out of your way to get things in a different > order. Apparently I'm not alone in my Pascal/C-derived habits of define-before-use. Inside a class, I tend to roughly follow __new__ (if present) __init__ other dunder methods subsequent methods alphabetically -tkc -- https://mail.python.org/mailman/listinfo/python-list
Re: Friday Finking: Source code organisation
On 12/28/19 6:52 PM, Greg Ewing wrote: > On 29/12/19 11:49 am, Chris Angelico wrote: >> "Define before use" is a broad principle that I try to follow, even >> when the code itself doesn't mandate this. > But strangely, I tend to do the opposite for methods of a class. I > don't really know why. My instinctive idea of the "right" ordering > just seems to flip over somehow between modules and classes. Me, too. :-/ Could be one of two reasons: (1) putting the public API at the top and pushing the internal/helper functions towards the bottom (whether program, library, or class); or (2) writing too much FORTRAN and/or BASIC early on, where execution begins at the top, whether you want it to or not Who puts a class's __init__ function anywhere except the very top of a class definition (doc strings and class attributes that aren't "def"ed notwithstanding), even when it calls some other method in the class? Dan -- https://mail.python.org/mailman/listinfo/python-list
Re: Friday Finking: Source code organisation
On Sun, Dec 29, 2019 at 10:56 AM Greg Ewing wrote: > > On 29/12/19 11:49 am, Chris Angelico wrote: > > "Define before use" is a broad principle that I try to follow, even > > when the code itself doesn't mandate this. > > I tend to do this too, although it's probably just a habit > carried over from languages such as Pascal and C where you > have to go out of your way to get things in a different > order. IMO it makes the code easier to navigate even when it's not strictly necessary. As others have said, Python mandates that the functions be defined before they're CALLED, but I find that it's worth being stricter. As a general rule, any global name in my code (that includes constants, module-level functions, etc, etc) will have its definition as the textually-first instance of that name. Or, at worst, the first instance will be a comment immediately above the definition. > But strangely, I tend to do the opposite for methods of > a class. I don't really know why. My instinctive idea of > the "right" ordering just seems to flip over somehow > between modules and classes. That's curious. I have a similar sort of inversion in that __init__ is usually going to be up the top (even though main() would be at the bottom), although not a complete inversion: anything that __init__ calls will still go above it. ChrisA -- https://mail.python.org/mailman/listinfo/python-list
Re: Friday Finking: Source code organisation
On 29/12/19 11:49 am, Chris Angelico wrote: "Define before use" is a broad principle that I try to follow, even when the code itself doesn't mandate this. I tend to do this too, although it's probably just a habit carried over from languages such as Pascal and C where you have to go out of your way to get things in a different order. But strangely, I tend to do the opposite for methods of a class. I don't really know why. My instinctive idea of the "right" ordering just seems to flip over somehow between modules and classes. -- Greg -- https://mail.python.org/mailman/listinfo/python-list
Re: Friday Finking: Source code organisation
On 29/12/19 11:35 am, DL Neil wrote: if our mythical collection of module-functions has an internal-reference, eg b() requires a(), then function a() MUST exist, ie be defined, 'before' function b(). Not true in Python -- a() must exist by the time b() is run, but they can be written in the file in either order, -- Greg -- https://mail.python.org/mailman/listinfo/python-list
Re: Friday Finking: Source code organisation
On 12/28/19 5:35 PM, DL Neil via Python-list wrote: Is it helpful to, and thus, do you have a style/convention for ordering the methods within each class in your code? Python's "honking great idea" of namespaces enables us to gather functions/methods under a single name-umbrella, thereby avoiding name-clashes/name-space 'pollution'. [Oh yeah!] Thus, if we collect a bunch of module-functions, we refer to them collectively by module-name/import-name, eg import collected_functions_module as cfm ... cfm.make_it_happen() cfm.make_it_better() Similarly, methods within a class may be accessed either as class-methods, or through instances (as required). [am assuming no code example necessary] A major difference however, is that if our mythical collection of module-functions has an internal-reference, eg b() requires a(), then function a() MUST exist, ie be defined, 'before' function b(). Whereas a class's methods may be defined in any (complete) sequence. If module function b calls function a in the same module, then a has to exist when b is CALLED, not before it is defined. Thus it is very possible to get a multi-function recursion where b() calls a() which then calls b(). (The existence of items mentioned within a function are looked up until that statement as actually executed) as an example, in a module: def b(): a() def a(): pass is perfectly valid. Modules are a bit different, if module b needs resources from module a, it needs to import module a before it can use them. If module a also needs resources from module b, and imports it, then stuff from b might not be available while doing the running of module a that is defining the items in a. -- Richard Damon -- https://mail.python.org/mailman/listinfo/python-list
Re: Friday Finking: Source code organisation
On Sun, Dec 29, 2019 at 9:37 AM DL Neil via Python-list wrote: > > Is it helpful to, and thus, do you have a style/convention for ordering > the methods within each class in your code? > > A major difference however, is that if our mythical collection of > module-functions has an internal-reference, eg b() requires a(), then > function a() MUST exist, ie be defined, 'before' function b(). Whereas a > class's methods may be defined in any (complete) sequence. > > So, do you have an orderly method [hah!] for presenting/locating > class-methods (and module-functions) within your code? > > - why bother, the editor does 'the heavy lifting' > - dunders to the fore > - alphanumeric sequence by name > - order of appearance/use in 'mainline code' > - as they sprang to mind during TDD-creation > - most-used first, least-used last > - my code 'at the top', their stuff later... > - names of Monty Python characters by TV appearance date > or, > - some combination of ideas > and, > - how do you vary the above when dependencies intrude? > "Define before use" is a broad principle that I try to follow, even when the code itself doesn't mandate this. This generally means that "if name is main" is the very last thing in the file, and if there's a main() function or equivalent, that's usually just before that. Any metaprogramming goes right at the top; sometimes this is mandated (if I write a decorator function, it has to be above the functions it's decorating), but even if it's not, metaprogramming goes before the mainline. Other than that, I don't have any consistent logic other than a loose idea of trying to keep related things together. ChrisA -- https://mail.python.org/mailman/listinfo/python-list