WedWonder: Scripts and Modules
On Thu, Sep 12, 2019 at 7:34 AM DL Neil via Python-list
<python-list at python.org> wrote:
> On 12/09/19 8:43 AM, Chris Angelico wrote:
> > Yes, absolutely. It's the easiest way to share code between two
> > scripts. Here's an example that I created recently:
> > https://github.com/Rosuav/shed/blob/master/BL1_find_items.py
> > https://github.com/Rosuav/shed/blob/master/BL2_find_items.py
> Interestingly, we appear to have opposite approaches to this situation -
> as soon as I think the word "common" it morphs immediately into "module".
I think we actually both agree here. The only difference is that in my
view, a module that's needed by only one other script can remain as
the script it is, whereas you instantly make it *exclusively* an
importable module. BL1_find_items *is* a module as well as a script,
and it has to be implemented with that in mind.
> I have also needed to scan a directory/tree recently, but took the
> course of refactoring a previous implementation's 'directory-walk' code
> into its own (generator) function, and thus the mainline of the newer
> application calls the utility function and chooses whether or not to
> deal with each 'found' file/dir in-turn. The previous script using the
> code was similarly refactored.
> (and there are no doubt ?many more scripts 'lurking' in my code-base
> which could be similarly 'improved' - such frequent commonality leading
> to my preference).
> My bias (I'm not criticising/complaining about/decrying the choices you
> have illustrated) probably comes out of "separation of concerns". An
> issue which has 'bitten' me, more than once...
> For example both BL1 and BL2 feature:
> def money(savefile): savefile.money += 5000000 # Add more dollars
> - a minor issue, agreed (and 'picking on it' purely to make a point).
Actually no they don't, and that's part of the subtlety of working
with the two distinctly different file formats. In BL2, money is an
array (dollars, Eridium, Seraph tokens, etc), but in BL1, it's a
single value. So the BL2 version is as you posted, but the BL1 one is
def money(savefile): savefile.money += 5000000
Both files follow the same structure of synthesizers (hence the common
code in the FunctionArg class), so they will look similar, but they're
not identical enough to actually share. :(
> The "s-o-c" is, that one day it will be possible to decide that the unit
> of addition should change, but only (remember to) amend the code in one
> of the two scripts!
If I cared that the amount added be the same, then I could put that
into a constant, I guess; if anything, what I might do is parameterize
it, but it's a fairly arbitrary figure and doesn't really matter much.
> Which brings me back to the preference for 'encapsulation' (just to
> prove I can speak "OOP"), and why I would have written quite separate
> 'main-lines' and extracted money() (and presumably a lot more) into a
> module which could then be called by both.
When I started the BL1 project, I thought about sharing heaps of code
with BL2, but it just didn't work out.
> Meantime, thanks for the opportunity to review your code. I was thinking
> of considering "data classes" (new in v3.7, IIRC) in relation to an SQL
> interface on today's ToDo list - constructing the application's queries
> and the data transfers 'in' and 'out', without the 'weight' of
> SQLAlchemy. Perhaps?
Data classes are awesome. Also, this is a great demonstration of why
annotations shouldn't be restricted to any particular definition of
"type" - it's wonderfully elegant to define a data structure with
constants for signatures, types for most values, and then use
range(256) or range(65536) to mean 1-byte or 2-byte integers. Within
the context of the parser/encoder here, these things ARE types, but in
a general Python context, they aren't :)
Incidentally, data classes can be used pre-3.7 if you pip install the
backport module. So it doesn't have to be a hard requirement.