learning python ...

hw hw at adminart.net
Mon May 24 10:17:09 EDT 2021


On 5/24/21 11:33 AM, Cameron Simpson wrote:
> On 24May2021 08:21, hw <hw at adminart.net> wrote:
>> On 5/24/21 12:03 AM, Cameron Simpson wrote:
>>> On 23May2021 21:02, Stestagg <stestagg at gmail.com> wrote:
>>>> On Sun, 23 May 2021 at 20:37, hw <hw at adminart.net> wrote:
>>>>> I don't know about shadowing.
>>>>
>>>> Shadowing is effectively saying “within this bit of code, (scope) I’m going
>>>> to use an already-used name for my own value”
>>>
>>> An example might make this clearer:
>>>
>>>      x = 1 # global variable
>>>
>>>      def f(a):
>>>          x = a * 2
>>>          return x
>>>
>>> Inside the function f() the name 'x" shadows the global "x"; references
>>> to "x" are to the function's local vairable. Which is very desireable.
>>
>> If it works that way, I would consider it an entirely different
>> variable.  Is there a way to access the global x from within a
>> function without transferring it through parameters of the function?
>> Than can also sometimes be useful.
> 
> Sure. You can declare a name like this:
> 
>      def f(a):
>          global x  # find x in the global namespace (the module)
>          x = a * 2
>          return x
> 
> This is pretty rare and usually discouraged. Of there are times when it
> is useful.
> 
> 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.

>>> 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'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.

> 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?

> 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.

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?


More information about the Python-list mailing list