0

Why and how to resolve shadows argument name from outer scope in class (python) ?

from optparse import OptionParser

class Test(object):
   def __init__(self):
      pass

   def _test1(self, some_val):
      print(some_val)

   def main(self, some_val):
      self.test1(some_val)

if __name__ == "__main__":
   parser = OptionParser()
   parser.add_option("-a", "--abcd", dest="abcd", default=None,
                      help="some_val")

   (options, args) = parser.parse_args()
   some_val = options.abcd

   mainobj = Test()
   mainobj.main(some_val)

In above code

  1. argument 'some_val' in 'main' and '_test' , displays shadows 'some_val' from outer scope.
  2. at method '_test' , displays '_test' may be static.

Pycharm, Python 3.8

Why those ? And how can I resolve them ?

khelwood
  • 55,782
  • 14
  • 81
  • 108
Fresher
  • 97
  • 2
  • 7
  • Does this answer your question? [What is the problem with shadowing names defined in outer scopes?](https://stackoverflow.com/questions/20125172/what-is-the-problem-with-shadowing-names-defined-in-outer-scopes) – bad_coder Jun 14 '21 at 11:43

2 Answers2

2

argument 'some_val' in 'main' and '_test' , displays shadows 'some_val' from outer scope.

You have declared a some_val variable in you global scope:

some_val = options.abcd

Since this variable is global, it is normally accessible from anywhere in the module.

But your Test._test1 and Test.main methods define some_val arguments which are accessible only from the methods body: they are in the methods local scopes.

This warning simply informs you that the some_val parameters are hiding ("shadowing") the some_val global variable, and that you won't be able to access the global variable from the method body (since some_val will refer to the local parameter).

Technically, if you don't need to access the global some_val variable from the methods body, it is not a problem.

You can fix this warning by simply giving better names to your variables/parameters, and not reusing same names for global and local variables.


at method '_test' , displays '_test' may be static

This warning means that, since your Test1._test method does not use the self argument, it could be declared as static using the staticmethod decorator (see more details in this other SO question):

@staticmethod
def _test1(some_val):
    print(some_val)
Tryph
  • 5,946
  • 28
  • 49
1
  • As others have explained, you have two variables called some_val which could technically be visible in the same part of the code; PyCharm is warning you about this because it can be confusing to have two different variables with the same name.

    In this case, the solution is to put the code after if __name__ == '__main__' into a function, and only have a call to that function after the if; that moves the variables used in that section of the code into a local scope, so they won't be confused with variables elsewhere:

    def main():
       parser = OptionParser()
       parser.add_option("-a", "--abcd", dest="abcd", default=None,
                          help="some_val")
    
       (options, args) = parser.parse_args()
       some_val = options.abcd
    
       mainobj = Test()
       mainobj.main(some_val)
    
    if __name__ == "__main__":
        main()
    

    You could also do this only partially, like this:

    def get_some_val():
       parser = OptionParser()
       parser.add_option("-a", "--abcd", dest="abcd", default=None,
                          help="some_val")
    
       (options, args) = parser.parse_args()
       return options.abcd
    
    if __name__ == "__main__":
       mainobj = Test()
       mainobj.main(get_some_val())
    
  • The method _test makes no use of the self parameter.

    If that's what's intended, you can mark it as @staticmethod and omit the self:

    @staticmethod
    def _test1(some_val):
        print(some_val)
    

    Alternately, expand the method so that it does, in fact, use self (which you may have been planning to do in any case).

Jiří Baum
  • 6,697
  • 2
  • 17
  • 17