learning python ...

Cameron Simpson cs at cskk.id.au
Mon May 24 17:27:01 EDT 2021


On 24May2021 16:17, hw <hw at adminart.net> wrote:
>On 5/24/21 11:33 AM, Cameron Simpson wrote:
>>Note that in this function:
>>
>>     x = 1
>>     y = 2
>>
>>     def f(a):
>>         x = 3
>>         print(x, y)
>>
>>"x" is local, because the function contains an assignment to it. "y"
>>comes from an outer scope (in this case, the global scope) because
>>there's no assignment to it.
>
>Thanks!  That basically works the same as in perl then.

ISTR that Perl needed me to declare locals with my(). Locals are deduced 
from the code in Python.

>>>>As Stestagg has mentioned, there are also tools called linters which
>>>>warn you about issues like this. Tools like pyflakes, pylint,
>>>>pycodestyle all inspect your code for a wide variety of potential errors
>>>>and discouraged habits.  Not to mention tools like mypy which do type
>>>>validation.
>>>
>>>So you're saying one can't really go without those unless you want to
>>>take the risk?
>>
>>Self restraint and developing good habits does 99% of the work. Linters
>>are great for catching various accidents.
>
>I never needed one before.

I programmed for years in Python (and Perl etc etc) without bothing with 
linters. As I said, 99% of the work can be achieved with a loittle self 
discipline. But linters are good for catching mistakes - computers don't 
get bored. And they can also catch things you weren't considering.

I used to use lint in C and liked the attention to tedious detail.

So for my environment I wrote myself a "lint" script which runs the 
linters I like with the options I like, and linting is now an easy step 
that I perform at my choosing (generally post bug fixing or feature 
implementing).

>>[...]
>>>I'm not saying it shouldn't be allowed to defeat or to re-define stuff,
>>>only that it shouldn't go through quietly.
>>
>>Well, most of us use linters to exhibit that noise, rather than
>>requiring the code to be littered with special directives.
>>
>>I usually code without much linter fuss until I've got the latest batch
>>of work (eg feature or fix) ready, commit the changes, then lint
>>vigorously and commit that polish before merging with the main line of
>>code.
>
>Maybe python requires a different approach than other languages in 
>that it doesn't allow for the overhead that can be used to make things 
>easy to read and without guessing in other languages.  That overhead 
>can be a disadvantage, yet getting to used to not having it could take 
>a while.

The approach isn't required. I find the approach useful to me.

>>Finally, consider this code:
>>
>>     num = input("Enter a number: ")
>>     num = int(num)
>>
>>input() returns a string, which would need converting to a number before
>>some numeric stuff. Plenty of people write the above. To my mind, this
>>is also a kind of shadowing, and I like this instead:
>>
>>     num_s = input("Enter a number: ")
>>     num = int(num_s)
>>
>>where the "_s" indicates quietly that this variable holds a string.
>
>Isn't that a kind of overhead python is trying to avoid?

It's a style or work practice of my own choosing. Python itself is happy 
with either code.

>>Is that shadowing to your mind? Or not? If yes, should the language emit
>>noise there, too? Remembering that Python _values_ are strongly typed,
>>though the variables are not (a variable might reference any kind of
>>object, as above).
>
>No, I don't see any shadowing in either example.  In the first one, 
>you (seem to) make sure that you get an integer (not considering what 
>happens when the input is not something that can be cast into an 
>integer) using the same variable by altering its contents.
>
>In the second example, you're using two different variables, trying to 
>cast the first one to an integer while assigning it to a second one 
>which is implicitly declared.
>
>If anything, I could argue that this is convoluted code because you're 
>doing lots of stuff implicitly --- and that could be argued for both 
>examples.  You could make it worse like
>
>  if(int(num = input("foo: ")) == 5):
>    pass
>
>involving side effects, but I don't know if python would allow you to 
>do that.  (Not that I would want to do something like this, but it 
>would make sense to me if it could be done ...)
>
>>I wouldn't say that your opinion would be wrong regardless of what side
>>of this question you come down on, but Python's chosen a side: noise for
>>nonsensical things, but not noise for dubious things. But plenty of
>>linters to complain about dubious things.
>
>What does python actually do in the first example?  Does it overshadow 
>a variable or does it change one?  If it overshadows a variable, it 
>would be dubious, if it doesn't, it won't be dubious.

Variables are just names which reference objects. The first example 
causes "num" to reference the string returned by input(), then it causes 
"num" to reference the int returned by int().

If you think of them like C pointers the analogy works well. They're not 
pointers (i.e. they're not memory addresses and you can't do arithmetic 
with the addresses), but they are references.

>There are more alternatives:  Python might create a new variable with 
>the same name and forget about the old one.  Or it doesn't forget 
>about the old one and the old one becomes inaccessible (unless you 
>have a reference to it, if there is such a thing in python).  How do 
>you call that?

Dunno, because that's not what happens. You're conflating values 
(objects, such as an int or a string) with variables (which _are_ 
references in Python, as opposed to named storage in some other 
languages).

Maybe you should give the Language Reference a read:

    https://docs.python.org/3/reference/index.html

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


More information about the Python-list mailing list