[Tutor] Need to discuss about a class that can be used to print number of vowels, consonants, uppercase and lowercase letters and spaces in a string
Manprit Singh
manpritsinghece at gmail.com
Thu Aug 19 10:54:19 EDT 2021
Dear Sir,
Based on the guidance given by all of you I have rewritten the class . Now
the problem is a little bit modified. The class should print only number of
spaces, uppercase letters and lowercase letters .The class is given below
class StringStats:
def __init__(self, seq = ""):
self.str_seq = seq
self.cnt_lowercase = 0
self.cnt_space= 0
self.cnt_uppercase = 0
self.compute_stats()
def compute_stats(self):
for ch in self.str_seq:
if ch == " ":
self.cnt_space += 1
elif ch.isupper():
self.cnt_uppercase += 1
elif ch.islower():
self.cnt_lowercase += 1
def __str__(self):
return (f"String is- {self.str_seq}\n"
f"Count of uppercaseletters-{self.cnt_uppercase}\n"
f"Count of lowercaseletters-{self.cnt_lowercase}\n"
f"Count of spaces -{self.cnt_space}")
s_seq = "Amar Singhji "
st1 = StringStats(s_seq)
print(st1)
Gives the desired output as follows :
String is- Amar Singhji
Count of uppercaseletters-2
Count of lowercaseletters-9
Count of spaces -2
Still i have following questions :
!) How can i place self.compute_stats() inside __init__ without
placing all those instance variables that are initialized to 0.
2) The way I have used f strings inside __str__ for multiple lines is correct ?
On Wed, Aug 18, 2021 at 2:35 PM Alan Gauld via Tutor <tutor at python.org>
wrote:
> On 18/08/2021 05:13, Manprit Singh wrote:
> > Dear sir,
> >
> > I have written below given program using a class that will print number
> of
> > vowels, consonants, uppercase and lowercase letters and spaces in a
> > string, provided string contains only alphabets and space
>
> In general its better to keep printing separate from calculation.
> You have done that by creating a separate method but it would be
> better still to simply create a __str__() method and you can
> then just print the object. This males the class more usable
> in different contexts - such as a GUI or Web application.
>
> > class StringStats:
> > def __init__(self):
> > self.str_seq = None
> > self.uppercase = None
> > self.lowercase = None
> > self.vowel = None
> > self.consonants = None
> > self.spaces = None
>
> These initializations are not type compatible with the expected
> values. It would be better to use an empty string and zeros.
> Otherwise your new instance will be incompatible with code
> that uses it - imagine an app with a list of StringStats
> objects and that extracts all the values for calculation.
> Any object which has not had a string assigned and an explicit
> call to compute() will return Nones instead of numbers.
>
> Why not add the seq to the constructor and then analyse
> it immediately?
>
> class StringStats:
> def __init__(self), seq="")
> self.seq = seq
> self.compute_stats()
>
> That does everything your method does and more.
> You can still use the seq assignment directly if you
> need to change the string later.
>
> > def set_string(self, seq):
> > self.str_seq = seq
> >
> > def count_uppercase(self):
> > self.uppercase = sum(ch.isupper() for ch in self.str_seq)
> >
> > def count_lowercase(self):
> > self.lowercase = sum(ch.islower() for ch in self.str_seq)
> >
> > def count_vowels(self):
> > self.vowel = sum(ch in "AEIOUaeoiu" for ch in self.str_seq)
> >
> > def count_consonants(self):
> > self.consonants = sum(ch not in "AEIOUaeoiu " for ch in
> > self.str_seq)
> >
> > def count_space(self):
> > self.spaces = self.str_seq.count(" ")
>
> Given that you need to loop over the entire string for each
> method why not just have one method that sets all the counters
> in one pass of the string? The extra work over just setting one
> is minimal.
>
> > def compute_stats(self):
> > self.count_uppercase()
> > self.count_lowercase()
> > self.count_vowels()
> > self.count_consonants()
> > self.count_space()
>
> So this would become:
>
> def compute_stats(self):
> for ch in self.seq:
> if ch in string.vowels
> self.vowels =+=1
> elif ch.islower():
> self.lower += 1
> elif ch.isupper():
> self.upper == 1
> etc.
>
> > def show_stats(self):
> > print("String is-", self.str_seq)
> > print("Count of vowels-", self.vowel)
> > print("Count of consonants-", self.consonants)
> > print("Count of uppercase letters-", self.uppercase)
> > print("Count of lowercase letters", self.lowercase)
> > print("Count of spaces", self.spaces)
>
> And this could become your __str__() method, returning
> the string instead of printing it.
>
> So the modified class creates neater client code:
>
> > s_seq = "Amar Singh"
> > st1 = StringStats()
> > st1.set_string(s_seq)
> > st1.compute_stats()
> > st1.show_stats()
>
> Becomes
>
> s_seq = "Amar Singh"
> st1 = StringStats(s_seq)
> print(st1)
>
> > Just need your comments on this class against following points :
> >
> > 1) The way i have initialized all instance variables inside __init__(),
> later
> > on assigning values to each instance variable in different methods .
>
> See above. The use of inconsistent types and the deferred assignment of
> the string leaves the class in an inconsistent state compared to its
> peers. This could cause issues in the processing of collections of
> Stringstat objects. At the very least it will require extra checks
> to see if None is returned.
>
> Much better to initialize the string in the init as a parameter.
>
> > 2) I have made different methods to set each instance variable, can't all
> > these instance variables be set in a single method ?
>
> Yes, it would be better that way. it seems very unlikely that
> a user would want to only initialise one statistic.
>
> > 3) Any further improvement in the class
> Does it need to be a class at all?
> This could just be a function that takes a string and returns
> a dict or tuple of results.
>
> It's the old rule that a class that only has an init() plus
> one method is really a function. (getter/setters and _str_()
> don't really count as methods in that context)
>
>
> --
> Alan G
> Author of the Learn to Program web site
> http://www.alan-g.me.uk/
> http://www.amazon.com/author/alan_gauld
> Follow my photo-blog on Flickr at:
> http://www.flickr.com/photos/alangauldphotos
>
>
> _______________________________________________
> Tutor maillist - Tutor at python.org
> To unsubscribe or change subscription options:
> https://mail.python.org/mailman/listinfo/tutor
>
More information about the Tutor
mailing list