0

I wrote some code that was meant to try to approach a target string by selecting randomly from a list of chars, but I have some problem that I do not quite understand.

import random

class MonkiesGo:

    __chars = ['a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z']

    def __init__(self, targetString):
        __targetString = targetString.lower()
        __targetList = list(targetString)
        __attemptList = []
        __unmatchedIndexes = [ x for x in range(0, (len(targetString)-1)) ]

    def attemptToSolve(self):

        if len(__unmatchedIndexes) == 0:
            __attemptString = ''.join(__attemptList)
            return __attemptString, __targetString
        else:
            for index in __unmatchedIndexes:
                __attemptList[index] = randomChar()

    def updateSolutionProgress(self):
        for indexCheck in __unmatchedIndexes:
            if __targetList[index] == __attemptList[index]:
                __indexToClear = __unmatchedIndexes.index(index)
                del __unmatchedIndexes[indextToClear]

    def __randomChar(self):
        return __chars[ random.randint(0,26) ]

when I import it into a python shell in my terminal, make an object as follows:

from monkies import MonkiesGo 
mk = MonkiesGo("hello")
mk.attemptToSolve()

I get the error:

Traceback (most recent call last): File "", line 1, in
File "path/to/the/file/monkies.py", line 15, in attemptToSolve if len(__unmatched 0: NameError: name '_MonkiesGo__unmatched' is not defined

What is causing this, and why is there an underscore before MonkiesGo?

THanks in advance.

Updated to:

import random

class MonkiesGo:


    def __init__(self, targetString):
        self.targetString = targetString.lower()
        self.targetList = list(targetString)
        self.attemptList = []
        self.unmatchedIndexes = [ x for x in range(0, (len(targetString)-1)) ]
        self.chars = ['a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z']

    def attemptToSolve(self):

        if len(self.unmatchedIndexes) == 0:
            self.attemptString = ''.join(self.attemptList)
            return self.attemptString, self.targetString
        else:
            for index in self.unmatchedIndexes:
                self.attemptList[index] = randomChar()

    def updateSolutionProgress(self):
        for indexCheck in self.unmatchedIndexes:
            if self.targetList[index] == self.attemptList[index]:
                indexToClear = self.unmatchedIndexes.index(index)
                del self.unmatchedIndexes[indextToClear]

    def randomChar(self):
        return self.chars[ random.randint(0,26) ]

Now I get a name error regarding randomChar..?

ptw
  • 23
  • 5
  • 2
    Check http://stackoverflow.com/questions/1301346/the-meaning-of-a-single-and-a-double-underscore-before-an-object-name-in-python also you should make the variables defined in `__init__` as instance variables to access them from other class methods. – Ankit Jaiswal Apr 28 '15 at 02:26
  • aren't variables defined in init already instance variables? – ptw Apr 28 '15 at 02:51
  • No, they are just local variables. To make them instance variables you need to create them with `self.variable_name`. – Ankit Jaiswal Apr 28 '15 at 03:33
  • Call your `randomChar()` method as `self.randomChar()` if you are calling it from another method of same class. – Ankit Jaiswal Apr 28 '15 at 03:35
  • Thanks, I'll give it a go. I thought self. was used when a variable was being shadowed. I haven't used python or done much programming in a while... – ptw Apr 28 '15 at 03:46

1 Answers1

0

You are not creating any instance variables. In the function __init__, variables such as __targetString are local and are defined only within the function. When you call the function attemptToSolve, the variable __unmatchedIndices is also local and therefore undefined. The double underscore does not automatically make an instance variable; perhaps that's your confusion.

Instead of __targetString = whatever, you should use self.__targetString = whatever, or better yet drop the underscores and use just self.targetString. That creates a member variable. Access it in member functions using the same self.targetString syntax. Check out the tutorial that comes with Python.

Paul Cornelius
  • 9,245
  • 1
  • 15
  • 24
  • I will do as you suggest, but why should one not use __. Doesn't that declare it as private and only available within the class? – ptw Apr 28 '15 at 03:11
  • That's correct, and most experienced Python programmers do it very rarely. See https://www.python.org/dev/peps/pep-0008/#method-names-and-instance-variables. To some extent it's a matter of style and not a big deal either way. – Paul Cornelius Apr 29 '15 at 06:33
  • That's not a major consideration in the Python philosophy. More important is ease of debugging. See https://plus.google.com/115212051037621986145/posts/7wpbQTPRWft. – Paul Cornelius Apr 30 '15 at 19:18