Search code examples
pythonpython-class

Set keyword argument's default value as length of string


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.


Solution

  • 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}")