Why is count in quotes and how does hasattr work in an if statement?

So we could put any kind of string as the second argument and it will be true anyway ? for example:

for element in how_many_s:
if hasattr(element, “anything”) :
print(element.count(“s”))

This will work to?

No. In the list that’s being evaluated,
[{'s': False}, 'sassafrass', 18, ['a', 'c', 's', 'd', 's']]
… there are objects of four types: dictionary, string, int and list. The attribute mentioned must be an attribute of the particular type of object.

Let’s comment out the print line, put in a different one, then explore several different attributes:

how_many_s = [{'s': False}, "sassafrass", 18, ["a", "c", "s", "d", "s"]]
print(" Original list = {}\n".format(how_many_s))

for attr in ["keys", "count", "bit_length", "append"]:    
    for item in how_many_s:
        if hasattr(item, attr):      
    #    print(item.count('s'))
            print("attribute = {},  item = {}, item type = {}".format(attr, item, type(item)))
    print("***")

Output

 Original list = [{'s': False}, 'sassafrass', 18, ['a', 'c', 's', 'd', 's']]

attribute = keys,  item = {'s': False}, item type = <class 'dict'>
***
attribute = count,  item = sassafrass, item type = <class 'str'>
attribute = count,  item = ['a', 'c', 's', 'd', 's'], item type = <class 'list'>
***
attribute = bit_length,  item = 18, item type = <class 'int'>
***
attribute = append,  item = ['a', 'c', 's', 'd', 's'], item type = <class 'list'>
***

You can see here that the attribute count is shared by both string and list, which is why the original function printed out, first 5, then 2, from the string and the list, respectively.

5 Likes

I couldn’t get my head around that, now i do , thank you ! This was really helpful

1 Like

So this is checking whether the method is available for the type of object each element is? So these are not attributes that have been assigned based on any class. Just attributes of types in python.

2 Likes

@petercook0108566555 Yes, hasattr() function checks whether the method/attribute is defined or not in an object.
If you have to check all the attributes of an object, then open your python shell and view it using:

dir(str)
dir(dict)
dir(int)
dir(list)

or
for above example u can check it using below code:

how_many_s = [{'s':False},"sassafrass",18,['a','c','s','d','s']]
for i in how_many_s:
	print('{a} has attributes {b}'.format(a=type(i),b= dir(type(i))))
4 Likes

Can someone help me understand why count needs to be in parenthesis for this exercise? My understand is that the line of code is cycling through the list and seeing if the variable is able to ‘count’ and if so count the number of ‘s’ in the variable. If that’s the case why put ‘count’ in a string vs. referring the actual function count?

Do you mean this line?

if hasattr(element, 'count'):

We do this to verify that the element has a count method, as some do not. If we try to run a method that is not an attribute, then it will raise an exception, halting the code.

Hi Roy - thanks for the response. I understand that we’re checking to see if the element has a count method but i’m still not 100% sure why we just don’t search for count vs. ‘count’ . For some reason i thought if you are searching for count as a string (i.e. with quotations). For example you would use a piece of code like this: print(“The count is:”, count) not print(“The count is:”, ‘count’)

Sorry, you’ve lost me. What are we searching for? Where does count come into this?

Hm, I think your response may have shed some light on my confusion…but perhaps not. There is a count method in python that counts stuff correct? I believe in this exercise what the “”“f hasattr(element, ‘count’):”"" line of code is doing is checking to see if each element in the list has the ability to count and, if so, count how man times ‘s’ is in each element. Is that right? Or in this case is the ‘count’ used in this exercise and the general count method entirely different?

We’re aimed at determining if a class of object has a count attribute. If not, then we shouldn’t call that method on that object.

>>> (1).count(1)
Traceback (most recent call last):
  File "<pyshell#103>", line 1, in <module>
    (1).count(1)
AttributeError: 'int' object has no attribute 'count'
>>> 
>>> hasattr(1, 'count')
False
>>> 
>>> [1].count(1)
1
>>> "1".count('1')
1
>>> {"1": 1}.count('1')
Traceback (most recent call last):
  File "<pyshell#108>", line 1, in <module>
    {"1": 1}.count('1')
AttributeError: 'dict' object has no attribute 'count'
>>> {"1": 1}.count(1)
Traceback (most recent call last):
  File "<pyshell#109>", line 1, in <module>
    {"1": 1}.count(1)
AttributeError: 'dict' object has no attribute 'count'
>>> 

What we 'search" for doesn’t change anything if the method does not exist.

+1 on the rant for this question.

Extremely confusing with the whole ‘count’ attribute thing. I realize now that the element itself (via it’s data type) has the ‘count’ attribute, but still, that’s after 20 mins of Googling.

This question needs to be rewritten.

3 Likes

There are a few things I don’t understand about this lesson.

  1. Why is the attribute you’re looking for with hasattr() passed as an argument in quotation marks? So far we’ve used quotation marks with strings, so it’s not intuitive to use them when looking for a method.

  2. Since an attribute can be either a method or a variable, when we look for the "count" attribute using hasattr() and it comes back as True, how do we know it is a method that can be called and not just a variable of the class? Is it considered best practice to not have a variable and a method in the same class that both have the same name?

Because attribute names are type str.

The method only checks for attributes of a sequence class (str, list). It is up to us to determine (or know already) that the attribute is a method.

4 Likes

for element in how_many_s:
if hasattr(element, “count”):
print(element.count(“s”))

Can anyone explain why “count” in hasattr(element, “count”) has to be a string? I thought we were checking if it was an attribute?

All attributes have keys of type ‘str’, so quotes are necessary in order to match.

1 Like

+1, I feel the same way.

1 Like

Can somebody explain what exactly are attributes. Reading all the comments it seems:
attribut = methods
Are there anymore attributs?

Thanks! :slight_smile:

Methods are attributes, but so are data values which are typically those given to the __init__() method on instantiation.

from math import sqrt as root

class Triangle:
    def check_sides(self, a, b, c):
        """
        sum of any two sides must be greater than the other side
        """
        if a + b > c and a + c > b and b + c > a:
            return True
        raise ValueError
    
    def __init__(self, a, b, c):    #  method
        self.check_sides(a, b, c)                    
        self.a = a                  #  attribute
        self.b = b                  #  attribute
        self.c = c                  #  attribute

    def area(self):                 #  method
        """
        Heron's Area Formula for S-S-S triangle
        """
        s = (self.a + self.b + self.c) / 2
        return root(s * (s - self.a) * (s - self.b) * (s - self.c))

abc = Triangle(60, 70, 80)          # instance
print (f"Where a = {abc.a}, b = {abc.b}, c = {abc.c}, Area = {abc.area():.3f}")
# Where a = 60, b = 70, c = 80, Area = 2033.316

fgh = Triangle(60, 20, 80)          # failed instance
# ValueError
2 Likes

Excellent explanation! Thank you very much! You breakdown exactly what is happening in the code.

The codeacademy lesson fails to do this and doesn’t give an example within the context of the lesson which is learning classes. I think code academy might need to review a number of lessons for lack of clarity in instruction and lack of context.

3 Likes