• Re: Evaluate once or every time

    From Chris Angelico@21:1/5 to avi.e.gross@gmail.com on Sat Feb 25 09:38:13 2023
    On Sat, 25 Feb 2023 at 09:36, <avi.e.gross@gmail.com> wrote:
    From what you say, concatenation between visibly adjacent strings is done once when generating bytecode. Using a plus is supposed to be about the same but may indeed result in either an error if you use anything other than a string literal

    bad = "hello " str(12)

    or you must use something like a "+" to do the concatenation at each run time. Or, weirder, do it manually as :


    Abuttal is a syntactic feature. It's completely different from string concatenation. The only similarity is that some forms of addition may
    be constant-folded.

    ChrisA

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From avi.e.gross@gmail.com@21:1/5 to avi.e.gross@gmail.com on Fri Feb 24 17:35:06 2023
    Mark,

    I was very interested in the point you made and have never thought much about string concatenation this way but adjacency is an operator worth using.

    This message has a new subject line as it is not about line continuation or comments.

    From what you say, concatenation between visibly adjacent strings is done once when generating bytecode. Using a plus is supposed to be about the same but may indeed result in either an error if you use anything other than a string literal

    bad = "hello " str(12)

    or you must use something like a "+" to do the concatenation at each run time. Or, weirder, do it manually as :

    good = "hello ".__add__(str(12))

    This may be no big deal in terms of efficiency but something to consider.

    I have often stared in amazement at code like:

    mylist = "The quick brown fox jumps over the lazy dog".split()

    mylist
    ['The', 'quick', 'brown', 'fox', 'jumps', 'over', 'the', 'lazy', 'dog']

    Or perhaps to make a list of vowels:

    import string

    vowels = list("aeiouAEIOU")
    consonants = sorted(list(set(string.ascii_letters) - set(vowels)))

    I mean couldn't you do this work in advance and do something like:

    vowels = ['A', 'E', 'I', 'O', 'U', 'a', 'e', 'i', 'o', 'u']
    consonants = ['B', 'C', 'D', 'F', 'G', 'H', 'J', 'K', 'L', 'M', 'N', 'P', 'Q', 'R', 'S', 'T', 'V', 'W', 'X', 'Y', 'Z', 'b', 'c', 'd', 'f', 'g', 'h', 'j', 'k', 'l', 'm', 'n', 'p', 'q', 'r', 's', 't', 'v', 'w', 'x', 'y', 'z']

    I assume this latter version would be set once no matter how often you run the unchanged program. YES, I am aware this may be bad practice for code you want to adapt for international use.

    But why be wasteful? I am currently reading a book on refactoring and will not share if it is illustrated, or if the above is a decent example as the book uses examples in JavaScript. 😉



    -----Original Message-----
    From: Python-list <python-list-bounces+avi.e.gross=gmail.com@python.org> On Behalf Of Mark Bourne
    Sent: Friday, February 24, 2023 4:04 PM
    To: python-list@python.org
    Subject: Re: Line continuation and comments

    Personally, I don't particularly like the way you have to put multiline strings on the far left (rather than aligned with the rest of the scope) to avoid getting spaces at the beginning of each line. I find it makes it more difficult to see where the
    scope of the class/method/etc.
    actually ends, especially if there are multiple such strings. It's not too bad for strings defined at the module level (outer scope) though, and of course for docstrings the extra spaces at the beginning of each line don't matter.

    However, rather than using "+" to join strings as in your examples (which, as you suggest, is probably less efficient), I tend to use string literal concatenation which I gather is more efficient (treated as a single string at compile-time rather than
    joining separate strings at run-time). See <https://docs.python.org/3/reference/lexical_analysis.html#string-literal-concatenation>.

    For example:
    HelpText = ("Left click: Open spam\n"
    "Shift + Left click: Cook spam\n"
    "Right click: Crack egg\n"
    "Shift + Right click: Fry egg\n")

    The downside is having to put an explicit "\n" at the end of each line, but to me that's not as bad as having to align the content to the far left.

    Getting a bit more on topic, use of backslashes in strings is a bit different to backslashes for line continuation anyway. You could almost think of "\ (newline)" in a multiline string as being like an escape sequence meaning "don't actually put a
    newline character in the string here", in a similar way to "\n" meaning "put a newline character here" and "\t"
    meaning "put a tab character here".

    Mark.


    avi.e.gross@gmail.com wrote:
    Good example, Rob, of how some people make what I consider RELIGIOUS edicts that one can easily violate if one wishes and it makes lots of sense in your example.

    Let me extend that. The goal was to store a character string consisting of multiple lines when printed that are all left-aligned. Had you written:

    HelpText = """
    Left click: Open spam
    ...
    Shift + Right click: Fry egg
    """
    Then it would begin with an extra carriage return you did not want. Your example also ends with a carriage return because you closed the quotes on another line, so a \ on the last line of text (or moving the quotes to the end of the line) would be a
    way of avoiding that.

    Consider some alternatives I have seen that are in a sense ugly and may involve extra work for the interpreter unless it is byte compiled once.

    def someFunc():
    HelpText =
    "Left click: Open spam" + "\n" +
    "Shift + Left click: Cook spam" + "\n" +
    ...

    Or the variant of:
    HelpText = "Left click: Open spam\n"
    HelpText += " Shift + Left click: Cook spam\n"
    ...

    Or perhaps just dumping the multi-line text into a file beforehand and reading that into a string!

    def someFunc():

    The backslash is not looking like such a bad idea! LOL!

    -----Original Message-----
    From: Python-list
    <python-list-bounces+avi.e.gross=gmail.com@python.org> On Behalf Of
    Rob Cliffe via Python-list
    Sent: Wednesday, February 22, 2023 2:08 PM
    To: python-list@python.org
    Subject: Re: Line continuation and comments



    On 22/02/2023 15:23, Paul Bryan wrote:
    Adding to this, there should be no reason now in recent versions of
    Python to ever use line continuation. Black goes so far as to state
    "backslashes are bad and should never be used":

    https://black.readthedocs.io/en/stable/the_black_code_style/future_st
    y le.html#using-backslashes-for-with-statements

    def someFunc():
    HelpText = """\
    Left click: Open spam
    Shift + Left click: Cook spam
    Right click: Crack egg
    Shift + Right click: Fry egg
    """

    The initial backslash aligns the first line with the others (in a fixed font of course).
    Best wishes
    Rob Cliffe
    --
    https://mail.python.org/mailman/listinfo/python-list

    --
    https://mail.python.org/mailman/listinfo/python-list

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Thomas Passin@21:1/5 to avi.e.gross@gmail.com on Fri Feb 24 18:42:39 2023
    On 2/24/2023 5:35 PM, avi.e.gross@gmail.com wrote:
    Mark,

    I was very interested in the point you made and have never thought much about string concatenation this way but adjacency is an operator worth using.

    This message has a new subject line as it is not about line continuation or comments.

    From what you say, concatenation between visibly adjacent strings is done once when generating bytecode. Using a plus is supposed to be about the same but may indeed result in either an error if you use anything other than a string literal

    bad = "hello " str(12)

    or you must use something like a "+" to do the concatenation at each run time. Or, weirder, do it manually as :

    good = "hello ".__add__(str(12))

    This may be no big deal in terms of efficiency but something to consider.

    I have often stared in amazement at code like:

    mylist = "The quick brown fox jumps over the lazy dog".split()

    mylist
    ['The', 'quick', 'brown', 'fox', 'jumps', 'over', 'the', 'lazy', 'dog']

    Why be amazed? The .split() version is way easier to type. I do it all
    the time. Usually these evaluations will be done only once, at compile
    time, so the cost in computing time is usually not important. And, if
    you get right down to it, the first form is actually what you mean. The
    second form is an implementation detail (you need to feed a list of
    words into a function).

    Or perhaps to make a list of vowels:

    import string

    vowels = list("aeiouAEIOU")
    consonants = sorted(list(set(string.ascii_letters) - set(vowels)))

    I mean couldn't you do this work in advance and do something like:

    vowels = ['A', 'E', 'I', 'O', 'U', 'a', 'e', 'i', 'o', 'u']
    consonants = ['B', 'C', 'D', 'F', 'G', 'H', 'J', 'K', 'L', 'M', 'N', 'P', 'Q', 'R', 'S', 'T', 'V', 'W', 'X', 'Y', 'Z', 'b', 'c', 'd', 'f', 'g', 'h', 'j', 'k', 'l', 'm', 'n', 'p', 'q', 'r', 's', 't', 'v', 'w', 'x', 'y', 'z']

    I don't want to have to type these monsters, and in this form I'd be
    prone to making an error. And they are hard to proofread. Anyway, a
    list like this is typically used to assess whether a character is in one
    or the other group, and you can do it without turning the string into a
    list of characters:

    VOWELS = 'aeiouAEIOU'
    is_vowel = 'y' in VOWELS

    If I really needed them to be in a list, I'd probably do a list
    comprehension:

    VOWEL_LIST = [ch for ch in VOWELS]

    Again, much easier to type and to read, closer to what is really meant,
    and less error-prone.

    In the case of the consonants, even in string form it would be hard to proofread, so I'd be inclined to insert spaces for readability:

    CONSONANTS = 'BCDFGH JKLMNP QRSTVWX YZ bcdfgh jklmnp qrstvwx yz'

    If for some reason spaces wouldn't work, I'd delete them:
    CONSONANTS = CONSONANTS.replace(' ', '')

    In concept this isn't much different from using the C pre-processor to pre-compute some things for you.


    I assume this latter version would be set once no matter how often you run the unchanged program. YES, I am aware this may be bad practice for code you want to adapt for international use.

    But why be wasteful? I am currently reading a book on refactoring and will not share if it is illustrated, or if the above is a decent example as the book uses examples in JavaScript. 😉

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From 2QdxY4RzWzUUiLuE@potatochowder.com@21:1/5 to Thomas Passin on Fri Feb 24 19:00:17 2023
    On 2023-02-24 at 18:42:39 -0500,
    Thomas Passin <list1@tompassin.net> wrote:

    VOWELS = 'aeiouAEIOU'
    is_vowel = 'y' in VOWELS

    If I really needed them to be in a list, I'd probably do a list comprehension:

    VOWEL_LIST = [ch for ch in VOWELS]

    Why use a comprehension when a simple loop will do? ;-)

    No. Wait. That's not what I meant.

    Why use a comprehension when the constructor will do?

    VOWEL_LIST = list(VOWELS)

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Thomas Passin@21:1/5 to 2QdxY4RzWzUUiLuE@potatochowder.com on Fri Feb 24 20:36:53 2023
    On 2/24/2023 7:00 PM, 2QdxY4RzWzUUiLuE@potatochowder.com wrote:
    On 2023-02-24 at 18:42:39 -0500,
    Thomas Passin <list1@tompassin.net> wrote:

    VOWELS = 'aeiouAEIOU'
    is_vowel = 'y' in VOWELS

    If I really needed them to be in a list, I'd probably do a list
    comprehension:

    VOWEL_LIST = [ch for ch in VOWELS]

    Why use a comprehension when a simple loop will do? ;-)

    No. Wait. That's not what I meant.

    Why use a comprehension when the constructor will do?

    VOWEL_LIST = list(VOWELS)

    It just didn't occur to me, I think, that this would create a list of
    the string's characters. Very nice!

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Stefan Ram@21:1/5 to Thomas Passin on Sat Feb 25 05:54:03 2023
    Thomas Passin <list1@tompassin.net> writes:
    VOWELS = 'aeiouAEIOU'
    is_vowel = 'y' in VOWELS

    A Pascal book from 1987 has an IF statement starting with

    |IF( ( symbol = 'X' ) OR ( SYMBOL = 'V' ) ) OR ( SYMBOL = 'I' )

    with the comment:

    |it is nicer to write
    |IF symbol IN [ 'X', 'V', 'I' ]
    |as explained in chapter 7

    . This reads quite similar to Python.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)