Can One List Comprehension Be Used for both a Method and Class?

Advertisements

I have a simple program that determines the lateral surface area and volume of a pyramid from preset values:

class RightSquarePyramid():
    def __init__(self, b=0, h=0):
        self.b = float(b)
        self.h = float(h)
        pass
    
    def slantHeight(self):
        self.l = sqrt((self.h ** 2 + (self.b / 2) ** 2))
        return self.l
    
    def lateralSurfaceArea(self):
        return 2 * self.b * self.l
    
    def volume(self):
        return 1/3 * self.b ** 2 * self.h

myList = [[2.5, 5.0], [4.3, 2.5], [8, 3]]

tri0, tri1, tri2 = [RightSquarePyramid(*x) for x in myList]
tri0.slantHeight()
tri1.slantHeight()
tri2.slantHeight()
print(round(tri0.lateralSurfaceArea(), 3), round(tri1.lateralSurfaceArea(), 3), round(tri2.lateralSurfaceArea(), 3))
print(round(tri0.volume(), 3), round(tri1.volume(), 3), round(tri2.volume(), 3))

This happens because we only have the height and length of the base, so we need to calculate the slant height first.

I am currently using this solution:

tri0, tri1, tri2 = [RightSquarePyramid(*x) for x in myList]
triForce = tri0, tri1, tri2
[x.slantHeight() for x in triForce]
# tri0.slantHeight()
# tri1.slantHeight()
# tri2.slantHeight()
print(round(tri0.lateralSurfaceArea(), 3), round(tri1.lateralSurfaceArea(), 3), round(tri2.lateralSurfaceArea(), 3))
print(round(tri0.volume(), 3), round(tri1.volume(), 3), round(tri2.volume(), 3))

But this essentially replaces 3 lines of code with 2.

Is there a way to use list comprehension for both RightSquarePyramid() and slantHeight()?
Maybe a common variable that I am just overlooking that could do it?

>Solution :

You can use loops in all the cases where you’re currently enumerating all three tri variables. There’s no reason to destructure the list into those three variables in the first place.

The idiomatic way of writing a loop where you want to execute code for a side effect rather than doing something with its return value is to put it in a for loop rather than a list comprehension (the list comprehension is just going to give you a list of values that you don’t want, probably Nones).

For the print cases, you can use a generator expression and the * operator to pass the results of the iteration as arguments to the function.

triForce = [RightSquarePyramid(*x) for x in myList]
for t in triForce:
    t.slantHeight()

print(*(round(t.lateralSurfaceArea(), 3) for t in triForce))
print(*(round(t.volume(), 3) for t in triForce))

Since you’re doing the exact same print routine with two different methods of the class, you could even put those in another loop:

for f in (
    RightSquarePyramid.lateralSurfaceArea,
    RightSquarePyramid.volume
):
    print(*(round(f(t), 3) for t in triForce)))

Leave a ReplyCancel reply