1

I've taken up a challenge to recreate some popular Python functions, one of them being string.count(). Other than the substring argument and the start index (optional), it also takes the end index (optional as well). This is my code:

def count(self,substring,start=0):
    self.substring = substring
    self.start = start

    self.queue = 0
    self.counter = 0

    for a in self.string[start:]:
        if a == self.substring[0]:
            self.queue += 1
        if a == self.substring[len(self.substring) - 1] and self.queue != 0:
            self.queue -= 1
            self.counter += 1

    return self.counter

Some variables I have defined outside of this function: self.string, which is the original string itself. You can see that I have not included the end argument, and that is why I'm here today. I would like to set the argument as: end=len(self.string) - 1, but it just throws and error and says: NameError: name 'self' is not defined. Is there a solution to this? So far I can say that my code is not the problem, since it works perfectly without the argument, but I may be wrong.

martineau
  • 119,623
  • 25
  • 170
  • 301
SecretSix
  • 53
  • 5
  • Are you using Classes? Cuz if you do please provide whole code. If not then self has no meaning here. – Soyokaze Dec 28 '21 at 08:23
  • Try create a variable `end` inside the function and give it the len() value, maybe you can't access variables inside the argument space. – Soyokaze Dec 28 '21 at 08:27
  • Yes I'm using classes, but I don't think I need to provide whole code, because only self.string is related to this function – SecretSix Dec 28 '21 at 08:37
  • Throughout this code, you are storing local values as instance attributes. The instance of the class will be keeping a copy of the last substring that was counted, the last start location, the value of counter, and the value of queue. These values should be stored in locals (i.e. drop the "self." from the start.) – Oddthinking Dec 28 '21 at 08:39

3 Answers3

2

I think one simple solution is the following

def count(self,substring,start=0, end=None):
    if end is None:
        end = len(self.string) - 1
    self.substring = substring
    self.start = start
    self.end = end # i suppose this needs to be set

    self.queue = 0
    self.counter = 0

    for a in self.string[start:]:
        if a == self.substring[0]:
            self.queue += 1
        if a == self.substring[len(self.substring) - 1] and self.queue != 0:
            self.queue -= 1
            self.counter += 1
    
    return self.counter
Robin Dillen
  • 704
  • 5
  • 11
  • Practical solution with a placeholder `None`. ️ The evaluation can be simplified as ️ [_conditional assignment_](https://stackoverflow.com/questions/6402311/python-conditional-assignment-operator) to: `self.end = len(substring) -1 if not end else end` – hc_dev Dec 28 '21 at 09:58
0

Try adding that end is a null value, then end = None in parentheses of def count():

def count(substring, start = 0, end = None):
    # implementation omitted

Later, thanks to the null value of end, you can create a condition inside the function, that is, if end is a null value, then end is -1.

You can write if end is None: end = len (self.string) - 1

hc_dev
  • 8,389
  • 1
  • 26
  • 38
Erling Olsen
  • 1
  • 4
  • 15
0

Let's categorize parameters into 3 types:

  • required (positional) parameter (like substring)
  • optional parameter (like start, end), often with None as type-less placeholder
  • parameter with default argument values (like start, end)

See also:

Use slicing and default for end parameter

See also the runnable demo on IDEone:

class StringUtil:

    def __init__(self, s):
        self.string = s
    
    
    def count(self, substring, start=0, end=-1):  # end index/slice: -1 for the last, instead len(self.substring) - 1
        self.substring = substring
        self.start = start
        self.end = end
        self.queue = 0
        self.counter = 0

        for a in self.string[start:]:
            if a == self.substring[0]:
                self.queue += 1
            if a == self.substring[end] and self.queue != 0:  # -1 for the last, instead len(self.substring) - 1
                self.queue -= 1
                self.counter += 1
        
        return self.counter


sub = "o*o"
s =  "Hell" + sub + " W" + sub + "rld"
cnt = StringUtil(s).count(sub)
print(f" counted '{sub}' in '{s}' times: {cnt}")
hc_dev
  • 8,389
  • 1
  • 26
  • 38