Python Forum
printing list of random generated rectangles - Printable Version

+- Python Forum (https://python-forum.io)
+-- Forum: Python Coding (https://python-forum.io/forum-7.html)
+--- Forum: Homework (https://python-forum.io/forum-9.html)
+--- Thread: printing list of random generated rectangles (/thread-8361.html)



printing list of random generated rectangles - Zatoichi - Feb-17-2018

import random

class Rectangle:
    
    def __init__(self, width, height):
        self.width = width
        self.height = height
    
    def get_width(self):
        return self.width
    def get_height(self):
        return self.height
    def compute_area(self):
        return self.width * self.height

myList = []

for i in range (random.randint(1, 10)):
    rand_Range = random.randint(1, 100)
    rand_Rectangle = Rectangle(rand_Range, rand_Range)
    myList += [rand_Rectangle]
    
total_area = 0

for r in myList:
    total_area += r.compute_area()

print (myList)

print (total_area)
Output:
[<__main__.Rectangle object at 0x033C91F0>, <__main__.Rectangle object at 0x034631B0>] Total area= 2245
So i have to make a program with a rectangle class. Then generate random number of rectangles from 1 to 10 and then print out the number of rectangles generated, the list of the heights and widths of each rectangle and then the total area of them all. The rectangles height and width are also randomly generated between 1 to 100. But I cannot seem to get the list to actually print the numbers from the rectangle.
desired output:
Output:
Number of rectangles is 2. [10, 100] [5, 57] Total area= 1285



RE: printing list of random generated rectangles - ka06059 - Feb-17-2018

1) hint for number of rects...len(myList)

2) loop myList & call methods on each item to print out height and width

print [item.get_width(),item.get_height()]


RE: printing list of random generated rectangles - buran - Feb-17-2018

yet another option is to define special __str__() method for your class


RE: printing list of random generated rectangles - Zatoichi - Feb-17-2018

import random

class Rectangle:
    
    def __init__(self, width, height):
        self.width = width
        self.height = height
    
    def get_width(self):
        return self.width
    def get_height(self):
        return self.height
    def compute_area(self):
        return self.width * self.height
    def __repr__(self):
        return '[%d,%d]\n' % (self.width, self.height)

def main():
    myList = []
        
    for _ in range (random.randint(1, 10)):
        
        rand_Rectangle = Rectangle(random.randint(1,100), random.randint(1,100))
        myList += [rand_Rectangle]
    
    
    total_area = 0
    
    for items in myList:
        total_area += items.compute_area()
    
    print ('Number of rectangles is', len(myList))
    
    print (myList)
    
    print ('Total area=', total_area)
    
main()
Output:
Number of rectangles is 3 [[96,91] , [24,47] , [26,44] ] Total area= 11008
So I am getting closer but is there way to clean it up or at least align the numbers nicely? i.e get rid of the comma in between sets and the extra set of brackets.


RE: printing list of random generated rectangles - ka06059 - Feb-18-2018

with __repr__() added like what buran said, all we need to do is to print each item in myList, not the nested list myList itself.


RE: printing list of random generated rectangles - buran - Feb-18-2018

you don't need the new line '\n' in your __repr__() function.
also you don't need these get functions.
import random
 
class Rectangle:
     
    def __init__(self, width, height):
        self.width = width
        self.height = height

    @property
    def area(self):
        return self.width * self.height

    def __repr__(self):
        return 'Rectangle[width:{: >2}, height:{: >2}]'.format(self.width, self.height)
 
def main():
        
    my_list = [Rectangle(random.randint(1,100), random.randint(1,100)) for _ in range (random.randint(1, 10))]
    total_area = sum([rect.area for rect in my_list])

    print ('Number of rectangles is', len(my_list))
    for rect in my_list:
        print(rect)
     
    print ('Total area=', total_area)


if __name__ == '__main__':   
    main()
Output:
Number of rectangles is 5 Rectangle[width:89,height:10] Rectangle[width:18,height:95] Rectangle[width:19,height:49] Rectangle[width:90,height: 9] Rectangle[width:44,height: 2] Total area= 4429

you can also buit-in the randomness in the class itself
import random
 
class Rectangle:
     
    def __init__(self, width=0, height=0):
        if width == 0:
            width = random.randint(1,100)
        if height == 0:
            height = random.randint(1,100)
        self.width = width
        self.height = height

    @property
    def area(self):
        return self.width * self.height

    def __repr__(self):
        return 'Rectangle[width:{: >3}, height:{: >3}]'.format(self.width, self.height)
 
def main():
        
    my_list = [Rectangle() for _ in range (random.randint(1, 10))]
    total_area = sum([rect.area for rect in my_list])

    print ('Number of rectangles is', len(my_list))
    for rect in my_list:
        print(rect)
     
    print ('Total area=', total_area)


if __name__ == '__main__':   
    main()



RE: printing list of random generated rectangles - DeaD_EyE - Feb-18-2018

Small improvement:

    def __init__(self, width=0, height=0):
        self.width = width or random.randint(1,100)
        self.height = height or random.randint(1,100)
The or operand looks up for truthiness. If the boolean is False it takes the next operand.

Following statement is True:
0 == 0.0 == False == bool(None) == bool([]) == bool({}) == bool(set())
This means the boolean of 0, 0.0 and None is False. This technique is used often for default arguments. A pitfall are negative numbers. They are True. You often see functions/methods with default arguments. Sometimes the function takes another object, which does not have __bool__ method implemented, then it is always True. In this case the default argument is None.

def get_beer(amount, brand=None):
    beer = '\N{BEER MUG}' * amount
    brand = brand or 'Warsteiner'
    print(f'Here your {brand} {beer}')
With this function you get always Warsteiner, if you don't supply the argument for brand.

Output:
>>> get_beer(2, 'Tsingtao') Here your Tsingtao ?? >>> get_beer(3, 0) # lets use a int Here your Warsteiner ??? >>> get_beer(3, -1) # what will happen now? Here your -1 ???



RE: printing list of random generated rectangles - Zatoichi - Feb-18-2018

Thanks for all the help!
I am curious buran what does the @property do?


RE: printing list of random generated rectangles - buran - Feb-18-2018

in your code you have calculate_area() method. it calculates area and returns the result. That is fine, however area is actually more of a property, then method. i.e. it is more convenient to treat as a property.
so short answer is that in this particular case we use @property decorator to make area read-only, i.e. you cannot set it (i.e. you don't want to be able to set area to 10, if it is 5x3 rectangle, right?)

class Rectangle:
     
    def __init__(self, width=0, height=0):
        self.width = width
        self.height = height

    @property
    def area(self):
        return self.width * self.height

rect = Rectangle(3,5)
print(rect.area)
rect.area = 10
Output:
15 Traceback (most recent call last): File "/home/boyan/geotag/misc/cli.py", line 18, in <module> rect.area = 10 AttributeError: can't set attribute
Note that this is so, only because we didn't use also @area.setter decorator
for more in-depth introduction read https://www.programiz.com/python-programming/property