• In code, list.clear doesn't throw error - it's just ignored

    From DFS@21:1/5 to All on Sun Nov 13 16:28:39 2022
    In code, list.clear is just ignored.
    At the terminal, list.clear shows
    <built-in method clear of list object at 0x000001C9CFEC4240>


    in code:
    x = [1,2,3]
    x.clear
    print(len(x))
    3

    at terminal:
    x = [1,2,3]
    x.clear
    <built-in method clear of list object at 0x000001C9CFEC4240>
    print(len(x))
    3


    Caused me an hour of frustration before I noticed list.clear() was what
    I needed.

    x = [1,2,3]
    x.clear()
    print(len(x))
    0

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Jon Ribbens@21:1/5 to DFS on Sun Nov 13 22:20:23 2022
    On 2022-11-13, DFS <nospam@dfs.com> wrote:
    In code, list.clear is just ignored.
    At the terminal, list.clear shows
    <built-in method clear of list object at 0x000001C9CFEC4240>


    in code:
    x = [1,2,3]
    x.clear
    print(len(x))
    3

    at terminal:
    x = [1,2,3]
    x.clear
    <built-in method clear of list object at 0x000001C9CFEC4240>
    print(len(x))
    3


    Caused me an hour of frustration before I noticed list.clear() was what
    I needed.

    x = [1,2,3]
    x.clear()
    print(len(x))
    0

    If you want to catch this sort of mistake automatically then you need
    a linter such as pylint:

    $ cat test.py
    """Create an array and print its length"""

    array = [1, 2, 3]
    array.clear
    print(len(array))
    $ pylint -s n test.py
    ************* Module test
    test.py:4:0: W0104: Statement seems to have no effect (pointless-statement)

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From DFS@21:1/5 to Jon Ribbens on Sun Nov 13 18:12:33 2022
    On 11/13/2022 5:20 PM, Jon Ribbens wrote:
    On 2022-11-13, DFS <nospam@dfs.com> wrote:
    In code, list.clear is just ignored.
    At the terminal, list.clear shows
    <built-in method clear of list object at 0x000001C9CFEC4240>


    in code:
    x = [1,2,3]
    x.clear
    print(len(x))
    3

    at terminal:
    x = [1,2,3]
    x.clear
    <built-in method clear of list object at 0x000001C9CFEC4240>
    print(len(x))
    3


    Caused me an hour of frustration before I noticed list.clear() was what
    I needed.

    x = [1,2,3]
    x.clear()
    print(len(x))
    0

    If you want to catch this sort of mistake automatically then you need
    a linter such as pylint:

    $ cat test.py
    """Create an array and print its length"""

    array = [1, 2, 3]
    array.clear
    print(len(array))
    $ pylint -s n test.py
    ************* Module test
    test.py:4:0: W0104: Statement seems to have no effect (pointless-statement)


    Thanks, I should use linters more often.

    But why is it allowed in the first place?

    I stared at list.clear and surrounding code a dozen times and said
    "Looks right! Why isn't it clearing the list?!?!"

    2 parens later and I'm golden!

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Jon Ribbens@21:1/5 to DFS on Mon Nov 14 00:31:39 2022
    On 2022-11-13, DFS <nospam@dfs.com> wrote:
    On 11/13/2022 5:20 PM, Jon Ribbens wrote:
    On 2022-11-13, DFS <nospam@dfs.com> wrote:
    In code, list.clear is just ignored.
    At the terminal, list.clear shows
    <built-in method clear of list object at 0x000001C9CFEC4240>


    in code:
    x = [1,2,3]
    x.clear
    print(len(x))
    3

    at terminal:
    x = [1,2,3]
    x.clear
    <built-in method clear of list object at 0x000001C9CFEC4240>
    print(len(x))
    3


    Caused me an hour of frustration before I noticed list.clear() was what
    I needed.

    x = [1,2,3]
    x.clear()
    print(len(x))
    0

    If you want to catch this sort of mistake automatically then you need
    a linter such as pylint:

    $ cat test.py
    """Create an array and print its length"""

    array = [1, 2, 3]
    array.clear
    print(len(array))
    $ pylint -s n test.py
    ************* Module test
    test.py:4:0: W0104: Statement seems to have no effect (pointless-statement)


    Thanks, I should use linters more often.

    But why is it allowed in the first place?

    Because it's an expression, and you're allowed to execute expressions.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Greg Ewing@21:1/5 to Jon Ribbens on Mon Nov 14 13:55:28 2022
    On 14/11/22 1:31 pm, Jon Ribbens wrote:
    On 2022-11-13, DFS <nospam@dfs.com> wrote:
    But why is it allowed in the first place?

    Because it's an expression, and you're allowed to execute expressions.

    To put it a bit more clearly, you're allowed to evaluate
    an expression and ignore the result.

    --
    Greg

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Chris Angelico@21:1/5 to DFS on Mon Nov 14 13:11:11 2022
    On Mon, 14 Nov 2022 at 11:53, DFS <nospam@dfs.com> wrote:

    On 11/13/2022 5:20 PM, Jon Ribbens wrote:
    On 2022-11-13, DFS <nospam@dfs.com> wrote:
    In code, list.clear is just ignored.
    At the terminal, list.clear shows
    <built-in method clear of list object at 0x000001C9CFEC4240>


    in code:
    x = [1,2,3]
    x.clear
    print(len(x))
    3

    at terminal:
    x = [1,2,3]
    x.clear
    <built-in method clear of list object at 0x000001C9CFEC4240>
    print(len(x))
    3


    Caused me an hour of frustration before I noticed list.clear() was what
    I needed.

    x = [1,2,3]
    x.clear()
    print(len(x))
    0

    If you want to catch this sort of mistake automatically then you need
    a linter such as pylint:

    $ cat test.py
    """Create an array and print its length"""

    array = [1, 2, 3]
    array.clear
    print(len(array))
    $ pylint -s n test.py
    ************* Module test
    test.py:4:0: W0104: Statement seems to have no effect (pointless-statement)


    Thanks, I should use linters more often.

    But why is it allowed in the first place?

    I stared at list.clear and surrounding code a dozen times and said
    "Looks right! Why isn't it clearing the list?!?!"

    2 parens later and I'm golden!


    No part of it is invalid, so nothing causes a problem. For instance,
    you can write this:

    1

    And you can write this:

    1 + 2

    And you can write this:

    print(1 + 2)

    But only one of those is useful in a script. Should the other two be
    errors? No. But linters WILL usually catch them, so if you have a good
    linter (especially built into your editor), you can notice these
    things.

    ChrisA

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Jon Ribbens@21:1/5 to Greg Ewing on Mon Nov 14 01:21:57 2022
    On 2022-11-14, Greg Ewing <greg.ewing@canterbury.ac.nz> wrote:
    On 14/11/22 1:31 pm, Jon Ribbens wrote:
    On 2022-11-13, DFS <nospam@dfs.com> wrote:
    But why is it allowed in the first place?

    Because it's an expression, and you're allowed to execute expressions.

    To put it a bit more clearly, you're allowed to evaluate
    an expression and ignore the result.

    ... because it may have side effects, and it's not possible to determine whether it will or not in advance.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From MRAB@21:1/5 to Greg Ewing on Mon Nov 14 02:13:34 2022
    On 2022-11-14 00:55, Greg Ewing wrote:
    On 14/11/22 1:31 pm, Jon Ribbens wrote:
    On 2022-11-13, DFS <nospam@dfs.com> wrote:
    But why is it allowed in the first place?

    Because it's an expression, and you're allowed to execute expressions.

    To put it a bit more clearly, you're allowed to evaluate
    an expression and ignore the result.

    But if it's an expression where it's expecting a statement and it's not
    a call, then it's probably a bug.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Chris Angelico@21:1/5 to MRAB on Mon Nov 14 13:22:31 2022
    On Mon, 14 Nov 2022 at 13:18, MRAB <python@mrabarnett.plus.com> wrote:

    On 2022-11-14 00:55, Greg Ewing wrote:
    On 14/11/22 1:31 pm, Jon Ribbens wrote:
    On 2022-11-13, DFS <nospam@dfs.com> wrote:
    But why is it allowed in the first place?

    Because it's an expression, and you're allowed to execute expressions.

    To put it a bit more clearly, you're allowed to evaluate
    an expression and ignore the result.

    But if it's an expression where it's expecting a statement and it's not
    a call, then it's probably a bug.

    Maybe, but I'd be dubious of making it that simplistic. For instance,
    which of these is more likely to be useless?

    spam or ham()
    spam() or ham

    Syntactically, both of them are 'or' expressions, but one of them is
    almost certainly unnecessary, while the other is just an oddly-written conditional statement and most definitely useful.

    In any case, this is the job of linters, NOT the language itself.

    ChrisA

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From DFS@21:1/5 to Chris Angelico on Sun Nov 13 22:23:09 2022
    On 11/13/2022 9:11 PM, Chris Angelico wrote:
    On Mon, 14 Nov 2022 at 11:53, DFS <nospam@dfs.com> wrote:

    On 11/13/2022 5:20 PM, Jon Ribbens wrote:
    On 2022-11-13, DFS <nospam@dfs.com> wrote:
    In code, list.clear is just ignored.
    At the terminal, list.clear shows
    <built-in method clear of list object at 0x000001C9CFEC4240>


    in code:
    x = [1,2,3]
    x.clear
    print(len(x))
    3

    at terminal:
    x = [1,2,3]
    x.clear
    <built-in method clear of list object at 0x000001C9CFEC4240>
    print(len(x))
    3


    Caused me an hour of frustration before I noticed list.clear() was what >>>> I needed.

    x = [1,2,3]
    x.clear()
    print(len(x))
    0

    If you want to catch this sort of mistake automatically then you need
    a linter such as pylint:

    $ cat test.py
    """Create an array and print its length"""

    array = [1, 2, 3]
    array.clear
    print(len(array))
    $ pylint -s n test.py
    ************* Module test
    test.py:4:0: W0104: Statement seems to have no effect (pointless-statement)


    Thanks, I should use linters more often.

    But why is it allowed in the first place?

    I stared at list.clear and surrounding code a dozen times and said
    "Looks right! Why isn't it clearing the list?!?!"

    2 parens later and I'm golden!


    No part of it is invalid, so nothing causes a problem. For instance,
    you can write this:


    If it wastes time like that it's invalid.

    This is an easy check for the interpreter to make.

    If I submit a suggestion to python-list@python.org will it just show up
    here? Or do the actual Python devs intercept it?






    1

    And you can write this:

    1 + 2

    And you can write this:

    print(1 + 2)

    But only one of those is useful in a script. Should the other two be
    errors? No. But linters WILL usually catch them, so if you have a good
    linter (especially built into your editor), you can notice these
    things.


    ran pylint against it and got 0.0/10.


    --disable=
    invalid-name
    multiple-statements
    bad-indentation
    line-too-long
    trailing-whitespace
    missing-module-docstring
    missing-function-docstring
    too-many-lines
    fixme


    and got 8.9/10.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Greg Ewing@21:1/5 to MRAB on Mon Nov 14 18:12:23 2022
    On 14/11/22 3:13 pm, MRAB wrote:
    But if it's an expression where it's expecting a statement and it's not
    a call, then it's probably a bug.

    The key word there is "probably". If there's any chance it
    could be not a bug, it can't be an error. At most it should
    be a warning, and that's what linters are for. I wouldn't
    like the core interpreter to be producing a bunch of warnings
    for things like this.

    --
    Greg

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Michael Speer@21:1/5 to nospam@dfs.com on Sun Nov 13 23:53:08 2022
    Python doesn't care what an expression returns.

    You've written an expression that returns the value of the 'clear' function that is bound to that particular list.

    The interpreter doesn't know or care if accessing that 'clear' attribute on
    the class returns a function or for some reason triggers a bunch of side effects that the author decided they wanted to use __getattr__ to trigger.

    'list.clear' might be a perfectly reasonable expression in some library.
    I'd rather it not be, but hey, there are millions of python programmers
    making all kinds of code out there

    arbitrary expressions can have arbitrary effects. just because a value
    isn't assigned, returned or used as an argument to a function doesn't mean
    it isn't doing anything.

    you might then want python to inspect the result of the function, but how
    can python know if the author isn't purposely ignoring the return value of
    the expression?

    people can call functions that return values for only their side effects.

    if you can't tell by the form of the expression or the value it returns,
    what is the linter supposed to look for?

    what is the interpreter supposed to look for?

    if you want to avoid accidentally failing to clear a list during a
    function, you should write tests that check that various inputs to the
    function produce the expected outputs.

    'unit tests' are a good place to make sure that code is acting as you want
    it to

    for one-off scripts, you should always make the thing dry-run or convert
    from an input to an output (rather than in-place) so you can rerun them a
    few times and make sure they're doing what you want.

    sometimes making sure things are right is just on you.

    there will always be the occasional silly error in a script that is hard to
    see until you step away for a moment.

    stepping away and coming back is a pretty good thing to do if you're stuck
    on something that feels impossible.




    On Sun, Nov 13, 2022 at 10:33 PM DFS <nospam@dfs.com> wrote:

    On 11/13/2022 9:11 PM, Chris Angelico wrote:
    On Mon, 14 Nov 2022 at 11:53, DFS <nospam@dfs.com> wrote:

    On 11/13/2022 5:20 PM, Jon Ribbens wrote:
    On 2022-11-13, DFS <nospam@dfs.com> wrote:
    In code, list.clear is just ignored.
    At the terminal, list.clear shows
    <built-in method clear of list object at 0x000001C9CFEC4240>


    in code:
    x = [1,2,3]
    x.clear
    print(len(x))
    3

    at terminal:
    x = [1,2,3]
    x.clear
    <built-in method clear of list object at 0x000001C9CFEC4240>
    print(len(x))
    3


    Caused me an hour of frustration before I noticed list.clear() was
    what
    I needed.

    x = [1,2,3]
    x.clear()
    print(len(x))
    0

    If you want to catch this sort of mistake automatically then you need
    a linter such as pylint:

    $ cat test.py
    """Create an array and print its length"""

    array = [1, 2, 3]
    array.clear
    print(len(array))
    $ pylint -s n test.py
    ************* Module test
    test.py:4:0: W0104: Statement seems to have no effect (pointless-statement)


    Thanks, I should use linters more often.

    But why is it allowed in the first place?

    I stared at list.clear and surrounding code a dozen times and said
    "Looks right! Why isn't it clearing the list?!?!"

    2 parens later and I'm golden!


    No part of it is invalid, so nothing causes a problem. For instance,
    you can write this:


    If it wastes time like that it's invalid.

    This is an easy check for the interpreter to make.

    If I submit a suggestion to python-list@python.org will it just show up
    here? Or do the actual Python devs intercept it?






    1

    And you can write this:

    1 + 2

    And you can write this:

    print(1 + 2)

    But only one of those is useful in a script. Should the other two be errors? No. But linters WILL usually catch them, so if you have a good linter (especially built into your editor), you can notice these
    things.


    ran pylint against it and got 0.0/10.


    --disable=
    invalid-name
    multiple-statements
    bad-indentation
    line-too-long
    trailing-whitespace
    missing-module-docstring
    missing-function-docstring
    too-many-lines
    fixme


    and got 8.9/10.

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


    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Chris Angelico@21:1/5 to Greg Ewing on Mon Nov 14 18:08:38 2022
    On Mon, 14 Nov 2022 at 18:00, Greg Ewing <greg.ewing@canterbury.ac.nz> wrote:

    On 14/11/22 3:13 pm, MRAB wrote:
    But if it's an expression where it's expecting a statement and it's not
    a call, then it's probably a bug.

    The key word there is "probably". If there's any chance it
    could be not a bug, it can't be an error. At most it should
    be a warning, and that's what linters are for. I wouldn't
    like the core interpreter to be producing a bunch of warnings
    for things like this.


    Notably, linters can be taught about more complex idioms, like:

    try:
    raw_input
    except NameError:
    raw_input = input

    which is an easy way to make polyglot Py2/Py3 code that handles the presence/absence of a particular name. Or, similarly:

    try:
    os.sendfile
    except AttributeError:
    ... # cope with sendfile not being available

    When os.sendfile exists, it's a completely useless expression. When it
    doesn't, it's an error. But the difference between those two is
    crucial.

    ChrisA

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From dn@21:1/5 to DFS on Mon Nov 14 20:25:30 2022
    On 14/11/2022 12.12, DFS wrote:
    On 11/13/2022 5:20 PM, Jon Ribbens wrote:
    On 2022-11-13, DFS <nospam@dfs.com> wrote:
    In code, list.clear is just ignored.
    At the terminal, list.clear shows
    <built-in method clear of list object at 0x000001C9CFEC4240>


    in code:
    x = [1,2,3]
    x.clear
    print(len(x))
    3

    at terminal:
    x = [1,2,3]
    x.clear
    <built-in method clear of list object at 0x000001C9CFEC4240>
    print(len(x))
    3


    Caused me an hour of frustration before I noticed list.clear() was what
    I needed.

    x = [1,2,3]
    x.clear()
    print(len(x))
    0

    If you want to catch this sort of mistake automatically then you need
    a linter such as pylint:

       $ cat test.py
       """Create an array and print its length"""

       array = [1, 2, 3]
       array.clear
       print(len(array))
       $ pylint -s n test.py
       ************* Module test
       test.py:4:0: W0104: Statement seems to have no effect
    (pointless-statement)


    Thanks, I should use linters more often.

    But why is it allowed in the first place?

    I stared at list.clear and surrounding code a dozen times and said
    "Looks right!  Why isn't it clearing the list?!?!"

    2 parens later and I'm golden!
    It looks 'right' because it is 'right'!
    However, compared with what was intended, it was 'wrong'!

    «
    I really hate this d***umb machine,
    I wish that they would sell it.
    It never does quite what I want,
    but only what I tell it!
    »



    Lifting some text from a recent PUG-meeting:

    «Distinguishing functions and their names:

    Please remind yourself that is_odd is the name of a function, whereas
    is_odd() calls the function and could thus be considered a 'label' for
    the returned-value – either approach could be used in different situations. »


    In this case, the subject is a method, and accordingly has a slightly
    different flavor. Rather than a return-value, the impact is an effect
    within the scope and/or to the state of the object. However, not materially-different from the OP's question.


    It is assumed that there is no difficulty related to calling the
    function, eg len( x ).


    So, why would we use the function/method by name instead of its asking
    for its return-value?
    (please remember that a Python function is a "first class" object)

    The (above) Challenge to PUG-members was to use code which produces the Fibonacci Sequence, and out of the first 16 values, return the number of Fibonacci-values which are also odd-numbers.

    We started with straight-line code which mixed-up these various steps in
    the process. As the challenge continued, such tangling made it very
    difficult to enable any variations. To illustrate the SRP and DIP
    (Single Responsibility and Dependency Inversion Principles of SOLID Architecture), we refactored and refactored, ending-up with:

    values_counted = sm.sequence_select_and_project(
    fg.fibonacci_generator,
    is_odd,
    limit,
    )

    sequence_select_and_project is a for-loop spanning two if-statements
    which count or break
    fibonacci_generator is self-explanatory (hopefully)
    is_odd returns boolean advice
    limit is 16

    Note how the first two arguments are [generator-]function names, cf function-calls!


    Now for 'the magic' of a dependency-inverted plug-in architecture:-

    If the 16 is changed to 32, we'll be comfortable with the idea that
    twice as many values will be generated and considered.

    So, think about changing the generator to produce (say) prime numbers.

    Alternately, alter the program to count only values divisible by two
    (perhaps using "is_even" as function-name).

    By 'plugging-in' a different function-name, the above control-routine
    can be used with any suitably-lengthy sequence as its data-source,
    and/or selection-criteria function!


    Accordingly, using the name of a function can be as useful as using the
    result of a function-call - even if the latter is far more common.

    --
    --
    Regards,
    =dn

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Stefan Ram@21:1/5 to Michael Speer on Mon Nov 14 08:55:08 2022
    Supersedes: <return-20221114095213@ram.dialup.fu-berlin.de>
    ["evaluation of a function" -> "evaluation of an expression"]

    Michael Speer <knomenet@gmail.com> writes:
    Python doesn't care what an expression returns.

    In my English, functions return values,
    expression are being evaluated to a value.
    The evaluation of an expression yields or
    produces a value. Expressions do not return,
    because they are not functions.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Stefan Ram@21:1/5 to Jon Ribbens on Mon Nov 14 08:24:45 2022
    Jon Ribbens <jon+usenet@unequivocal.eu> writes:
    If you want to catch this sort of mistake automatically then you need
    a linter such as pylint:

    For comparison, a C program:

    main.c

    #include <stdio.h> /* printf */

    int main( void )
    { printf; }

    transcript

    main.c: In function 'main':
    main.c:7:3: warning: statement with no effect [-Wunused-value]
    7 | { printf; }
    | ^~~~~~

    . Maybe some of the early designers of Python were C programmers.

    In VBA, "debug.print" is allowed, having the same meaning as
    "debug.print()", while "sin" gives an error: "Argument is not
    optional".

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Stefan Ram@21:1/5 to Jon Ribbens on Mon Nov 14 09:02:17 2022
    Jon Ribbens <jon+usenet@unequivocal.eu> writes:
    Because it's an expression, and you're allowed to execute expressions.

    Yes. This is the dynamical point of view. There's also a
    statical point of view, i.e., mere syntax, which is, in
    this case, "expression_stmt ::= starred_expression".

    |7.1 Expression statements
    ...
    |expression_stmt ::= starred_expression
    |
    |An expression statement evaluates the expression list
    |(which may be a single expression).
    |
    |In interactive mode, if the value is not None, it is converted
    |to a string using the built-in repr() function and the
    |resulting string is written to standard output on a line by
    |itself (except if the result is None, so that procedure calls
    |do not cause any output.)
    |
    The Python Language Reference (early 3.9)

    So, in interactive mode, it even does call a function,
    viz., "repr()".

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Roel Schroeven@21:1/5 to All on Mon Nov 14 10:09:44 2022
    Op 14/11/2022 om 4:23 schreef DFS:
    On 11/13/2022 9:11 PM, Chris Angelico wrote:
    On Mon, 14 Nov 2022 at 11:53, DFS <nospam@dfs.com> wrote:

    On 11/13/2022 5:20 PM, Jon Ribbens wrote:
    On 2022-11-13, DFS <nospam@dfs.com> wrote:
    In code, list.clear is just ignored.
    At the terminal, list.clear shows
    <built-in method clear of list object at 0x000001C9CFEC4240>


    in code:
    x = [1,2,3]
    x.clear
    print(len(x))
    3

    But why is it allowed in the first place?

    I stared at list.clear and surrounding code a dozen times and said
    "Looks right!  Why isn't it clearing the list?!?!"

    2 parens later and I'm golden!


    No part of it is invalid, so nothing causes a problem. For instance,
    you can write this:


    If it wastes time like that it's invalid.

    It's not invalid. In the REPL for example, it does something useful:

    x = [1, 2, 3]
    x.clear
    <built-in method clear of list object at 0x000002947DBBF680>

    Others have shown instances where writing a method or function without
    calling it are useful in a script too.

    There are languages that handle this differently. Ruby, for example,
    calls the function/method even when you don't write the parens, if I'm
    not mistaken. Personally I don't like that; I much prefer Python's
    explicitness in making the difference between the value of a function
    and calling that function. Still, there's something to be said for
    warnings. I agree with others that such warnings are more the job for a
    linter than for the language.

    FWIW I've been bitten by this in C++ once. I wanted to write something like

    if (some_condition())
        foo();

    But I forgot the parens after some_condition, so C++ evaluated the
    function pointer (which was non-NULL so evaluated is true in a boolean
    context) instead of the return value, and therefore foo() got called unconditionally.

    --

    "Don't Panic."
    -- Douglas Adams, The Hitchhiker's Guide to the Galaxy

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Karsten Hilbert@21:1/5 to All on Mon Nov 14 11:46:14 2022
    Am Mon, Nov 14, 2022 at 02:13:34AM +0000 schrieb MRAB:

    But if it's an expression where it's expecting a statement and it's not a call, then
    it's probably a bug.

    That "probably" makes it suitable for a linter, as was pointed out.

    Karsten
    --
    GPG 40BE 5B0E C98E 1713 AFA6 5BC0 3BEA AC80 7D4F C89B

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Weatherby,Gerard@21:1/5 to All on Mon Nov 14 11:35:26 2022
    The terminal told you what x.clear was.

    The Python documentation tells you how to call it: https://docs.python.org/3/tutorial/datastructures.html

    list.clear()
    Remove all items from the list. Equivalent to del a[:].

    An IDE (e.g. PyCharm) will try to autocomplete the parentheses and warn you if you don’t:

    “Statement seems to have no effect and can be replaced with a function call to have effect”

    From: Python-list <python-list-bounces+gweatherby=uchc.edu@python.org> on behalf of DFS <nospam@dfs.com>
    Date: Sunday, November 13, 2022 at 7:46 PM
    To: python-list@python.org <python-list@python.org>
    Subject: In code, list.clear doesn't throw error - it's just ignored
    *** Attention: This is an external email. Use caution responding, opening attachments or clicking on links. ***

    In code, list.clear is just ignored.
    At the terminal, list.clear shows
    <built-in method clear of list object at 0x000001C9CFEC4240>


    in code:
    x = [1,2,3]
    x.clear
    print(len(x))
    3

    at terminal:
    x = [1,2,3]
    x.clear
    <built-in method clear of list object at 0x000001C9CFEC4240>
    print(len(x))
    3


    Caused me an hour of frustration before I noticed list.clear() was what
    I needed.

    x = [1,2,3]
    x.clear()
    print(len(x))
    0

    -- https://urldefense.com/v3/__https://mail.python.org/mailman/listinfo/python-list__;!!Cn_UX_p3!jRrjG0fRo46VyY0jLfD1Z5C6tXDiphZy8zi2AqN_N5BB1_OwBe_wxmsBWmIVOFQDdZnvbRq1JNeGnPg$<https://urldefense.com/v3/__https:/mail.python.org/mailman/listinfo/python-list_
    _;!!Cn_UX_p3!jRrjG0fRo46VyY0jLfD1Z5C6tXDiphZy8zi2AqN_N5BB1_OwBe_wxmsBWmIVOFQDdZnvbRq1JNeGnPg$>

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Stefan Ram@21:1/5 to Jon Ribbens on Mon Nov 14 14:01:41 2022
    Jon Ribbens <jon+usenet@unequivocal.eu> writes:
    """Create an array and print its length"""
    array = [1, 2, 3]
    array.clear

    BTW: Above, there are /two/ expression statements
    with no effect; the other one is

    """Create an array and print its length"""

    . Apparently, linters know this and will not create
    a warning for such string literals.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Stefan Ram@21:1/5 to Stefan Ram on Mon Nov 14 14:07:57 2022
    ram@zedat.fu-berlin.de (Stefan Ram) writes:
    BTW: Above, there are /two/ expression statements
    with no effect; the other one is
    """Create an array and print its length"""
    . Apparently, linters know this and will not create
    a warning for such string literals.

    And Python is reported to remove such string
    statements when invoked with "-OO".

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Jon Ribbens@21:1/5 to Stefan Ram on Mon Nov 14 14:18:25 2022
    On 2022-11-14, Stefan Ram <ram@zedat.fu-berlin.de> wrote:
    Jon Ribbens <jon+usenet@unequivocal.eu> writes:
    """Create an array and print its length"""
    array = [1, 2, 3]
    array.clear

    BTW: Above, there are /two/ expression statements
    with no effect; the other one is

    """Create an array and print its length"""

    . Apparently, linters know this and will not create
    a warning for such string literals.

    Not only do they know this, pylint will complain if you *don't* include
    that line, which is why I included it ;-)

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Chris Angelico@21:1/5 to Stefan Ram on Tue Nov 15 06:14:02 2022
    On Tue, 15 Nov 2022 at 05:57, Stefan Ram <ram@zedat.fu-berlin.de> wrote:

    Michael Speer <knomenet@gmail.com> writes:
    Python doesn't care what an expression returns.

    In my English, functions return values,
    expression are being evaluated to a value.
    The evaluation of a function yields or
    produces a value. Expressions do not return,
    because they are not functions.


    Well, you can dispute the terminology all you like, but there's no
    real difference between function calls and other types of expression.
    They're all just expressions and they can be combined arbitrarily.

    ChrisA

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Cameron Simpson@21:1/5 to DFS on Tue Nov 15 09:11:10 2022
    On 13Nov2022 22:23, DFS <nospam@dfs.com> wrote:
    On 11/13/2022 9:11 PM, Chris Angelico wrote:
    [ ... `x.clear` ... ]
    No part of it is invalid, so nothing causes a problem. For instance,
    you can write this:

    If it wastes time like that it's invalid.

    It's a valid expression.

    It looks to your eye like a no-op, but at actually Python _looks up the
    name `clear`_ on an object (which happens to be a `list`). That is a
    real thing to do, and can have side effects.

    While most of the examples here have been in the REPL where running an expression with no side effects is itself useful, because the REPL can
    print the result, I've personally got some real world code with a bare `some_object.attribute` line. I'm not sure where, or I'd show it, but I
    _think_ it was probably prepriming a cached object property. There might
    have been a more expressive way to do that, but it was a bare attribute
    lookup with side effects, _used for those side effects_.

    This is an easy check for the interpreter to make.

    It really isn't, given that (a) this isn't known by the interpreter to
    be a `list` until runtime and (b) that would need embedding special
    knowledge that looking up an attribute on a `list` has no side effects
    (versus some other things, where it is not the case).

    Linters are the best place for this: they warn about probably-mistakes
    idioms like this, and can have slightly deep knowledge of the code's
    semantics sometimes.

    If I submit a suggestion to python-list@python.org will it just show
    up here? Or do the actual Python devs intercept it?

    Nah, it'll go through.

    Cheers,
    Cameron Simpson <cs@cskk.id.au>

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Dennis Lee Bieber@21:1/5 to All on Mon Nov 14 19:15:22 2022
    On Tue, 15 Nov 2022 09:11:10 +1100, Cameron Simpson <cs@cskk.id.au>
    declaimed the following:

    On 13Nov2022 22:23, DFS <nospam@dfs.com> wrote:
    This is an easy check for the interpreter to make.

    It really isn't, given that (a) this isn't known by the interpreter to
    be a `list` until runtime and (b) that would need embedding special
    knowledge that looking up an attribute on a `list` has no side effects >(versus some other things, where it is not the case).


    There is also the minor facet that "x.clear" can be bound to a different name...

    x = [1, 2, 3.145926536, "Pie"]
    clearx = x.clear
    x
    [1, 2, 3.145926536, 'Pie']
    clearx()
    x
    []




    --
    Wulfraed Dennis Lee Bieber AF6VN
    wlfraed@ix.netcom.com http://wlfraed.microdiversity.freeddns.org/

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Cameron Simpson@21:1/5 to Dennis Lee Bieber on Tue Nov 15 13:33:40 2022
    On 14Nov2022 19:15, Dennis Lee Bieber <wlfraed@ix.netcom.com> wrote:
    There is also the minor facet that "x.clear" can be bound to a
    different name...

    x = [1, 2, 3.145926536, "Pie"]
    clearx = x.clear
    x
    [1, 2, 3.145926536, 'Pie']
    clearx()
    x
    []


    I think the OP would take the stance that this:

    clearx = x.clear

    is more valid than:

    x.clear

    which discards the return value of the expression.

    Cheers,
    Cameron Simpson <cs@cskk.id.au>

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From avi.e.gross@gmail.com@21:1/5 to Dennis Lee Bieber on Tue Nov 15 00:45:17 2022
    Cameron,

    What would be the meaning of an ordering relation determining what is MORE VALID?

    As has been pointed out, not only are some uses that look odd sometimes
    valid, but perhaps even can be used in ways you simply may not see, such as side effects. Some examples ranging from poor to horrible are mentioned
    below.

    In some languages, trying to access a variable that is not properly existing
    or initialized, can generate an error, as an example, which may cause the current function to terminate if not caught and jump up the call chain till
    an error handler is found. Code like:

    1/0

    May seem meaningless as the result is not saved, but may trigger a divide by zero error.

    Is it an error to write code like:

    If x.clear:
    pass

    I suspect it is possible to write quite weird code that might pass most
    linters but that does nothing useful and also to write code that is useful
    but might be disparaged by many interpreters or linters.

    My example above is a fairly common code pattern while code is being written
    as a sort of reminder to perhaps come back later and flesh it out properly,
    or remove it if it is no longer applicable. If so, it would be reasonable
    for it to be challenged and also to ignore such warnings until later when either it is gone, or the code hint should be gone.

    There are many cases where short-circuit evaluation means code is not run
    such as "True || x" that is less obvious but equally bypassed if you set a variable to True and do not change it and use it instead of True above. But
    is it an error? What if again, my later goal is to add code that may change
    the Truth value. As it is, the statement is not evaluated. But it may be set
    up as a placeholder to enhance later, perhaps long after, or retain some flexibility. Insisting it be removed might be too harsh while a warning
    might be reasonable. Yet again, it is not always an error to not use
    something like declaring a variable you might need or importing a module you never use.

    Code is chock full of such things in mid-stream. And you can deliberately ignore some things without it being a mistake as in:

    ( _, mean, _) = minMeanMax(args)

    Sure, it may be overkill to call a function that returns three things then ignore two of them. So what? What if instead of "_" I used real variable
    names like min and max? Should I get error messages that two variable are
    set up with values but never again used?

    Or consider what I sometimes do when I write code that someone else will use and to test it I must use something like a different filename/path on my machine than they do on theirs. I might write code like

    # Comment out one or more of the below so only one exists:
    Place = "whatever"
    Place = "Some other place"

    Clearly if I am using the second one, I can comment the first out OR I can leave it alone and at minor expenses let the variable be unconditionally
    reset to the second value. Is it a bug or a feature?

    I could go on with other examples including some more subtle ones like declaring a variable name just to mask another variable from being
    accessible from a higher level and perhaps prevent the interpreter or
    compiler optimizing it away by using it in the meaningless way this
    discussion began with as it has been accessed once.

    One person's bug can be another person's feature. And clearly, as has been mentioned, there MAY be subtle side effects like invoking your custom setter
    or dunder method which also does logging or increments a count.

    There is a spectrum between being overly permissive and overly strict. This case almost amuses me because of the way that many a REPL works so something run directly in a console will take an expression like "varname" and PRINT
    the current value to the screen. If the same code is run from a file, or
    from inside some function, it does nothing useful and you need something
    like "print(varname)" instead. People often cut and paste such snippets of
    code and in one context they did something and in another, it seems
    meaningless and possibly an error.

    -----Original Message-----
    From: Python-list <python-list-bounces+avi.e.gross=gmail.com@python.org> On Behalf Of Cameron Simpson
    Sent: Monday, November 14, 2022 9:34 PM
    To: python-list@python.org
    Subject: Re: In code, list.clear doesn't throw error - it's just ignored

    On 14Nov2022 19:15, Dennis Lee Bieber <wlfraed@ix.netcom.com> wrote:
    There is also the minor facet that "x.clear" can be bound to a
    different name...

    x = [1, 2, 3.145926536, "Pie"]
    clearx = x.clear
    x
    [1, 2, 3.145926536, 'Pie']
    clearx()
    x
    []


    I think the OP would take the stance that this:

    clearx = x.clear

    is more valid than:

    x.clear

    which discards the return value of the expression.

    Cheers,
    Cameron Simpson <cs@cskk.id.au>
    --
    https://mail.python.org/mailman/listinfo/python-list

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Cameron Simpson@21:1/5 to avi.e.gross@gmail.com on Tue Nov 15 20:13:04 2022
    On 15Nov2022 00:45, avi.e.gross@gmail.com <avi.e.gross@gmail.com> wrote:
    What would be the meaning of an ordering relation determining what is
    MORE VALID?

    Are you asking what criterion would rate:

    clearx = x.clear

    as "more" valid than:

    x.clear

    on its own?

    I don't want to speak for the OP, but I'd think the OP's issue is that
    the bare `x.clear` is evaluated but not stored in a variable. As a
    metric, we might gather various descriptive statements we could make
    about these statements. They'd perhaps include "is legal Python code",
    "is pretty simple". The former line could include "saves the expression
    value in a variable for later use" and the latter could not. That's a comparison test you could use for ordering.

    My own opinion is that a bare:

    x.clear

    is legal and valid for all the example use cases already mentioned, but
    an entirely valid target for complaint by a linter, whose task is to
    point out dodgy looking stuff for review by the author.

    Cheers,
    Cameron Simpson <cs@cskk.id.au>

    --- 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 Tue Nov 15 18:10:28 2022
    That is clear, Cameron, but on my python interpreter values evaluated on the command line ARE saved:

    numb = 5
    5 + numb
    10
    numb
    5
    _ + _ + 1
    11
    _ * 2
    22


    The point is that a dummy variable of _ is assigned and re-assigned at each step and there can be a valid, if not very useful, reason to evaluating it
    and storing a result. If the darn thing is a very long name like alpha.beta.gamma.delta.epsilon then code that uses it repeatedly in the very next line can be much simpler by using _ repeatedly and perhaps more
    efficient. Consider:

    negsq = _ * -_

    versus

    negsq = alpha.beta.gamma.delta.epsilon * - alpha.beta.gamma.delta.epsilon

    So does your linter now need to look ahead and see if "_" is used properly
    in the next line? Note it can also be used on the LHS where it means
    something else.

    Still, I grant generally a naked evaluation is generally an error. LOL!

    -----Original Message-----
    From: Python-list <python-list-bounces+avi.e.gross=gmail.com@python.org> On Behalf Of Cameron Simpson
    Sent: Tuesday, November 15, 2022 4:13 AM
    To: python-list@python.org
    Subject: Re: In code, list.clear doesn't throw error - it's just ignored

    On 15Nov2022 00:45, avi.e.gross@gmail.com <avi.e.gross@gmail.com> wrote:
    What would be the meaning of an ordering relation determining what is
    MORE VALID?

    Are you asking what criterion would rate:

    clearx = x.clear

    as "more" valid than:

    x.clear

    on its own?

    I don't want to speak for the OP, but I'd think the OP's issue is that the
    bare `x.clear` is evaluated but not stored in a variable. As a metric, we
    might gather various descriptive statements we could make about these statements. They'd perhaps include "is legal Python code", "is pretty
    simple". The former line could include "saves the expression value in a variable for later use" and the latter could not. That's a comparison test
    you could use for ordering.

    My own opinion is that a bare:

    x.clear

    is legal and valid for all the example use cases already mentioned, but an entirely valid target for complaint by a linter, whose task is to point out dodgy looking stuff for review by the author.

    Cheers,
    Cameron Simpson <cs@cskk.id.au>
    --
    https://mail.python.org/mailman/listinfo/python-list

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Chris Angelico@21:1/5 to avi.e.gross@gmail.com on Wed Nov 16 10:15:32 2022
    On Wed, 16 Nov 2022 at 10:11, <avi.e.gross@gmail.com> wrote:

    That is clear, Cameron, but on my python interpreter values evaluated on the command line ARE saved:

    numb = 5
    5 + numb
    10
    numb
    5
    _ + _ + 1
    11

    That's a REPL feature.

    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 Tue Nov 15 19:10:23 2022
    Yes, Chris, that is a REPL feature and one that people may use
    interactively.

    As you note, it does not work inside something like a function which the
    REPL is not trying to evaluate and print. So clearly my supposed use would
    not make much sense in such code.


    -----Original Message-----
    From: Python-list <python-list-bounces+avi.e.gross=gmail.com@python.org> On Behalf Of Chris Angelico
    Sent: Tuesday, November 15, 2022 6:16 PM
    To: python-list@python.org
    Subject: Re: In code, list.clear doesn't throw error - it's just ignored

    On Wed, 16 Nov 2022 at 10:11, <avi.e.gross@gmail.com> wrote:

    That is clear, Cameron, but on my python interpreter values evaluated
    on the command line ARE saved:

    numb = 5
    5 + numb
    10
    numb
    5
    _ + _ + 1
    11

    That's a REPL feature.

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

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Stefan Ram@21:1/5 to Stefan Ram on Wed Nov 16 10:39:15 2022
    ram@zedat.fu-berlin.de (Stefan Ram) writes:
    In VBA, "debug.print" is allowed, having the same meaning as
    "debug.print()", while "sin" gives an error: "Argument is not
    optional".

    In Python 2.6, one could write

    print


    to print an empty line. Today, "print" would be a mere name.

    print
    <built-in function print>

    In Python 3.9, one needs to write

    print()


    for the same effect as "print" had in Python 2.6.

    One also could have gone the other way, that of VBA.
    By this, we would be able to call any function without
    parenthesis in the top (outermost) level of a statement.

    So, if I would have written a function

    def trace( message ):
    print message

    , I would then be able to call it via

    trace "my message"

    . It would look as if the language could be extended
    by new user-defined commands, while under the hood it
    would still be a function call.

    One would be able to define a no-argument function:

    def here:
    print "I'm here."

    and call it with just the statement

    here

    . This would not prevent functions as values.

    return here

    ,

    print here

    or

    x = here

    could still be used, because in those cases "here" is not
    used at the /outermost/ level of a statement. So in those
    cases, it would denote the function, not invoke it.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Stefan Ram@21:1/5 to Jon Ribbens on Wed Nov 23 19:16:48 2022
    Jon Ribbens <jon+usenet@unequivocal.eu> writes:
    If you want to catch this sort of mistake automatically then you need
    a linter such as pylint:

    output

    <string>, line 1
    list.clear
    Warning: Attribute used as statement.

    <string>, line 5
    list.clear
    Warning: Attribute used as statement.

    source code

    import ast, sys

    def check( point, source ):
    if isinstance( point, ast.Expr ) and\
    type( point.value )== ast.Attribute:
    print( "<string>, line", point.lineno, file=sys.stderr )
    print( source.split( '\n' )[ point.lineno-1 ], file=sys.stderr )
    print\
    ( "Warning:", "Attribute used as statement.", file=sys.stderr )
    print()

    def mylinter( source ):
    for point in ast.walk( ast.parse( example )):
    check( point, source )

    example = """\
    list.clear
    list.clear()
    x = list.clear
    print( list.clear )
    list.clear
    """

    mylinter( example )

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Chris Angelico@21:1/5 to Stefan Ram on Thu Nov 24 06:28:45 2022
    On Thu, 24 Nov 2022 at 06:26, Stefan Ram <ram@zedat.fu-berlin.de> wrote:

    Jon Ribbens <jon+usenet@unequivocal.eu> writes:
    If you want to catch this sort of mistake automatically then you need
    a linter such as pylint:

    output

    <string>, line 1
    list.clear
    Warning: Attribute used as statement.

    <string>, line 5
    list.clear
    Warning: Attribute used as statement.

    source code

    import ast, sys

    def check( point, source ):
    if isinstance( point, ast.Expr ) and\
    type( point.value )== ast.Attribute:
    print( "<string>, line", point.lineno, file=sys.stderr )
    print( source.split( '\n' )[ point.lineno-1 ], file=sys.stderr )
    print\
    ( "Warning:", "Attribute used as statement.", file=sys.stderr )
    print()

    def mylinter( source ):
    for point in ast.walk( ast.parse( example )):
    check( point, source )

    example = """\
    list.clear
    list.clear()
    x = list.clear
    print( list.clear )
    list.clear
    """

    mylinter( example )


    Uhh, yes? You just created an extremely simplistic linter. Your point?

    ChrisA

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Gilmeh Serda@21:1/5 to DFS on Fri Nov 25 00:52:55 2022
    On Sun, 13 Nov 2022 16:28:39 -0500, DFS wrote:

    In code, list.clear is just ignored.
    At the terminal, list.clear shows <built-in method clear of list object
    at 0x000001C9CFEC4240>

    It is obvious why ignores it. It's a method:

    Python 3.10.8 (main, Nov 1 2022, 14:18:21) [GCC 12.2.0] on linux
    Type "help", "copyright", "credits" or "license" for more information.
    l=[1,2,3]
    help(l.clear)

    Help on built-in function clear:

    clear() method of builtins.list instance
    Remove all items from list.

    --
    Gilmeh

    Contains no artificial colors or ingredients.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Dan Stromberg@21:1/5 to nospam@dfs.com on Fri Nov 25 07:56:22 2022
    On Sun, Nov 13, 2022 at 4:45 PM DFS <nospam@dfs.com> wrote:

    In code, list.clear is just ignored.
    At the terminal, list.clear shows
    <built-in method clear of list object at 0x000001C9CFEC4240>


    in code:
    x = [1,2,3]
    x.clear
    print(len(x))
    3

    at terminal:
    x = [1,2,3]
    x.clear
    <built-in method clear of list object at 0x000001C9CFEC4240>
    print(len(x))
    3


    Caused me an hour of frustration before I noticed list.clear() was what
    I needed.

    x = [1,2,3]
    x.clear()
    print(len(x))
    0

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



    I'm not 100% sanguine about properties, but the fact is they are part of
    the language:

    $ cat p
    below cmd output started 2022 Fri Nov 25 07:54:42 AM PST
    #!/usr/bin/env python3

    class P:
    def __init__(self):
    self.count = 0

    @property
    def increment(self):
    self.count += 1

    def result(self):
    return self.count


    p = P()
    p.increment
    p.increment
    print(p.result())
    above cmd output done 2022 Fri Nov 25 07:54:42 AM PST dstromberg@tp-mini-c:~/src/experiments/property x86_64-pc-linux-gnu 2670

    $ ./p
    below cmd output started 2022 Fri Nov 25 07:54:44 AM PST
    2

    As you can see, if the interpreter refused to do something with p.increment because it has no parens, the meaning of this code would change
    significantly.

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