that' fairly succinct and easy to readyou might thinkbut let' compare it to the function-based codesquare [( , )( , )( , )( , )perimeter(square hmmmaybe the object-oriented api isn' so compactthat saidi' argue that it was easier to read than the functional examplehow do we know what the list of tuples is supposed to represent in the second versionhow do we remember what kind of object ( list of two-tuplesthat' not intuitive!we're supposed to pass into the perimeter functionwe would need lot of documentation to explain how these functions should be used in contrastthe object-oriented code is relatively self-documentingwe just have to look at the list of methods and their parameters to know what the object does and how to use it by the time we wrote all the documentation for the functional versionit would probably be longer than the object-oriented code finallycode length is not good indicator of code complexity some programmers get hung up on complicated "one linersthat do an incredible amount of work in one line of code this can be fun exercisebut the result is often unreadableeven to the original author the following day minimizing the amount of code can often make program easier to readbut do not blindly assume this is the case luckilythis trade-off isn' necessary we can make the object-oriented polygon api as easy to use as the functional implementation all we have to do is alter our polygon class so that it can be constructed with multiple points let' give it an initializer that accepts list of point objects in factlet' allow it to accept tuples tooand we can construct the point objects ourselvesif neededdef __init__(selfpoints=none)points points if points else [self vertices [for point in pointsif isinstance(pointtuple)point point(*pointself vertices append(pointthis initializer goes through the list and ensures that any tuples are converted to points if the object is not tuplewe leave it as isassuming that it is either point object alreadyor an unknown duck-typed object that can act like point object