On 16/04/20 1:55 AM, dcwhat...@gmail.com wrote:
As much as possible, I make use of optional type hints.  So if I know a 
function returns an integer, then I use
this_number_i : int = GetThisNumber()
But there's no 'file' type, so I'm not sure what to use as the type for the 
return value of an Open() function.
config_file : file = open(config_file_s, "r")
What type of variable should config_file (above) be declared as?


First point (at the risk of teaching you/Grandma how to suck eggs) is that Python is a "dynamically-typed" language. Thus we may write:
        
        a = "abc"

in one place, and:

        a = 123

in another.

Python won't complain. However, such code is a recipe for confusing people - if not yourself, more 'simple' colleagues, such as me; because we get used to the idea of "a" as a string of characters, only to be presented with a number/int. What???

Thus the 'virtue' of typed languages, and adding data-typing features into one's code!


It is important to remember that the Python docs (see refs, below) refer to data-typing as "Hints". Indeed Python itself pays little/no attention:

>>> i:int=6
>>> j:int="str"
>>> i
6
>>> j
'str'

Since when has the string of characters: "str" been an integer???

To make good use of typing hints requires a bolt-on checker such as "mypy". Quoting, the release notes for Python 3.5:
<<<
While these annotations are available at run-time through the usual __annotations__ attribute, no automatic type checking happens at run-time. Instead, it is assumed that a separate off-line type checker (e.g. mypy) will be used for on-demand source code analysis.
>>>

(most IDEs will offer a mechanism to automatically run this, along with linters, test-runners, etc, every time a source-file is saved)


Coming from other languages, there is a tendency to see typing as at least helpful, even when it's not 'required'. Similarly, some languages/conventions encourage the use of prefixes or suffixes in naming variables, to help one remember the data-type. These are habits that are difficult to break - and indeed, it is arguable whether breaking them entirely would make one a 'better programmer'! (IMHO)


Python prefers to be descriptive, and in making a variable's name meaningful, to imply or to 'carry' well-rounded and sufficient information. Choosing names is an under-rated skill, and difficult to master. (again, IMHO)

Now, because you (as above) "know a function returns an integer", Python does too! However, if you (so kindly) save me hours of work by offering this function to me, what do I know about it? The answer is that I look at the function's "signature".

If we totally eschew data-typing it might be:

        def find_sentence_length( sentence ):
                etc

We can guess the data-type of "sentence" and that of the value to be returned, but (a) it's a "guess", (b) we have to invest extra effort, and (c) we might guess wrong[ly]! (although such might/should be included in the function's docstring!)

You (as I) probably prefer:

        def find_sentence_length( sentence:str )->int:
                etc

This is readily-understood to describe the taking 'in' of a string of characters, and the subsequent return of an integer. No muss, no fuss!

Subsequently:

        sentence_length = find_sentence_length( my_sentence )

tells both Python and me (and any typing checker), that sentence_length is an integer.

That said, there is still room for misunderstanding. Guessing again?


Even with such a contrived and simplistic example, there is room for confusion: is that "length" measured in characters, inches/millimeters, pixels, or what?

So, typing (or strongly-typed languages) is/are not the be-all-and-end-all, nor does it offer a 'silver bullet'!

Before anyone asks: when I use "sentence_lengthPX" it produces howls of complaint from certain ('pythonic') colleagues - notice though, that its purpose is clear!


My opinion/coding-habits may differ from others (surely (and sadly) it is 'they' who differ from me!). For each class I like to 'define' most/all of its data-attributes in the __init__(), and to add typing information to those definitions - with additional supportive comment, as appropriate. This is mostly a bid to carry-forward as much information as possible from the design-docs. (also, if the class contains 'state' information, it seems to make it easier to write and generalise __str__() and any other 'general' routines across states. YMMV!)

NB I'm not arguing with @Chris - I wouldn't dare!

I don't see this as an extension of the class's signature - it won't be read because it's not needed if we treat the class as a 'black box'. Conversely, it *is* a useful reminder/initiation to my/someone else's comprehension of the inner-workings of the class itself!


Another thought, relating to the (above) specific example of "config_file : file = open(config_file_s, "r")", is that once-again, the 'pythonic' approach leads one into a different way of thinking (if we let ourselves 'go with the flow').

The preferred method of dealing with files, (somewhat newer than illustrations in many text-books) is to use a "Context Manager", eg

        with open(config_file_s, "r") as configurations:
            for configuration in configurations:
                # bend it to your will

Note the absence of any try...except structure, which we would normally use to ensure the file is (eventually) closed and garbage-collection assured! These offer a powerful implementation (actually, a "protocol").

Thus, "configurations" is (still) a "file descriptor" (fd), but its definition now appears on the right of the open() (ie the open function-call), because it is part of a "with" (compound) statement. Auto-magically, "configurations" will only exist within the "context" of the "with"!

The "with" opens a code-block ("wraps" is the docs' terminology). The code block/compound[ed] statements (presumably) contain everything needed to operate on that file's content, eg read a config setting, update the app's environment class/dict/constant, log the specification, etc. Hence the terms "context" and "encapsulation".

The fd only exists (its "scope") 'within' and for the 'life' of this block. If this code-block is kept short - as it should be (fitting on one screen is a popular definition for max-"short") then you/I/we can easily track "configurations" during its short, but very-necessary, life - and being a 'bear of little brain', if/when I forget, the reminder is still right there on-screen if I but lift mine eyes! So, using data-typing seems of little benefit (although it is still possible!)

NB clearly this is an argument from cognitive psychology rather than computer science!


To generalise that point: if one practices 'modular coding', "separation of concerns", and related philosophies (in recognition of how encapsulation helps cognition); then considerately-thoughtful function/method signatures combined with (short) single-objective code-modules, enable one to comprehend and remember (all?most) data-type information, as part of understanding the context and purpose of each unit of code. ("chunking")


Speaking personally, it took me a long time to get used to such ideas as "dynamic typing" and to focus on what I gained (cf what I 'lost'). Some might argue that I'm still adapting! However, the 'golden rule' (whether considering programming languages or human languages!) is not to try to bend/fold/spindle/mutilate one language, to make it look/sound like another! It's always worth asking the meta-level question: why am I wanting to (try to) do this, this way? Aka: is there a better way?


Web-Refs:
PEP 483 -- The Theory of Type Hints: https://www.python.org/dev/peps/pep-0483/
PEP 484 -- Type Hints: https://www.python.org/dev/peps/pep-0484/
New in Python 3.5: https://docs.python.org/3/whatsnew/3.5.html
Typing: https://docs.python.org/3/library/typing.html?highlight=pep%20typing
Using "with": https://docs.python.org/3/reference/compound_stmts.html?highlight=context%20manager#the-with-statement Typing context managers: https://docs.python.org/3/library/typing.html?highlight=context%20manager#typing.ContextManager Using context managers: https://jeffknupp.com/blog/2016/03/07/python-with-context-managers/
--
Regards =dn
--
https://mail.python.org/mailman/listinfo/python-list

Reply via email to