100% found this document useful (4 votes)
30 views

Download Complete Advanced Computer Programming in Python 1st Edition Karim Pichara PDF for All Chapters

Advanced

Uploaded by

pomadaguni
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
100% found this document useful (4 votes)
30 views

Download Complete Advanced Computer Programming in Python 1st Edition Karim Pichara PDF for All Chapters

Advanced

Uploaded by

pomadaguni
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 81

Visit https://ebookgate.

com to download the full version and


explore more ebooks

Advanced Computer Programming in Python 1st Edition


Karim Pichara

_____ Click the link below to download _____


https://ebookgate.com/product/advanced-computer-
programming-in-python-1st-edition-karim-pichara/

Explore and download more ebooks at ebookgate.com


Here are some recommended products that might interest you.
You can download now and explore!

Practical programming An introduction to computer science


using Python Jennifer Campbell

https://ebookgate.com/product/practical-programming-an-introduction-
to-computer-science-using-python-jennifer-campbell/

ebookgate.com

OpenCV with Python blueprints design and develop advanced


computer vision projects using OpenCV with Python 1st
Edition Michael Beyeler
https://ebookgate.com/product/opencv-with-python-blueprints-design-
and-develop-advanced-computer-vision-projects-using-opencv-with-
python-1st-edition-michael-beyeler/
ebookgate.com

Ultimate Python Programming 1st Edition Deepali Srivastava

https://ebookgate.com/product/ultimate-python-programming-1st-edition-
deepali-srivastava/

ebookgate.com

Expert Python Programming 2nd Edition Jaworski

https://ebookgate.com/product/expert-python-programming-2nd-edition-
jaworski/

ebookgate.com
Python Programming 4th Edition Singh A.

https://ebookgate.com/product/python-programming-4th-edition-singh-a/

ebookgate.com

Black hat Python Python programming for hackers and


pentesters 1st Edition Seitz

https://ebookgate.com/product/black-hat-python-python-programming-for-
hackers-and-pentesters-1st-edition-seitz/

ebookgate.com

OpenCV Computer Vision with Python 1st Edition Howse

https://ebookgate.com/product/opencv-computer-vision-with-python-1st-
edition-howse/

ebookgate.com

Computer Programming 1st Edition E. Balagurusamy

https://ebookgate.com/product/computer-programming-1st-edition-e-
balagurusamy/

ebookgate.com

Practical Maya Programming with Python 1st Edition


Galanakis

https://ebookgate.com/product/practical-maya-programming-with-
python-1st-edition-galanakis/

ebookgate.com
Contents

Contents 5

1 Object Oriented Programming 9


1.1 Classes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
1.2 Properties . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
1.3 Aggregation and Composition . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
1.4 Inheritance . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
1.5 Multiple Inheritance . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
1.6 Abstract Base Class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35
1.7 Class Diagrams . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39
1.8 Hands-On Activities . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43

2 Data Structures 45
2.1 Array-Based Data Structures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47
2.2 Node-based Data Structures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76
2.3 Hands-On Activities . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 96

3 Functional Programming 101


3.1 Python Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 101
3.2 Decorators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 123
3.3 Hands-On Activities . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 130

4 Meta Classes 135


4.1 Creating classes dynamically . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 137
4.2 Metaclasses . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 140
4.3 Hands-On Activities . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 146
6 CONTENTS

5 Exceptions 147
5.1 Exception Types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 147
5.2 Raising exceptions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 150
5.3 Exception handling . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 152
5.4 Creating customized exceptions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 156
5.5 Hands-On Activities . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 160

6 Testing 163
6.1 Unittest . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 163
6.2 Pytest . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 172
6.3 Hands-On Activities . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 181

7 Threading 185
7.1 Threading . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 185
7.2 Synchronization . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 197
7.3 Hands-On Activities . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 207

8 Simulation 209
8.1 Synchronous Simulation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 210
8.2 Discrete Event Simulation (DES) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 215
8.3 Hands-On Activities . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 222

9 Handling Strings and Bytes 227


9.1 Some Built-in Methods for Strings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 227
9.2 Bytes and I/O . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 236
9.3 bytearrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 239
9.4 Hands-On Activities . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 240

10 I/O Files 245


10.1 Context Manager . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 248
10.2 Emulating files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 250

11 Serialization 253
11.1 Serializing web objects with JSON . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 257
11.2 Hands-On Activities . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 261
CONTENTS 7

12 Networking 263
12.1 How to identify machines on internet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 263
12.2 Ports . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 263
12.3 Sockets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 265
12.4 Client-Server Architecture . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 266
12.5 Sending JSON data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 273
12.6 Sending data with pickle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 274
12.7 Hands-On Activities . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 276

13 Web Services 277


13.1 HTTP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 278
13.2 REST architecture . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 279
13.3 Client-side Script . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 280
13.4 Server-side Script . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 281
13.5 Request . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 284
13.6 Request Data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 285
13.7 Response . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 287
13.8 Other architectures for Web Services . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 289

14 Graphical User Interfaces 291


14.1 PyQt . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 291
14.2 Layouts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 300
14.3 Events and Signals . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 303
14.4 Sender . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 305
14.5 Creating Custom Signals . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 306
14.6 Mouse and Keyboard Events . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 308
14.7 QT Designer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 308

15 Solutions for Hands-On Activities 315


15.1 Solution for activity 1.1: Variable stars . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 316
15.2 Solution for activity 1.2: Geometric Shapes . . . . . . . . . . . . . . . . . . . . . . . . . . . . 319
15.3 Solution for activity 2.1: Production line of bottles . . . . . . . . . . . . . . . . . . . . . . . . 326
15.4 Solution for activity 2.2: Subway Map . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 330
15.5 Solution for activity 3.1: Patients in a Hospital . . . . . . . . . . . . . . . . . . . . . . . . . . 332
8 CONTENTS

15.6 Solution for activity 3.2: Soccer Team . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 334


15.7 Solution for activity 3.3: Hamburger Store . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 337
15.8 Solution for activity 4.1: MetaRobot . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 341
15.9 Solution for activity 5.1: Calculator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 343
15.10 Solution for activity 6.1: Testing the encryptor . . . . . . . . . . . . . . . . . . . . . . . . . . . 347
15.11 Solution for activity 6.2: Testing ATMs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 354
15.12 Solution for activity 7.1: Godzilla . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 357
15.13 Solution for activity 7.2: Mega Godzilla . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 360
15.14 Solution for activity 8.1: Client queues . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 364
15.15 Solution for activity 8.2: GoodZoo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 368
15.16 Solution for activity 9.1: Fixing data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 378
15.17 Solution for activity 9.2: Audio files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 382
15.18 Solution for activity 11.1: Cashiers’ data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 383

Bibliography 389
KARIM PICHARA – CHRISTIAN PIERINGER

ADVANCED COMPUTER PROGRAMMING IN PYTHON


ADVANCED COMPUTER PROGRAMMING IN PYTHON

Copyright © 2017 by Karim Pichara and Christian Pieringer


All rights reserved. This book or any portion thereof may not be reproduced or used in
any manner whatsoever without the express written permission of the publisher except
for the use of brief quotations in a book review.

ISBN: 9781521232385
To our wives and children
Preface

This book contains most of the relevant topics necessary to be an advanced computer programmer. The language used
in the book is Python 3. Besides the programming language, the reader will learn most of the backbone contents in
computer programming, such as object-oriented modeling, data structures, functional programming, input/output,
simulation, graphical interfaces, and much more. We believe that the best way to learn computer programming is to
work in hands-on activities. Practical exercises make the user get familiar with the main challenges that programming
brings, such as how to model a particular problem; or how to write good code and efficient routine implementation,
among others. Most of the chapters contain a set of hands-on activities (with proposed solutions) at the end. We
encourage the readers to solve all those assignments without previously checking the solution. Challenges may be hard
for initial programmers, but while going through this book, the activities will become more achievable for the reader.
This book contains most of the material used for the Advanced Python Programming course taught at PUC University
in Chile, by professors Karim Pichara and Christian Pieringer. The course is intended for Computer Science students
as well as any other affine career that can be benefited by computer programming knowledge. Of course, this book
is not enough to become a Software Engineer; there are other necessary courses that the reader must take to learn
more advanced concepts related to the development of bigger software projects. Some of the recommended courses
are Database Systems, Data Structures, Operating Systems, Compilers, Software Engineering, Testing, Software
Architecture, and Software Design, among others. The content of this book will prepare the reader to have the necessary
background for any of the next Software Engineering courses listed above. While using this book, readers should
follow along on their computers to be able to try all the examples included in the chapters. It will be necessary that
computers have already installed the required Python libraries.
3

Authors

Karim Pichara Baksai


Ph.D. in Computer Science,
Research Area: Machine Learning and Data Science applied to Astron-
omy
Associate Professor, Computer Science Department
Pontificia Universidad Católica de Chile (PUC)

Christian Pieringer Baeza


Ph.D. in Computer Science
Research Area: Computer Vision and Machine Learning
Adjunt Professor, Computer Science Department
Pontificia Universidad Católica de Chile (PUC)
4

Acknowledgments

This book was not possible without the constant help of the teaching assistants; they gave us invaluable feedback,
code and text editions to improve the book. The main collaborators who highly contributed are Belén Saldías, Ivania
Donoso, Marco Bucchi, Patricio López, and Ignacio Becker.

We would like also thank the team of assistants who worked in the hands-on activities: Jaime Castro, Rodrigo Gómez,
Bastián Mavrakis, Vicente Dominguez, Felipe Garrido, Javiera Astudillo, Antonio Gil, and José María De La Torre.

Belén Saldías Ivania Donoso Marco Bucci

Patricio López Ignacio Becker


Chapter 1

Object Oriented Programming

In the real world, objects are tangible; we can touch and feel them, they represent something meaningful for us. In the
software engineering field, objects are a virtual representation of entities that have a meaning within a particular context.
In this sense, objects keep information/data related to what they represent and can perform actions/behaviors using
their data. Object Oriented Programming (OOP) means that programs model functionalities through the interaction
among objects using their data and behavior. The way OOP represents objects is an abstraction. It consists in to create
a simplified model of the reality taking the more related elements according to the problem context and transforming
them into attributes and behaviors. Assigning attributes and methods to objects involves two main concepts close
related with the abstraction: encapsulation and interface.

Encapsulation refers to the idea of some attributes do not need to be visualized by other objects, so we can produce
a cleaner code if we keep those attributes inside their respective object. For example, imagine we have the object
Amplifer that includes attributes tubes and power transformer. These attributes only make sense inside
the amplifier because other objects such as the Guitar do not need to interact with them nor visualize them. Hence,
we should keep it inside the object Amplifier.

Interface let every object has a “facade” to protect its implementation (internal attributes and methods) and interact
with the rest of objects. For example, an amplifier may be a very complex object with a bunch of electronic pieces
inside. Think of another object such as the Guitar player and the Guitar that only interact with the amplifier
through the input plug and knobs. Furthermore, two or more objects may have the same interface allowing us to
replace them independently of their implementation and without change how we use them. Imagine a guitar player
wants to try a tube amplifier and a solid state amp. In both cases, amplifiers have the interface (knobs an input plug)
and offer the same user experience independently of their construction. In that sense, each object can provide the
10 CHAPTER 1. OBJECT ORIENTED PROGRAMMING

suitable interface according to the context.

1.1 Classes

From the OOP perspective, classes describe objects, and each object is an instance of a class. The class statement
allow us to define a class. For convention, we name classes using CamelCase and methods using snake_case.
Here is an example of a class in Python:

1 # create_apartment.py
2

4 class Apartment:
5 '''
6 Class that represents an apartment for sale
7 value is in USD
8 '''
9

10 def __init__(self, _id, mts2, value):


11 self._id = _id
12 self.mts2 = mts2
13 self.value = value
14 self.sold = False
15

16 def sell(self):
17 if not self.sold:
18 self.sold = True
19 else:
20 print("Apartment {} was sold"
21 .format(self._id))

To create an object, we must create an instance of a class, for example, to create an apartment for sale we have to call
the class Apartment with the necessary parameters to initialize it:

1 # instance_apartment.py
2

3 from create_apartment import Apartment


1.1. CLASSES 11

5 d1 = Apartment(_id=1, mts2=100, value=5000)


6

7 print("sold?", d1.sold)
8 d1.sell()
9 print("sold?", d1.sold)
10 d1.sell()

sold? False
sold? True
Apartment 1 was sold

We can see that the __init__ method initializes the instance by setting the attributes (or data) to the initial values,
passed as arguments. The first argument in the __init__ method is self, which corresponds to the instance itself.
Why do we need to receive the same instance as an argument? Because the __init__ method is in charge of the
initialization of the instance, hence it naturally needs access to it. For the same reason, every method defined in the
class that specifies an action performed by the instance must receive self as the first argument. We may think of
these methods as methods that belong to each instance. We can also define methods (inside a class) that are intended
to perform actions within the class attributes, not to the instance attributes. Those methods belong to the class and do
not need to receive self as an argument. We show some examples later.

Python provides us with the help(<class>) function to watch a description of a class:

1 help(Apartment)

#output

Help on class Apartment in module create_apartment:

class Apartment(builtins.object)
| Class that represents an apartment for sale
| price is in USD
|
| Methods defined here:
|
| __init__(self, _id, sqm, price)
12 CHAPTER 1. OBJECT ORIENTED PROGRAMMING

|
| sell(self)
|
| ----------------------------------------------------------------------
| Data descriptors defined here:
|
| __dict__
| dictionary for instance variables (if defined)
|
| __weakref__
| list of weak references to the object (if defined)

1.2 Properties

Encapsulation suggests some attributes and methods are private according to the object implementation, i.e., they
only exist within an object. Unlike other programming languages such as C++ or Java, in Python, the private concept
does not exist. Therefore all attributes/methods are public, and any object can access them even if an interface exist.
As a convention, we can suggest that an attribute or method to be private adding an underscore at the beginning
of its name. For example, _<attribute/method name>. Even with this convention, we may access directly
to the attributes or methods. We can strongly suggest that an element within an object is private using a double
underscore __<attribute/method name>. The name of this approach is name mangling. It concerns to the
fact of encoding addition semantic information into variables. Remember both approaches are conventions and good
programming practices.

Properties are the pythonic mechanism to implement encapsulation and the interface to interact with private attributes
of an object. It means every time we need that an attribute has a behavior we define it as property. In other way, we are
forced to use a set of methods that allow us to change and retrieve the attribute values, e.g, the commonly used pattern
get_value() and set_value(). This approach could generate us several maintenance problems.

The property() function allow us to create a property, receiving as arguments the functions use to get, set and delete
the attribute as property(<setter_function>, <getter_function>, <deleter_function>).
The next example shows the way to create a property:

1 # property.py
2

3 class Email:
1.2. PROPERTIES 13

5 def __init__(self, address):


6 self._email = address # A private attribute
7

8 def _set_email(self, value):


9 if '@' not in value:
10 print("This is not an email address.")
11 else:
12 self._email = value
13

14 def _get_email(self):
15 return self._email
16

17 def _del_email(self):
18 print("Erase this email attribute!!")
19 del self._email
20

21 # The interface provides the public attribute email


22 email = property(_get_email, _set_email, _del_email,
23 'This property contains the email.')

Check out how the property works once we create an instance of the Email class:

1 m1 = Email("[email protected]")
2 print(m1.email)
3 m1.email = "[email protected]"
4 print(m1.email)
5 m1.email = "kp2.com"
6 del m1.email

[email protected]
[email protected]
This is not an email address.
Erase this email attribute!!

Note that properties makes the assignment of internal attributes easier to write and read. Python also let us to define
properties using decorators. Decorators is an approach to change the behavior of a method. The way to create a
14 CHAPTER 1. OBJECT ORIENTED PROGRAMMING

property through decorators is adding @property statement before the method we want to define as attribute. We
explain decorators in Chapter 3.

1 # property_without_decorator.py
2

3 class Color:
4

5 def __init__(self, rgb_code, name):


6 self.rgb_code = rgb_code
7 self._name = name
8

9 def set_name(self, name):


10 self._name = name
11

12 def get_name(self):
13 return self._name
14

15 name = property(get_name, set_name)

1 # property_with_decorator.py
2

3 class Color:
4

5 def __init__(self, rgb_code, name):


6 self._rgb_code = rgb_code
7 self._name = name
8

9 # Create the property using the name of the attribute. Then we


10 # define how to get/set/delet it.
11 @property
12 def name(self):
13 print("Function to get the name color")
14 return self._name
15

16 @name.setter
17 def name(self, new_name):
1.3. AGGREGATION AND COMPOSITION 15

18 print("Function to set the name as {}".format(new_name))


19 self._name = new_name
20

21 @name.deleter
22 def name(self):
23 print("Erase the name!!")
24 del self._name

1.3 Aggregation and Composition

In OOP there are different ways from which objects interact. Some objects are a composition of other objects who
only exists for that purpose. For instance, the object printed circuit board only exists inside a amplifier
and its existence only last while the amplifier exists. That kind of relationship is called composition. Another kind
of relationship between objects is aggregation, where a set of objects compose another object, but they may continue
existing even if the composed object no longer exist. For example, students and a teacher compose a classroom, but
both are not meant to be just part of that classroom, they may continue existing and interacting with other objects
even if that particular classroom disappears. In general, aggregation and composition concepts are different from the
modeling perspective. The use of them depends on the context and the problem abstraction. In Python, we can see
aggregation when the composed object receive instances of the components as arguments, while in composition, the
composed object instantiates the components at its initialization stage.

1.4 Inheritance

The inheritance concept allows us to model relationships like “object B is an object A but specialized in certain
functions”. We can see a subclass as a specialization of its superclass. For example, lets say we have a class called
Car which has attributes: brand, model and year; and methods: stop, charge_gas and fill_tires.
Assume that someone asks us to model a taxi, which is a car but has some additional specifications. Since we already
have defined the Car class, it makes sense somehow to re-use its attributes and methods to create a new Taxi class
(subclass). Of course, we have to add some specific attributes and methods to Taxi, like taximeter, fares or
create_receipt. However, if we do not take advantage of the Car superclass by inheriting from it, we will have
to repeat a lot of code. It makes our software much harder to maintain.

Besides inheriting attributes and methods from a superclass, inheritance allows us to “re-write” superclass methods.
Suppose that the subclass Motorcycle inherits from the class Vehicle. The method called fill_tires from
16 CHAPTER 1. OBJECT ORIENTED PROGRAMMING

Vehicle has to be changed inside Motorcycle, because motorcycles (in general) have two wheels instead of four.
In Python, to modify a method in the subclass we just need to write it again, this is called overriding, so that Python
understands that every time the last version of the method is the one that holds for the rest of the code.

A very useful application of inheritance is to create subclasses that inherit from some of the Python built-in classes, to
extend them into a more specialized class. For example, if we want to create a custom class similar to the built-in class
list, we just must create a subclass that inherits from list and write the new methods we want to add:

1 # grocery_list.py
2

4 class GroceryList(list):
5

6 def discard(self, price):


7 for product in self:
8 if product.price > price:
9 # remove method is implemented in the class "list"
10 self.remove(product)
11 return self
12

13 def __str__(self):
14 out = "Grocery List:\n\n"
15 for p in self:
16 out += "name: " + p.name + " - price: "
17 + str(p.price) + "\n"
18

19 return out
20

21

22 class Product:
23

24 def __init__(self, name, price):


25 self.name = name
26 self.price = price
27

28
1.5. MULTIPLE INHERITANCE 17

29 grocery_list = GroceryList()
30

31 # extend method also belongs to 'list' class


32 grocery_list.extend([Product("bread", 5),
33 Product("milk", 10), Product("rice", 12)])
34

35 print(grocery_list)
36 grocery_list.discard(11)
37 print(grocery_list)

Grocery List:

name: bread - price: 5


name: milk - price: 10
name: rice - price: 12

Grocery List:

name: bread - price: 5


name: milk - price: 10

Note that the __str__ method makes the class instance able to be printed out, in other words, if we call
print(grocery_list) it will print out the string returned by the __str__ method.

1.5 Multiple Inheritance

We can inherit from more than one class. For example, a professor might be a teacher and a researcher, so she/he
should inherit attributes and methods from both classes:

1 # multiple_inheritance.py
2

4 class Researcher:
5

6 def __init__(self, field):


7 self.field = field
18 CHAPTER 1. OBJECT ORIENTED PROGRAMMING

9 def __str__(self):
10 return "Research field: " + self.field + "\n"
11

12

13 class Teacher:
14

15 def __init__(self, courses_list):


16 self.courses_list = courses_list
17

18 def __str__(self):
19 out = "Courses: "
20 for c in self.courses_list:
21 out += c + ", "
22 # the [:-2] selects all the elements
23 # but the last two
24 return out[:-2] + "\n"
25

26

27 class Professor(Teacher, Researcher):


28

29 def __init__(self, name, field, courses_list):


30 # This is not completetly right
31 # Soon we will see why
32 Researcher.__init__(self, field)
33 Teacher.__init__(self, courses_list)
34 self.name = name
35

36 def __str__(self):
37 out = Researcher.__str__(self)
38 out += Teacher.__str__(self)
39 out += "Name: " + self.name + "\n"
40 return out
41

42
1.5. MULTIPLE INHERITANCE 19

43 p = Professor("Steve Iams",
44 "Meachine Learning",
45 [
46 "Python Programming",
47 "Probabilistic Graphical Models",
48 "Bayesian Inference"
49 ])
50

51 print(p)

#output

Research field: Meachine Learning


Courses: Python Programming, Probabilistic Graphical Models,
Bayesian Inference
Name: Steve Iams

Multiple Inheritance Problems

In Python, every class inherits from the Object class, that means, among other things, that every time we in-
stantiate a class, we are indirectly creating an instance of Object. Assume we have a class that inherits from
several superclasses. If we call to all the __init__ superclass methods, as we did in the previous example
(calling Researcher.__init__ and Teacher.__init__), we are calling the Object initializer twice:
Researcher.__init__ calls the initialization of Object and Teacher.__init__ calls the initialization of
Object as well. Initializing objects twice is not recommended. It is a waste of resources, especially in cases where
the initialization is expensive. It could be even worst. Imagine that the second initialization changes the setup done by
the first one, and probably the objects will not notice it. This situation is known as The Diamond Problem.

The following example (taken from [6]) shows what happens in the context of multiple-inheritance if each subclass
calls directly to initialize all its superclasses. Figure 1.1 indicates the hierarchy of the classes involved.

The example below (taken from [6]) shows what happens when we call the call() method in both superclasses from
SubClassA.

1 # diamond_problem.py
2
20 CHAPTER 1. OBJECT ORIENTED PROGRAMMING

Figure 1.1: The diamond problem

3 class ClassB:
4 num_calls_B = 0
5

6 def make_a_call(self):
7 print("Calling method in ClassB")
8 self.num_calls_B += 1
9

10

11 class LeftSubClass(ClassB):
12 num_left_calls = 0
13

14 def make_a_call(self):
15 ClassB.make_a_call(self)
16 print("Calling method in LeftSubClass")
17 self.num_left_calls += 1
18

19

20 class RightSubClass(ClassB):
21 num_right_calls = 0
1.5. MULTIPLE INHERITANCE 21

22

23 def make_a_call(self):
24 ClassB.make_a_call(self)
25 print("Calling method in RightSubClass")
26 self.num_right_calls += 1
27

28

29 class SubClassA(LeftSubClass, RightSubClass):


30 num_calls_subA = 0
31

32 def make_a_call(self):
33 LeftSubClass.make_a_call(self)
34 RightSubClass.make_a_call(self)
35 print("Calling method in SubClassA")
36 self.num_calls_subA += 1
37

38

39 if __name__ == '__main__':
40 s = SubClassA()
41 s.make_a_call()
42 print("SubClassA: {}".format(s.num_calls_subA))
43 print("LeftSubClass: {}".format(s.num_left_calls))
44 print("RightSubClass: {}".format(s.num_right_calls))
45 print("ClassB: {}".format(s.num_calls_B))

Calling method in ClassB


Calling method in LeftSubClass
Calling method in ClassB
Calling method in RightSubClass
Calling method in SubClassA
SubClassA: 1
LeftSubClass: 1
RightSubClass: 1
ClassB: 2

From the output, we can see that the upper class in the hierarchy (ClassB) is called twice, despite that we just directly
22 CHAPTER 1. OBJECT ORIENTED PROGRAMMING

call it once in the code.

Every time that one class inherits from two classes, a diamond structure is created. We refer the readers to
https://www.python.org/doc/newstyle/ for more details about new style classes. Following the same example shown
above, if instead of calling the make_a_call() method we call the __init__ method, we would be initializing
Object twice.

Solution to the diamond problem

One possible solution to the diamond problem is that each class must call the initialization of the superclass that
precedes it in the multiple inheritance resolution order. In Python, the order goes from left to right on the list of
superclasses from where the subclass inherits.

In this case, we just should call to super(), because Python will make sure to call the parent class in the multiple in-
heritance resolution order. In the previous example, after the subclass goes LeftSubclass, then RightSubClass,
and finally ClassB. From the following output, we can see that each class was initialized once:

1 # diamond_problem_solution.py
2

3 class ClassB:
4 num_calls_B = 0
5

6 def make_a_call(self):
7 print("Calling method in ClassB")
8 self.num_calls_B += 1
9

10

11 class LeftSubClass(ClassB):
12 num_left_calls = 0
13

14 def make_a_call(self):
15 super().make_a_call()
16 print("Calling method in LeftSubClass")
17 self.num_left_calls += 1
18

19
1.5. MULTIPLE INHERITANCE 23

20 class RightSubClass(ClassB):
21 num_right_calls = 0
22

23 def make_a_call(self):
24 super().make_a_call()
25 print("Calling method in RightSubClass")
26 self.num_right_calls += 1
27

28

29 class SubClassA(LeftSubClass, RightSubClass):


30 num_calls_subA = 0
31

32 def make_a_call(self):
33 super().make_a_call()
34 print("Calling method in SubClassA")
35 self.num_calls_subA += 1
36

37 if __name__ == '__main__':
38

39 s = SubClassA()
40 s.make_a_call()
41 print("SubClassA: {}".format(s.num_calls_subA))
42 print("LeftSubClass: {}".format(s.num_left_calls))
43 print("RightSubClass: {}".format(s.num_right_calls))
44 print("ClassB: {}".format(s.num_calls_B))

Calling method in ClassB


Calling method in RightSubClass
Calling method in LeftSubClass
Calling method in SubClassA
SubClassA: 1
LeftSubClass: 1
RightSubClass: 1
ClassB: 1
24 CHAPTER 1. OBJECT ORIENTED PROGRAMMING

Method Resolution Order

The mro method shows us the hierarchy order. It is very useful in more complex multiple-inheritance cases. Python
uses the C3 [3] algorithm to calculate a linear order among the classes involved in multiple inheritance schemes.

1 # mro.py
2

3 from diamond_problem_solution import SubClassA


4

5 for c in SubClassA.__mro__:
6 print(c)

<class ’diamond_problem_solution.SubClassA’>
<class ’diamond_problem_solution.LeftSubClass’>
<class ’diamond_problem_solution.RightSubClass’>
<class ’diamond_problem_solution.ClassB’>
<class ’object’>

The next example describes a case of an unrecommended initialization. The C3 algorithm generates an error because
it cannot create a logical order:

1 # invalid_structure.py
2

3 class X():
4 def call_me(self):
5 print("I'm X")
6

8 class Y():
9 def call_me(self):
10 print("I'm Y")
11

12

13 class A(X, Y):


14 def call_me(self):
15 print("I'm A")
16
1.5. MULTIPLE INHERITANCE 25

17

18 class B(Y, X):


19 def call_me(self):
20 print("I'm B")
21

22

23 class F(A, B):


24 def call_me(self):
25 print("I'm F")
26

27 # TypeError: Cannot create a consistent method resolution


28 # order (MRO) for bases X, Y

Traceback (most recent call last):


File "/codes/invalid_structure.py",
line 24, in <module>
class F(A, B):
TypeError: Cannot create a consistent method resolution
order (MRO) for bases X, Y

A Multiple Inheritance Example

Here we present another case of multiple-inheritance, showing the wrong and the right way to call the initialization of
superclasses:

Wrong initialization of the superclass’ __init__ method

Calling directly to superclasses’ __init__ method inside the class Customer, as we show in the next example, is
highly not recommended. We could initiate a superclass multiple times, as we mentioned previously. In this example,
a call to object’s __init__ is done twice:

1 # inheritance_wrong.py
2

4 class AddressHolder:
5

6 def __init__(self, street, number, city, state):


26 CHAPTER 1. OBJECT ORIENTED PROGRAMMING

7 self.street = street
8 self.number = number
9 self.city = city
10 self.state = state
11

12

13 class Contact:
14

15 contact_list = []
16

17 def __init__(self, name, email):


18 self.name = name
19 self.email = email
20 Contact.contact_list.append(self)
21

22

23 class Customer(Contact, AddressHolder):


24

25 def __init__(self, name, email, phone,


26 street, number, state, city):
27 Contact.__init__(self, name, email)
28 AddressHolder.__init__(self, street, number,
29 state, city)
30 self.phone = phone
31

32

33 if __name__ == "__main__":
34

35 c = Customer('John Davis', 'jp@g_mail.com', '23542331',


36 'Beacon Street', '231', 'Cambridge', 'Massachussets')
37

38 print("name: {}\nemail: {}\naddress: {}, {}"


39 .format(c.name, c.email, c.street, c.state))

name: John Davis


email: jp@g_mail.com
1.5. MULTIPLE INHERITANCE 27

address: Beacon Street, Massachussets

The right way: *args y **kwargs

Before showing the fixed version of the above example, we show how to use a list of arguments (*args) and keyword
arguments (**kwargs). In this case *args refers to a Non-keyword variable length argument list, where the
operator * unpacks the content inside the list args and pass them to a function as positional arguments.

1 # args_example.py
2

3 def method2(f_arg, *argv):


4 print("first arg normal: {}".format(f_arg))
5 for arg in argv:
6 print("the next arg is: {}".format(arg))
7

8 if __name__ == "__main__":
9 method2("Lorem", "ipsum", "ad", "his", "scripta")

first arg normal: Lorem


the next arg is: ipsum
the next arg is: ad
the next arg is: his
the next arg is: scripta

Similarly, **kwargs refers to a keyword variable-length argument list, where ** maps all the elements within the
dictionary kwargs and pass them to a function as non-positional arguments. This method is used to send a variable
amount of arguments to a function:

1 # kwargs_example.py
2

3 def method(arg1, arg2, arg3):


4 print("arg1: {}".format(arg1))
5 print("arg2: {}".format(arg2))
6 print("arg3: {}".format(arg3))
7

8
28 CHAPTER 1. OBJECT ORIENTED PROGRAMMING

9 if __name__ == "__main__":
10 kwargs = {"arg3": 3, "arg2": "two"}
11 method(1, **kwargs)

arg1: 1
arg2: two
arg3: 3

Now that we know how to use *args and **kwargs, we can figure out how to properly write an example of
multiple inheritance as shown before:

1 # inheritance_right.py
2

4 class AddressHolder:
5

6 def __init__(self, street, number, city, state, **kwargs):


7 super().__init__(**kwargs)
8 self.street = street
9 self.number = number
10 self.city = city
11 self.state = state
12

13

14 class Contact:
15 contact_list = []
16

17 def __init__(self, name, email, **kwargs):


18 super().__init__(**kwargs)
19 self.name = name
20 self.email = email
21 Contact.contact_list.append(self)
22

23

24 class Customer(Contact, AddressHolder):


25
1.5. MULTIPLE INHERITANCE 29

26 def __init__(self, phone_number, **kwargs):


27 super().__init__(**kwargs)
28 self.phone_number = phone_number
29

30

31 if __name__ == "__main__":
32

33 c = Customer(name='John Davis', email='jp@g_mail.com',


34 phone_number='23542331', street='Beacon Street',
35 number='231', city='Cambridge', state='Massachussets')
36

37 print("name: {}\nemail: {}\naddress: {}, {}".format(c.name, c.email,


38 c.street, c.state))

name: John Davis


email: jp@g_mail.com
address: Beacon Street, Massachussets

As we can see in the above example, each class manage its own arguments passing the rest of the non-used arguments
to the higher classes in the hierarchy. For example, Customer passes all the non-used argument (**args) to
Contact and to AddressHolder through the super() function.

Polymorfism

Imagine that we have the ChessPiece class. This class has six subclasses: King, Queen, Rook, Bishop,
Knight, and Pawn. Each subclass contains the move method, but that method behaves differently on each subclass.
The ability to call a method with the same name but with different behavior within subclasses is called Polymorphism.
There are mainly two flavors of polymorphism:

• Overriding: occurs when a subclass implements a method that replaces the same method previously implemented
in the superclass.

• Overloading: happens when a method is implemented more than once, having a different number of arguments
on each case. Python does not support overloading because it is not really necessary. Each method can have a
variable number of arguments by using a keyworded o non-keyworded list of arguments. Recall that in Python
every time we implement a method more than once, the last version is the only one that Python will use. Other
30 CHAPTER 1. OBJECT ORIENTED PROGRAMMING

programming languages support overloading, automatically detecting what method implementation to use
depending on the number of present arguments when the method is called.

The code bellow shows an example of Overriding. The Variable class represents data of any kind. The Income
class contains a method to calculate the representative value for it. In Income, the representative value is the average,
in City, the representative value is the most frequent city, and in JobTitle, the representative value is the job with
highest range, according to the _range dictionary:

1 # polymorfism_1.py
2

3 class Variable:
4 def __init__(self, data):
5 self.data = data
6

7 def representative(self):
8 pass
9

10

11 class Income(Variable):
12 def representative(self):
13 return sum(self.data) / len(self.data)
14

15

16 class City(Variable):
17 # class variable
18 _city_pop_size = {'Shanghai': 24000, 'Sao Paulo': 21300, 'Paris': 10800,
19 'London': 8600, 'Istambul': 15000,
20 'Tokyo': 13500, 'Moscow': 12200}
21

22 def representative(self):
23 dict = {City._city_pop_size[c]: c for c in self.data
24 if c in City._city_pop_size.keys()}
25 return dict[max(dict.keys())]
26

27

28 class JobTitle(Variable):
1.5. MULTIPLE INHERITANCE 31

29 # class variable
30 _range = {'CEO': 1, 'CTO': 2, 'Analyst': 3, 'Intern': 4}
31

32 def representative(self):
33 dict = {JobTitle._range[c]: c for c in self.data if
34 c in JobTitle._range.keys()}
35 return dict[min(dict.keys())]
36

37

38 if __name__ == "__main__":
39 income_list = Income([50, 80, 90, 150, 45, 65, 78, 89, 59, 77, 90])
40 city_list = City(['Shanghai', 'Sao Paulo', 'Paris', 'London',
41 'Istambul', 'Tokyo', 'Moscow'])
42 job_title_list = JobTitle(['CTO', 'Analyst', 'CEO', 'Intern'])
43 print(income_list.representative())
44 print(city_list.representative())
45 print(job_title_list.representative())

79.36363636363636
Shanghai
CEO

Operator Overriding

Python has several built-in operators that work for many of the built-in classes. For example, the operator “+” can
sum up two numbers, concatenate two strings, mix two lists, etc., depending on the object we are working with. The
following code shows an example:

1 # operator_overriding_1.py
2

3 a = [1, 2, 3, 4]
4 b = [5, 6, 7, 8]
5 print(a + b)
6

7 c = "Hello"
8 d = " World"
9 print(c + d)
32 CHAPTER 1. OBJECT ORIENTED PROGRAMMING

[1, 2, 3, 4, 5, 6, 7, 8]
Hello World

Thanks to polymorphism, we can also personalize the method __add__ to make it work on any particular class we
want. For example, we may need to create a specific way of adding two instances of the ShoppingCart class in the
following code:

1 # operator_overriding_2.py
2

3 class ShoppingCart:
4

5 def __init__(self, product_list):


6 self.product_list = product_list # Python dictionary
7

8 def __call__(self, product_list = None):


9 if product_list is None:
10 product_list = self.product_list
11 self.product_list = product_list
12

13 def __add__(self, other_cart):


14 added_list = self.product_list
15 for p in other_cart.product_list.keys():
16 if p in self.product_list.keys():
17 value = other_cart.product_list[p] + self.product_list[p]
18 added_list.update({p: value})
19 else:
20 added_list.update({p: other_cart.product_list[p]})
21

22 return ShoppingCart(added_list)
23

24 def __repr__(self):
25 return "\n".join("Product: {} | Quantity: {}".format(
26 p, self.product_list[p]) for p in self.product_list.keys()
27 )
28

29
1.5. MULTIPLE INHERITANCE 33

30 if __name__ == "__main__":
31 s_cart_1 = ShoppingCart({'muffin': 3, 'milk': 2, 'water': 6})
32 s_cart_2 = ShoppingCart({'milk': 5, 'soda': 2, 'beer': 12})
33 s_cart_3 = s_cart_1 + s_cart_2
34 print(s_cart_3.product_list)
35 print(s_cart_3)

{’soda’: 2, ’water’: 6, ’milk’: 7, ’beer’: 12, ’muffin’: 3}


Product: soda | Quantity: 2
Product: water | Quantity: 6
Product: milk | Quantity: 7
Product: beer | Quantity: 12
Product: muffin | Quantity: 3

The __repr__ method allows us to generate a string that will be used everytime we ask to print any instance of
the class. We could also implement the __str__ method instead, it works almost exactly as __repr__, the main
difference is that __str__ should be used when we need a user friendly print of the object instance, related to the
particular context where it is used. The __repr__ method should generate a more detailed printing, containing all the
necessary information to understand the instance. In cases where __str__ and __repr__ are both implemented,
Python will use __str__ when print(instance) is called. Hence, __repr__ will be used only if __str__
is not implemented.

There are other operators that we can override, for example “less than” (__lt__), “greather than” (__gt__) and
“equal” (__eq__). We refer the reader to https://docs.python.org/3.4/library/operator.html
for a detailed list of built-in operators. Here is an example that shows how to override the __lt__ method for
implementing the comparison between two elements of the Point class:

1 # operator_overriding_3.py
2

3 class Point:
4

5 def __init__(self, x, y):


6 self.x = x
7 self.y = y
8

9 def __lt__(self, other_point):


34 CHAPTER 1. OBJECT ORIENTED PROGRAMMING

10 self_mag = (self.x ** 2) + (self.y ** 2)


11 other_point_mag = (other_point.x ** 2) + (other_point.y ** 2)
12 return self_mag < other_point_mag
13

14 if __name__ == "__main__":
15 p1 = Point(2, 4)
16 p2 = Point(8, 3)
17 print(p1 < p2)

True

Duck Typing

The most common way to define it is "If it walks like a duck and quacks like a duck, then it is a duck." In other words,
it does not matter what kind of object performs the action, if it can do it, let it do it. Duck typing is a feature that
some programming languages have that makes polymorphism less attractive because it allows polymorphic behavior
without inheritance. In the next example, we can see that the activate function makes a duck scream and walk.
Despite that the method is implemented for Duck objects, it can be used with any object that has the scream and
walk methods implemented:

1 # duck_typing.py
2

4 class Duck:
5

6 def scream(self):
7 print("Cuack!")
8

9 def walk(self):
10 print("Walking like a duck...")
11

12

13 class Person:
14

15 def scream(self):
16 print("Ahhh!")
1.6. ABSTRACT BASE CLASS 35

17

18 def walk(self):
19 print("Walking like a human...")
20

21

22 def activate(duck):
23 duck.scream()
24 duck.walk()
25

26 if __name__ == "__main__":
27 Donald = Duck()
28 John = Person()
29 activate(Donald)
30 # this is not supported in other languajes, because John
31 # is not a Duck object
32 activate(John)

Cuack!
Walking like a duck...
Ahhh!
Walking like a human...

Typed programming languages that verify the type of objects during compilation time, such as C/C++, do not support
duck typing because in the list of arguments the object’s type has to be specified.

1.6 Abstract Base Class

Abstract classes in a programming language allow us to represent abstract objects better. What is an abstract object?
Abstract objects are created only to be inherited, so it does not make any sense to instantiate them. For example,
imagine that we have cars, buses, ships, and planes. Each one has similar properties (passengers capacity, color,
among others) and actions (load, move, stop) but they implement their methods differently: it is not the same to stop a
ship than a car. For this reason, we can create the class called Vehicle, to be a superclass of Car, Bus, Ship and
Plane.

Our problem now is how do we define Vehicle’s actions. We cannot define any of those behaviors inside Vehicle.
We can only do it inside any of its subclasses. That explains why it does not make any sense to instantiate the abstract
36 CHAPTER 1. OBJECT ORIENTED PROGRAMMING

class Vehicle. Hence, it is recommended to make sure that abstract classes are not going to be instantiated in the
code, by raising an exception in case any programmer attempts to instantiate it.

We can also have abstract methods, in other words, methods that have to be defined in the subclasses because their
implementation makes no sense to occur in the abstract class. Abstract classes can also have traditional (non abstract)
methods when they do not need to be modified withing the subclasses. Let’s try to define abstract classes and abstract
methods in Python. The following code shows an example:

1 # 01_abstract_1.py
2

3 class Base:
4 def func_1(self):
5 raise NotImplementedError()
6

7 def func_2(self):
8 raise NotImplementedError()
9

10 class SubClass(Base):
11 def func_1(self):
12 print("func_1() called...")
13 return
14

15 # We intentionally did not implement func_2


16

17 b1 = Base()
18 b2 = SubClass()
19 b2.func_1()
20 b2.func_2()

func_1() called...
-----------------------------------------------------
NotImplementedError Traceback (most recent call last)
<ipython-input-17-0803174cce17> in <module>()
16 b2 = SubClass()
17 b2.func_1()
---> 18 b2.func_2()
1.6. ABSTRACT BASE CLASS 37

<ipython-input-17-0803174cce17> in func_2(self)
4
5 def func_2(self):
----> 6 raise NotImplementedError()
7
8 class SubClass(Base):

NotImplementedError:

The problem with this approach is that the program lets us instantiate Base without complaining, that is not what we
want. It also allows us not to implement all the needed methods in the subclass. An Abstract class allows the class
designer to assert that the user will implement all the required methods in the respective subclasses.

Python, unlike other programming languages, does not have a built-in way to declare abstract classes. Fortunately,
we can import the ABC module (stands for Abstract Base Class), that satisfies our requirements. The following code
shows an example:

1 # 03_ABC_1.py
2

3 from abc import ABCMeta, abstractmethod


4

6 class Base(metaclass=ABCMeta):
7 @abstractmethod
8 def func_1(self):
9 pass
10

11 @abstractmethod
12 def func_2(self):
13 pass
14

15

16 class SubClass(Base):
17 def func_1(self):
18 pass
19
38 CHAPTER 1. OBJECT ORIENTED PROGRAMMING

20 # We intentionally did not implement func_2


21

22 print('Is it subclass?: {}'.format(issubclass(SubClass, Base)))


23 print('Is it instance?: {}'.format(isinstance(SubClass(), Base)))

Is it subclass?: True
-----------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-19-b1003dd6fd92> in <module>()
17
18 print(’Is it subclass?: {}’.format(issubclass(SubClass, Base)))
---> 19 print(’Is it instance?: {}’.format(isinstance(SubClass(), Base)))

TypeError: Can’t instantiate abstract class SubClass with abstract methods ’ \


’func_2

1 # 04_ABC_2.py
2

3 print('Trying to generate an instance of the Base class\n')


4 a = Base()

Trying to generate an instance of the Base class


---------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-20-e8aa694c9937> in <module>()
1 print(’Trying to generate an instance of the Base class\n’)
----> 2 a = Base()

TypeError: Can’t instantiate abstract class Base with abstract methods


func_1, func_2

Note that to declare a method as abstract we have to add the @abstractmethod decorator over its declaration. The
following code shows the implementation of the abstract methods:

1 # 05_ABC_3.py
2

3 from abc import ABCMeta, abstractmethod


1.7. CLASS DIAGRAMS 39

6 class Base(metaclass=ABCMeta):
7 @abstractmethod
8 def func_1(self):
9 pass
10

11 @abstractmethod
12 def func_2(self):
13 pass
14

15

16 class SubClass(Base):
17

18 def func_1(self):
19 pass
20

21 def func_2(self):
22 pass
23

24 # We forgot again to implement func_2


25

26 c = SubClass()
27 print('Subclass: {}'.format(issubclass(SubClass, Base)))
28 print('Instance: {}'.format(isinstance(SubClass(), Base)))

Subclass: True
Instance: True

1.7 Class Diagrams

By using class diagrams, we can visualize the classes that form most of the objects in our problem. Besides the classes,
we can also represent their properties, methods, and the way other classes interact with them. These diagrams belong
to a language known as Unified Modelling Language (UML). UML allows us to incorporate elements and tools to
model more complex systems, but it is out of the scope of this book. A class diagram is composed of a set of classes
40 CHAPTER 1. OBJECT ORIENTED PROGRAMMING

and their relations. Rectangles represent classes, and they have three fields; the class name, its data (attributes and
variables), and its methods. Figure 1.2 shows an example.

Figure 1.2: UML Class diagram example

Suppose that by using OOP we want to model a database with stars that exist in a given area of the Universe. Each
star is correspond to a set of T observations, where each observation is a tuple (mi , ti , ei ), where mi is the bright
magnitude of the star in observation i, ti is the time when the observation i was obtained, and ei is the instrumental
error associated with observation i. Using UML diagrams, we can model the system as shown in figure 1.3.

Figure 1.3: UML tables for the stars model

Consider now that the TimeSeries class has methods to add an observation to the time series and to return the
average and standard deviation of the set of observations that belong to the star. We can represent the class and the
mentioned methods as in figure 1.4.

Besides the classes, we can represent the relations among them using UML notation as well. The most common types
of relations are: composition, agreggation and inheritance (Concepts explained previously in this chapter). Figure 1.5
shows an example of Composition. This relation is represented by an arrow starting from the base object towards the
target that the class is composing. The base of the connector is a black diamond. The number at the beginning and end
of the arrow represent the cardinalities, in other words, the range of the number of objects included in each side of the
relation. In this example, the number one at the beginning of the arrow and the 1, . . . , ∗ at the end, mean that one Time
Series may include a set of one or more observations, respectively.
1.7. CLASS DIAGRAMS 41

Figure 1.4: UML table for the TimeSeries class including the add_observation, average and
standard_deviation methods.

Figure 1.5: Example of the composition relation between classes in a UML diagram.

Similarly, agreggation is represented as an arrow with a hollow diamond at the base. Figure 1.6 shows an example. As
we learn previously in this chapter, here the only difference is that the database aggregates time series, but the time
series objects are entities that have a significance even out of the database where they are aggregate.

Figure 1.6: Example of the agreggation relation between classes in a UML diagram.
42 CHAPTER 1. OBJECT ORIENTED PROGRAMMING

In UML, we represent the inheritance as a simple arrow with a hollow triangle at the head. To show an example,
consider the case of astronomical stars again. Imagine that some of the time series are periodic. It means
that there is a set of values repeated at a constant amount of time. According to that, we can define the subclass
PeriodicTimeSeries that inherits from the TimeSeries class its common attributes and behaviors. Figure
1.7 shows this example in a UML diagram. The complete UML diagram for the astronomical stars example is shown
in figure 1.8.

Figure 1.7: Example of the inheritance relation between classes in a UML diagram.

Figure 1.8: The complete UML diagram for the astronomical stars example.
1.8. HANDS-ON ACTIVITIES 43

1.8 Hands-On Activities

Activity 1.1

Variable stars are stars whose level of brightness changes with time. They are of considerable interest in the
astronomical community. Each star belongs to one of the possible classes of variability. Some of the classes are RR
Lyrae, Eclipsing Binaries, Mira, Long Period Variables, Cepheids, and Quasars. Each star has a position in the sky
represented by RA and DEC coordinates. Stars are represented by an identifier and contain a set of observations. Each
observation is a tuple with three values: time, magnitude and error. Time value indicates the moment in which the
telescope or the instrument does the observation. The magnitude indicates the amount of brightness calculated in the
observation. The error corresponds to a range of uncertainty associated with the measurement. Many fields compose
the sky, and each field contains a huge amount of stars. For each star, we need to know the average and the variance
of the bright magnitudes. Create the necessary Python classes which allow modeling the situation described above.
Classes must have the corresponding attributes and methods. Write code to instantiate the classes involved.

Activity 1.2

A software company is building a computer program that works with geometric shapes and needs help with the initial
model. The company is interested in making the model as extensible as possible.

• Each figure has:

– A property center as an ordered pair (x,y). It should be possible to access and set it. The constructor
needs one to build a figure.

– A method translate that receives an ordered pair (a, b) and sums to each of the center’s component,
the components in (a, b).

– A property perimeter that should be calculated with the figure’s dimensions.

– A property area that should be calculated with the figure’s dimensions.

– A method grow_area that enlarges the area of the figure x times, increasing its dimensions proportionally.
For example, in the case of a rectangle it should modify its width y length.

– A method grow_perimeter that enlarges the perimeter in x units, increasing its dimensions propor-
tionally. For example, in the case of a rectangle it should modify its width y length.

– Each time a figure is printed, the output should have the following format:
ClassName - Perimeter: value, Area: value, Center: (x, y)
Random documents with unrelated
content Scribd suggests to you:
an Inclined Plane. The Normal Air-pressure on a Thin Plane Inclined
at an Angle to the Direction of Motion. Lilienthal’s Balance of
Rotation. The Numerical Value of the Normal Pressure. Flying in
General. Flying in Reality. Horizontal Flight by Wing-Flapping.
Steering and other Effects of the Stroke. Conclusions. 23
illustrations, 8vo., paper. 75c.
FLIGHT-VELOCITY. By A. Samuelson. This work is a short
comprehension of extensive scientific investigation and experimental
work. Contents: The Rowing Flyer No. 5. The Motor Mechanism. The
Fundamental Conditions of Flying by Wing Flapping. The Wings. The
Re-sail. Flight Velocity. Living Flyers. Plane or Concave Supporting
Surfaces. The False Resolution of Forces. The Erroneous Opinion:
the Breadth of an Incline Plane Prevails over its Length. The Centre
of Air-pressure, and the Distribution of the Pressure. On the Single
Parts of an Inclined Plane. The Principle: the Normal Air-pressure of
an Inclined Plane is independent of the Angle of Inclination. Tables
of Motion at Varying Angles. The Human Flight. Conclusions. With
five plates, 8vo., paper. 75c.
FLYING MACHINES. Past, Present and Future. A popular
account of flying machines, dirigible balloons. By A. W. Marshall and
H. Greenly. Whilst the matter in this book is intended as a popular
exhibition of the subject, it includes information which will assist the
reader with serious intentions of making an attempt to produce a
flying machine or air-ship. A great deal of sound experimental work
has been done, forming a basis upon which future plans can be
calculated. An account of some of this work is here given. Contents
of Chapters: 1. Introduction. Dr. Barton’s Air-ship. Lebaudy’s Military
Air-ship. The Deutsch Air-ship. The Wellman Air-ship. Motors of the
Wellman Air-ship. Chapter 2. Dirigible Balloons. Giffard’s. Dupuy de
Lome. Tissandiers’. Krebes’. Santos Dumont’s, No. 6 and No. 9.
Spencer’s Air-ship. Barton’s. Maxim’s Flying Machine. Archdeacon’s
Air Propeller Cycle. Barton’s, Rawson’s, Baulx, Zeppelin, Deutsch,
Lambert, Wellman’s Air-ships. Trolanini’s Air-propelled Boat. Chapter
3. Flying Machines. Giving a Number of those made by Hargrave and
also by Phillips, Ader, Maxim, Pilsher’s Soaring Wings, Langley,
Bastine, Bleirot, Voison, Wright’s Gliding Aeroplane, and numerous
others. Chapter 4. The Art of Flying. Chapter 5. Flying Machines of
the Future. 134 pages, illustrations and page plates, 12mo.
50c.

MODEL AEROPLANES.

MODEL FLYING MACHINES, THEIR DESIGN AND


CONSTRUCTION. By W. G. Aston. Contents of chapters:—1.
General principles and their application. 2. Power. 3. Supporting
surfaces. 4. Screws, and how to make them. 5. Tails and elevators.
6. Fins. 7. Designs. With a number of examples of monoplane, bi-
plane, tandem bi-plane and tri-plane models. 8. Dirigibles. 9.
Helicopters. 10. Ornithopters. 11. Winding apparatus. 12.
Compressed air motor. A first-rate book for Model Makers, 125
pages, 95 illustrations, 12mo. boards, postpaid, for 55c.
MODEL GLIDERS, BIRDS, BUTTERFLIES AND
AEROPLANES. How to Make and Fly Them. A booklet with one
large sheet containing twelve butterflies and two birds in colors and
material for making a small card-board Model Aeroplane Glider.
Complete in folder, postpaid, for 55c.
MODEL AEROPLANES, HOW TO BUILD AND FLY THEM. By
E. W. Twining. Consisting of one booklet and five large scaled
drawings for three Twining Models, two of them being of the Bi-
plane Glider type. Complete in folder, postpaid, for 55c.
TWINING’S MODEL NO. 2. A complete set of the materials in
the rough, including the rubber of a Bi-plane Model without the
drawings, postpaid, for 65c.
TWINING'S MODEL NO. 3. A complete set of materials in the
rough with rubber for the construction of this handsome Model Bi-
plane without the drawings, postpaid, for $1.15.
THE AEROPLANE PORTFOLIO. By D. Ross Kennedy.
Containing nine sheets of scale drawings of the following celebrated
Aeroplanes: Bi-plane type—Wright, Farman, Voisin, Cody, Herring-
Curtis. Monoplanes—Rep. Antoinette, Santos Dumont, and Bleriot.
Each of these machines are here shown in End View, Plan and
Elevation. Including booklet which contains a description of each
machine. This timely set of drawings should prove of value to
everyone interested in this important new industry. The complete set
in folder, postpaid, for 55c.
THE PERCY PIERCE FLYER. A large scale drawing of this
prize-winning Monoplane. With all measurements and details
showing a front elevation, a side elevation and a top elevation; with
8-page descriptive booklet of particulars postpaid, 15c.
PERCY PIERCE DRAWING, with booklet and complete set of
materials in the rough from which any one can make an exact
duplicate of this dandy Model complete, postpaid, for $1.15.
A THREE-FOOT MODEL AEROPLANE. Bleriot Type. By G. E.
Alexander. A large scale drawing with measurements and descriptive
matter showing the construction of a splendid Model Flying Machine.
The Model from which this drawing is taken has proved a very
successful flyer, postpaid for 15c.

GOOD BOOKS FOR WIRELESS OPERATORS.

PART I. PLANS AND SPECIFICATIONS FOR WIRELESS TELEGRAPH


SETS, Complete and Detailed Instruction for Making an Experimental
Set, also a One to Five Mile Set, 55 pages, 37 illustrations; price 25c.
Part 2. PLANS AND SPECIFICATIONS FOR WIRELESS
TELEGRAPH SETS. By A. Frederick Collins. Will contain complete and
detailed data for constructing a Five to Ten Mile Set, also a Ten to
Twenty-five Mile Set, with about 60 illustrations, and 90 pages. Price,
25c.
Parts three and four in preparation.
MAKING WIRELESS OUTFITS. By Newton Harrison. A concise
and simple explanation on the construction and use of simple and
inexpensive wireless equipments, for sending and receiving, giving
full details and drawings of apparatus, diagrams of circuits and
tables. Including the Morse and Continental Codes. 61 pages, 27
illustrations. Price, 25c.; cloth, 50c.
WIRELESS TELEPHONE CONSTRUCTION. By Newton Harrison.
A comprehensive explanation of the making of a Wireless Telephone
Equipment. Both the transmitting and receiving stations fully
explained with details of construction sufficient to give an intelligent
reader a good start in building a Wireless Telephone system and in
operating it. 74 pages and 43 illustrations. Price, 25c.
TELEGRAPHY FOR BEGINNERS. The Standard Method. An
authoritative book of instruction in the methods and forms most
approved, with a series of lessons. By Willis H. Jones. With the
Morse alphabet and the Continental code. 64 pages, 19 illustrations,
paper binding, 25c.; cloth binding, 50c.
INDUCTION COILS. How to Make and Use Them. By P. Marshall.
A practical handbook on the construction and use of sparking coils
for wireless telegraphy. With tables of windings for coils giving 1/4
in. spark up to 12 in. sparks. With full description for the
construction of mercury interrupters. 76 pages, 35 illustrations.
Price, 25c.; cloth binding, 50c.
Full descriptive circular of The Model Library Series of practical
Handbooks FREE.

*** END OF THIS PROJECT GUTENBERG EBOOK HOW TO BUILD A


20-FOOT BI-PLANE GLIDER ***
*** END OF THE PROJECT GUTENBERG EBOOK HOW TO BUILD A
20-FOOT BI-PLANE GLIDER ***

Updated editions will replace the previous one—the old editions will
be renamed.

Creating the works from print editions not protected by U.S.


copyright law means that no one owns a United States copyright in
these works, so the Foundation (and you!) can copy and distribute it
in the United States without permission and without paying
copyright royalties. Special rules, set forth in the General Terms of
Use part of this license, apply to copying and distributing Project
Gutenberg™ electronic works to protect the PROJECT GUTENBERG™
concept and trademark. Project Gutenberg is a registered trademark,
and may not be used if you charge for an eBook, except by following
the terms of the trademark license, including paying royalties for use
of the Project Gutenberg trademark. If you do not charge anything
for copies of this eBook, complying with the trademark license is
very easy. You may use this eBook for nearly any purpose such as
creation of derivative works, reports, performances and research.
Project Gutenberg eBooks may be modified and printed and given
away—you may do practically ANYTHING in the United States with
eBooks not protected by U.S. copyright law. Redistribution is subject
to the trademark license, especially commercial redistribution.

START: FULL LICENSE


THE FULL PROJECT GUTENBERG LICENSE
PLEASE READ THIS BEFORE YOU DISTRIBUTE OR USE THIS WORK

To protect the Project Gutenberg™ mission of promoting the free


distribution of electronic works, by using or distributing this work (or
any other work associated in any way with the phrase “Project
Gutenberg”), you agree to comply with all the terms of the Full
Project Gutenberg™ License available with this file or online at
www.gutenberg.org/license.

Section 1. General Terms of Use and


Redistributing Project Gutenberg™ electronic
works
1.A. By reading or using any part of this Project Gutenberg™
electronic work, you indicate that you have read, understand, agree
to and accept all the terms of this license and intellectual property
(trademark/copyright) agreement. If you do not agree to abide by all
the terms of this agreement, you must cease using and return or
destroy all copies of Project Gutenberg™ electronic works in your
possession. If you paid a fee for obtaining a copy of or access to a
Project Gutenberg™ electronic work and you do not agree to be
bound by the terms of this agreement, you may obtain a refund
from the person or entity to whom you paid the fee as set forth in
paragraph 1.E.8.

1.B. “Project Gutenberg” is a registered trademark. It may only be


used on or associated in any way with an electronic work by people
who agree to be bound by the terms of this agreement. There are a
few things that you can do with most Project Gutenberg™ electronic
works even without complying with the full terms of this agreement.
See paragraph 1.C below. There are a lot of things you can do with
Project Gutenberg™ electronic works if you follow the terms of this
agreement and help preserve free future access to Project
Gutenberg™ electronic works. See paragraph 1.E below.
1.C. The Project Gutenberg Literary Archive Foundation (“the
Foundation” or PGLAF), owns a compilation copyright in the
collection of Project Gutenberg™ electronic works. Nearly all the
individual works in the collection are in the public domain in the
United States. If an individual work is unprotected by copyright law
in the United States and you are located in the United States, we do
not claim a right to prevent you from copying, distributing,
performing, displaying or creating derivative works based on the
work as long as all references to Project Gutenberg are removed. Of
course, we hope that you will support the Project Gutenberg™
mission of promoting free access to electronic works by freely
sharing Project Gutenberg™ works in compliance with the terms of
this agreement for keeping the Project Gutenberg™ name associated
with the work. You can easily comply with the terms of this
agreement by keeping this work in the same format with its attached
full Project Gutenberg™ License when you share it without charge
with others.

1.D. The copyright laws of the place where you are located also
govern what you can do with this work. Copyright laws in most
countries are in a constant state of change. If you are outside the
United States, check the laws of your country in addition to the
terms of this agreement before downloading, copying, displaying,
performing, distributing or creating derivative works based on this
work or any other Project Gutenberg™ work. The Foundation makes
no representations concerning the copyright status of any work in
any country other than the United States.

1.E. Unless you have removed all references to Project Gutenberg:

1.E.1. The following sentence, with active links to, or other


immediate access to, the full Project Gutenberg™ License must
appear prominently whenever any copy of a Project Gutenberg™
work (any work on which the phrase “Project Gutenberg” appears,
or with which the phrase “Project Gutenberg” is associated) is
accessed, displayed, performed, viewed, copied or distributed:
This eBook is for the use of anyone anywhere in the
United States and most other parts of the world at no
cost and with almost no restrictions whatsoever. You
may copy it, give it away or re-use it under the terms
of the Project Gutenberg License included with this
eBook or online at www.gutenberg.org. If you are not
located in the United States, you will have to check the
laws of the country where you are located before using
this eBook.

1.E.2. If an individual Project Gutenberg™ electronic work is derived


from texts not protected by U.S. copyright law (does not contain a
notice indicating that it is posted with permission of the copyright
holder), the work can be copied and distributed to anyone in the
United States without paying any fees or charges. If you are
redistributing or providing access to a work with the phrase “Project
Gutenberg” associated with or appearing on the work, you must
comply either with the requirements of paragraphs 1.E.1 through
1.E.7 or obtain permission for the use of the work and the Project
Gutenberg™ trademark as set forth in paragraphs 1.E.8 or 1.E.9.

1.E.3. If an individual Project Gutenberg™ electronic work is posted


with the permission of the copyright holder, your use and distribution
must comply with both paragraphs 1.E.1 through 1.E.7 and any
additional terms imposed by the copyright holder. Additional terms
will be linked to the Project Gutenberg™ License for all works posted
with the permission of the copyright holder found at the beginning
of this work.

1.E.4. Do not unlink or detach or remove the full Project


Gutenberg™ License terms from this work, or any files containing a
part of this work or any other work associated with Project
Gutenberg™.

1.E.5. Do not copy, display, perform, distribute or redistribute this


electronic work, or any part of this electronic work, without
prominently displaying the sentence set forth in paragraph 1.E.1
with active links or immediate access to the full terms of the Project
Gutenberg™ License.

1.E.6. You may convert to and distribute this work in any binary,
compressed, marked up, nonproprietary or proprietary form,
including any word processing or hypertext form. However, if you
provide access to or distribute copies of a Project Gutenberg™ work
in a format other than “Plain Vanilla ASCII” or other format used in
the official version posted on the official Project Gutenberg™ website
(www.gutenberg.org), you must, at no additional cost, fee or
expense to the user, provide a copy, a means of exporting a copy, or
a means of obtaining a copy upon request, of the work in its original
“Plain Vanilla ASCII” or other form. Any alternate format must
include the full Project Gutenberg™ License as specified in
paragraph 1.E.1.

1.E.7. Do not charge a fee for access to, viewing, displaying,


performing, copying or distributing any Project Gutenberg™ works
unless you comply with paragraph 1.E.8 or 1.E.9.

1.E.8. You may charge a reasonable fee for copies of or providing


access to or distributing Project Gutenberg™ electronic works
provided that:

• You pay a royalty fee of 20% of the gross profits you derive
from the use of Project Gutenberg™ works calculated using the
method you already use to calculate your applicable taxes. The
fee is owed to the owner of the Project Gutenberg™ trademark,
but he has agreed to donate royalties under this paragraph to
the Project Gutenberg Literary Archive Foundation. Royalty
payments must be paid within 60 days following each date on
which you prepare (or are legally required to prepare) your
periodic tax returns. Royalty payments should be clearly marked
as such and sent to the Project Gutenberg Literary Archive
Foundation at the address specified in Section 4, “Information
about donations to the Project Gutenberg Literary Archive
Foundation.”

• You provide a full refund of any money paid by a user who


notifies you in writing (or by e-mail) within 30 days of receipt
that s/he does not agree to the terms of the full Project
Gutenberg™ License. You must require such a user to return or
destroy all copies of the works possessed in a physical medium
and discontinue all use of and all access to other copies of
Project Gutenberg™ works.

• You provide, in accordance with paragraph 1.F.3, a full refund of


any money paid for a work or a replacement copy, if a defect in
the electronic work is discovered and reported to you within 90
days of receipt of the work.

• You comply with all other terms of this agreement for free
distribution of Project Gutenberg™ works.

1.E.9. If you wish to charge a fee or distribute a Project Gutenberg™


electronic work or group of works on different terms than are set
forth in this agreement, you must obtain permission in writing from
the Project Gutenberg Literary Archive Foundation, the manager of
the Project Gutenberg™ trademark. Contact the Foundation as set
forth in Section 3 below.

1.F.

1.F.1. Project Gutenberg volunteers and employees expend


considerable effort to identify, do copyright research on, transcribe
and proofread works not protected by U.S. copyright law in creating
the Project Gutenberg™ collection. Despite these efforts, Project
Gutenberg™ electronic works, and the medium on which they may
be stored, may contain “Defects,” such as, but not limited to,
incomplete, inaccurate or corrupt data, transcription errors, a
copyright or other intellectual property infringement, a defective or
damaged disk or other medium, a computer virus, or computer
codes that damage or cannot be read by your equipment.

1.F.2. LIMITED WARRANTY, DISCLAIMER OF DAMAGES - Except for


the “Right of Replacement or Refund” described in paragraph 1.F.3,
the Project Gutenberg Literary Archive Foundation, the owner of the
Project Gutenberg™ trademark, and any other party distributing a
Project Gutenberg™ electronic work under this agreement, disclaim
all liability to you for damages, costs and expenses, including legal
fees. YOU AGREE THAT YOU HAVE NO REMEDIES FOR
NEGLIGENCE, STRICT LIABILITY, BREACH OF WARRANTY OR
BREACH OF CONTRACT EXCEPT THOSE PROVIDED IN PARAGRAPH
1.F.3. YOU AGREE THAT THE FOUNDATION, THE TRADEMARK
OWNER, AND ANY DISTRIBUTOR UNDER THIS AGREEMENT WILL
NOT BE LIABLE TO YOU FOR ACTUAL, DIRECT, INDIRECT,
CONSEQUENTIAL, PUNITIVE OR INCIDENTAL DAMAGES EVEN IF
YOU GIVE NOTICE OF THE POSSIBILITY OF SUCH DAMAGE.

1.F.3. LIMITED RIGHT OF REPLACEMENT OR REFUND - If you


discover a defect in this electronic work within 90 days of receiving
it, you can receive a refund of the money (if any) you paid for it by
sending a written explanation to the person you received the work
from. If you received the work on a physical medium, you must
return the medium with your written explanation. The person or
entity that provided you with the defective work may elect to provide
a replacement copy in lieu of a refund. If you received the work
electronically, the person or entity providing it to you may choose to
give you a second opportunity to receive the work electronically in
lieu of a refund. If the second copy is also defective, you may
demand a refund in writing without further opportunities to fix the
problem.

1.F.4. Except for the limited right of replacement or refund set forth
in paragraph 1.F.3, this work is provided to you ‘AS-IS’, WITH NO
OTHER WARRANTIES OF ANY KIND, EXPRESS OR IMPLIED,
INCLUDING BUT NOT LIMITED TO WARRANTIES OF
MERCHANTABILITY OR FITNESS FOR ANY PURPOSE.

1.F.5. Some states do not allow disclaimers of certain implied


warranties or the exclusion or limitation of certain types of damages.
If any disclaimer or limitation set forth in this agreement violates the
law of the state applicable to this agreement, the agreement shall be
interpreted to make the maximum disclaimer or limitation permitted
by the applicable state law. The invalidity or unenforceability of any
provision of this agreement shall not void the remaining provisions.

1.F.6. INDEMNITY - You agree to indemnify and hold the Foundation,


the trademark owner, any agent or employee of the Foundation,
anyone providing copies of Project Gutenberg™ electronic works in
accordance with this agreement, and any volunteers associated with
the production, promotion and distribution of Project Gutenberg™
electronic works, harmless from all liability, costs and expenses,
including legal fees, that arise directly or indirectly from any of the
following which you do or cause to occur: (a) distribution of this or
any Project Gutenberg™ work, (b) alteration, modification, or
additions or deletions to any Project Gutenberg™ work, and (c) any
Defect you cause.

Section 2. Information about the Mission of


Project Gutenberg™
Project Gutenberg™ is synonymous with the free distribution of
electronic works in formats readable by the widest variety of
computers including obsolete, old, middle-aged and new computers.
It exists because of the efforts of hundreds of volunteers and
donations from people in all walks of life.

Volunteers and financial support to provide volunteers with the


assistance they need are critical to reaching Project Gutenberg™’s
goals and ensuring that the Project Gutenberg™ collection will
remain freely available for generations to come. In 2001, the Project
Gutenberg Literary Archive Foundation was created to provide a
secure and permanent future for Project Gutenberg™ and future
generations. To learn more about the Project Gutenberg Literary
Archive Foundation and how your efforts and donations can help,
see Sections 3 and 4 and the Foundation information page at
www.gutenberg.org.

Section 3. Information about the Project


Gutenberg Literary Archive Foundation
The Project Gutenberg Literary Archive Foundation is a non-profit
501(c)(3) educational corporation organized under the laws of the
state of Mississippi and granted tax exempt status by the Internal
Revenue Service. The Foundation’s EIN or federal tax identification
number is 64-6221541. Contributions to the Project Gutenberg
Literary Archive Foundation are tax deductible to the full extent
permitted by U.S. federal laws and your state’s laws.

The Foundation’s business office is located at 809 North 1500 West,


Salt Lake City, UT 84116, (801) 596-1887. Email contact links and up
to date contact information can be found at the Foundation’s website
and official page at www.gutenberg.org/contact

Section 4. Information about Donations to the


Project Gutenberg Literary Archive Foundation
Project Gutenberg™ depends upon and cannot survive without
widespread public support and donations to carry out its mission of
increasing the number of public domain and licensed works that can
be freely distributed in machine-readable form accessible by the
widest array of equipment including outdated equipment. Many
small donations ($1 to $5,000) are particularly important to
maintaining tax exempt status with the IRS.
The Foundation is committed to complying with the laws regulating
charities and charitable donations in all 50 states of the United
States. Compliance requirements are not uniform and it takes a
considerable effort, much paperwork and many fees to meet and
keep up with these requirements. We do not solicit donations in
locations where we have not received written confirmation of
compliance. To SEND DONATIONS or determine the status of
compliance for any particular state visit www.gutenberg.org/donate.

While we cannot and do not solicit contributions from states where


we have not met the solicitation requirements, we know of no
prohibition against accepting unsolicited donations from donors in
such states who approach us with offers to donate.

International donations are gratefully accepted, but we cannot make


any statements concerning tax treatment of donations received from
outside the United States. U.S. laws alone swamp our small staff.

Please check the Project Gutenberg web pages for current donation
methods and addresses. Donations are accepted in a number of
other ways including checks, online payments and credit card
donations. To donate, please visit: www.gutenberg.org/donate.

Section 5. General Information About Project


Gutenberg™ electronic works
Professor Michael S. Hart was the originator of the Project
Gutenberg™ concept of a library of electronic works that could be
freely shared with anyone. For forty years, he produced and
distributed Project Gutenberg™ eBooks with only a loose network of
volunteer support.

Project Gutenberg™ eBooks are often created from several printed


editions, all of which are confirmed as not protected by copyright in
the U.S. unless a copyright notice is included. Thus, we do not
necessarily keep eBooks in compliance with any particular paper
edition.

Most people start at our website which has the main PG search
facility: www.gutenberg.org.

This website includes information about Project Gutenberg™,


including how to make donations to the Project Gutenberg Literary
Archive Foundation, how to help produce our new eBooks, and how
to subscribe to our email newsletter to hear about new eBooks.
The Full Project Gutenberg License

Please read this before you distribute or use this work.


To protect the Project Gutenberg™ mission of promoting the
free distribution of electronic works, by using or distributing this
work (or any other work associated in any way with the phrase
“Project Gutenberg”), you agree to comply with all the terms of the
Full Project Gutenberg™ License available with this file or online at
https://www.gutenberg.org/license.

Section 1. General Terms of Use &


Redistributing Project Gutenberg™ electronic
works

1.A. By reading or using any part of this Project Gutenberg™


electronic work, you indicate that you have read, understand, agree
to and accept all the terms of this license and intellectual property
(trademark/copyright) agreement. If you do not agree to abide by all
the terms of this agreement, you must cease using and return or
destroy all copies of Project Gutenberg™ electronic works in your
possession. If you paid a fee for obtaining a copy of or access to a
Project Gutenberg™ electronic work and you do not agree to be
bound by the terms of this agreement, you may obtain a refund
from the person or entity to whom you paid the fee as set forth in
paragraph 1.E.8.
1.B. “Project Gutenberg” is a registered trademark. It may only
be used on or associated in any way with an electronic work by
people who agree to be bound by the terms of this agreement.
There are a few things that you can do with most Project
Gutenberg™ electronic works even without complying with the full
terms of this agreement. See paragraph 1.C below. There are a lot
of things you can do with Project Gutenberg™ electronic works if
you follow the terms of this agreement and help preserve free future
access to Project Gutenberg™ electronic works. See paragraph 1.E
below.
1.C. The Project Gutenberg Literary Archive Foundation (“the
Foundation” or PGLAF), owns a compilation copyright in the
collection of Project Gutenberg™ electronic works. Nearly all the
individual works in the collection are in the public domain in the
United States. If an individual work is unprotected by copyright law
in the United States and you are located in the United States, we do
not claim a right to prevent you from copying, distributing,
performing, displaying or creating derivative works based on the
work as long as all references to Project Gutenberg are removed. Of
course, we hope that you will support the Project Gutenberg™
mission of promoting free access to electronic works by freely
sharing Project Gutenberg™ works in compliance with the terms of
this agreement for keeping the Project Gutenberg™ name associated
with the work. You can easily comply with the terms of this
agreement by keeping this work in the same format with its attached
full Project Gutenberg™ License when you share it without charge
with others.
1.D. The copyright laws of the place where you are located also
govern what you can do with this work. Copyright laws in most
countries are in a constant state of change. If you are outside the
United States, check the laws of your country in addition to the
terms of this agreement before downloading, copying, displaying,
performing, distributing or creating derivative works based on this
work or any other Project Gutenberg™ work. The Foundation makes
no representations concerning the copyright status of any work in
any country outside the United States.
1.E. Unless you have removed all references to Project
Gutenberg:
1.E.1. The following sentence, with active links to, or other
immediate access to, the full Project Gutenberg™ License must
appear prominently whenever any copy of a Project Gutenberg™
work (any work on which the phrase “Project Gutenberg” appears,
or with which the phrase “Project Gutenberg” is associated) is
accessed, displayed, performed, viewed, copied or distributed:

This eBook is for the use of anyone anywhere in the


United States and most other parts of the world at no
cost and with almost no restrictions whatsoever. You
may copy it, give it away or re-use it under the terms
of the Project Gutenberg License included with this
eBook or online at https://www.gutenberg.org . If you
are not located in the United States, you'll have to
check the laws of the country where you are located
before using this ebook.

1.E.2. If an individual Project Gutenberg™ electronic work is derived


from texts not protected by U.S. copyright law (does not contain a
notice indicating that it is posted with permission of the copyright
holder), the work can be copied and distributed to anyone in the
United States without paying any fees or charges. If you are
redistributing or providing access to a work with the phrase “Project
Gutenberg” associated with or appearing on the work, you must
comply either with the requirements of paragraphs 1.E.1 through
1.E.7 or obtain permission for the use of the work and the Project
Gutenberg™ trademark as set forth in paragraphs 1.E.8 or 1.E.9.
1.E.3. If an individual Project Gutenberg™ electronic work is
posted with the permission of the copyright holder, your use and
distribution must comply with both paragraphs 1.E.1 through 1.E.7
and any additional terms imposed by the copyright holder. Additional
terms will be linked to the Project Gutenberg™ License for all works
posted with the permission of the copyright holder found at the
beginning of this work.
1.E.4. Do not unlink or detach or remove the full Project
Gutenberg™ License terms from this work, or any files containing a
part of this work or any other work associated with Project
Gutenberg™.
1.E.5. Do not copy, display, perform, distribute or redistribute
this electronic work, or any part of this electronic work, without
prominently displaying the sentence set forth in paragraph 1.E.1
with active links or immediate access to the full terms of the Project
Gutenberg™ License.
1.E.6. You may convert to and distribute this work in any
binary, compressed, marked up, nonproprietary or proprietary form,
including any word processing or hypertext form. However, if you
provide access to or distribute copies of a Project Gutenberg™ work
in a format other than “Plain Vanilla ASCII” or other format used in
the official version posted on the official Project Gutenberg™ web
site (https://www.gutenberg.org), you must, at no additional cost,
fee or expense to the user, provide a copy, a means of exporting a
copy, or a means of obtaining a copy upon request, of the work in its
original “Plain Vanilla ASCII” or other form. Any alternate format
must include the full Project Gutenberg™ License as specified in
paragraph 1.E.1.
1.E.7. Do not charge a fee for access to, viewing, displaying,
performing, copying or distributing any Project Gutenberg™ works
unless you comply with paragraph 1.E.8 or 1.E.9.
1.E.8. You may charge a reasonable fee for copies of or
providing access to or distributing Project Gutenberg™ electronic
works provided that

You pay a royalty fee of 20% of the gross profits you derive
from the use of Project Gutenberg™ works calculated using the
method you already use to calculate your applicable taxes. The
fee is owed to the owner of the Project Gutenberg™ trademark,
but he has agreed to donate royalties under this paragraph to
the Project Gutenberg Literary Archive Foundation. Royalty
payments must be paid within 60 days following each date on
which you prepare (or are legally required to prepare) your
periodic tax returns. Royalty payments should be clearly marked
as such and sent to the Project Gutenberg Literary Archive
Foundation at the address specified in Section 4, “Information
about donations to the Project Gutenberg Literary Archive
Foundation.”

You provide a full refund of any money paid by a user who


notifies you in writing (or by e-mail) within 30 days of receipt
that s/he does not agree to the terms of the full Project
Gutenberg™ License. You must require such a user to return or
destroy all copies of the works possessed in a physical medium
and discontinue all use of and all access to other copies of
Project Gutenberg™ works.

You provide, in accordance with paragraph 1.F.3, a full refund of


any money paid for a work or a replacement copy, if a defect in
the electronic work is discovered and reported to you within 90
days of receipt of the work.

You comply with all other terms of this agreement for free
distribution of Project Gutenberg™ works.

1.E.9. If you wish to charge a fee or distribute a Project


Gutenberg™ electronic work or group of works on different terms
than are set forth in this agreement, you must obtain permission in
writing from both the Project Gutenberg Literary Archive Foundation
and The Project Gutenberg Trademark LLC, the owner of the Project
Gutenberg™ trademark. Contact the Foundation as set forth in
Section 3. below.
1.F.
1.F.1. Project Gutenberg volunteers and employees expend
considerable effort to identify, do copyright research on, transcribe
and proofread works not protected by U.S. copyright law in creating
the Project Gutenberg™ collection. Despite these efforts, Project
Gutenberg™ electronic works, and the medium on which they may
be stored, may contain “Defects,” such as, but not limited to,
incomplete, inaccurate or corrupt data, transcription errors, a
copyright or other intellectual property infringement, a defective or
damaged disk or other medium, a computer virus, or computer
codes that damage or cannot be read by your equipment.
1.F.2. LIMITED WARRANTY, DISCLAIMER OF DAMAGES –
Except for the “Right of Replacement or Refund” described in
paragraph 1.F.3, the Project Gutenberg Literary Archive Foundation,
the owner of the Project Gutenberg™ trademark, and any other
party distributing a Project Gutenberg™ electronic work under this
agreement, disclaim all liability to you for damages, costs and
expenses, including legal fees. YOU AGREE THAT YOU HAVE NO
REMEDIES FOR NEGLIGENCE, STRICT LIABILITY, BREACH OF
WARRANTY OR BREACH OF CONTRACT EXCEPT THOSE PROVIDED
IN PARAGRAPH 1.F.3. YOU AGREE THAT THE FOUNDATION, THE
TRADEMARK OWNER, AND ANY DISTRIBUTOR UNDER THIS
AGREEMENT WILL NOT BE LIABLE TO YOU FOR ACTUAL, DIRECT,
INDIRECT, CONSEQUENTIAL, PUNITIVE OR INCIDENTAL DAMAGES
EVEN IF YOU GIVE NOTICE OF THE POSSIBILITY OF SUCH
DAMAGE.
1.F.3. LIMITED RIGHT OF REPLACEMENT OR REFUND – If you
discover a defect in this electronic work within 90 days of receiving
it, you can receive a refund of the money (if any) you paid for it by
sending a written explanation to the person you received the work
from. If you received the work on a physical medium, you must
return the medium with your written explanation. The person or
entity that provided you with the defective work may elect to provide
a replacement copy in lieu of a refund. If you received the work
electronically, the person or entity providing it to you may choose to
give you a second opportunity to receive the work electronically in
lieu of a refund. If the second copy is also defective, you may
demand a refund in writing without further opportunities to fix the
problem.
1.F.4. Except for the limited right of replacement or refund set
forth in paragraph 1.F.3, this work is provided to you ‘AS-IS,’ WITH
NO OTHER WARRANTIES OF ANY KIND, EXPRESS OR IMPLIED,
INCLUDING BUT NOT LIMITED TO WARRANTIES OF
MERCHANTABILITY OR FITNESS FOR ANY PURPOSE.
1.F.5. Some states do not allow disclaimers of certain implied
warranties or the exclusion or limitation of certain types of damages.
If any disclaimer or limitation set forth in this agreement violates the
law of the state applicable to this agreement, the agreement shall be
interpreted to make the maximum disclaimer or limitation permitted
by the applicable state law. The invalidity or unenforceability of any
provision of this agreement shall not void the remaining provisions.
1.F.6. INDEMNITY – You agree to indemnify and hold the
Foundation, the trademark owner, any agent or employee of the
Foundation, anyone providing copies of Project Gutenberg™
electronic works in accordance with this agreement, and any
volunteers associated with the production, promotion and
distribution of Project Gutenberg™ electronic works, harmless from
all liability, costs and expenses, including legal fees, that arise
directly or indirectly from any of the following which you do or cause
to occur: (a) distribution of this or any Project Gutenberg™ work, (b)
alteration, modification, or additions or deletions to any Project
Gutenberg™ work, and (c) any Defect you cause.

Section 2. Information about the Mission of


Project Gutenberg™

Project Gutenberg™ is synonymous with the free distribution of


electronic works in formats readable by the widest variety of
computers including obsolete, old, middle-aged and new computers.
It exists because of the efforts of hundreds of volunteers and
donations from people in all walks of life.
Volunteers and financial support to provide volunteers with the
assistance they need, is critical to reaching Project Gutenberg™'s
goals and ensuring that the Project Gutenberg™ collection will
remain freely available for generations to come. In 2001, the Project
Gutenberg Literary Archive Foundation was created to provide a
secure and permanent future for Project Gutenberg™ and future
generations. To learn more about the Project Gutenberg Literary
Archive Foundation and how your efforts and donations can help,
see Sections 3 and 4 and the Foundation web page at
https://www.pglaf.org .
Section 3. Information about the Project
Gutenberg Literary Archive Foundation

The Project Gutenberg Literary Archive Foundation is a non profit


501(c)(3) educational corporation organized under the laws of the
state of Mississippi and granted tax exempt status by the Internal
Revenue Service. The Foundation's EIN or federal tax identification
number is 64-6221541. Contributions to the Project Gutenberg
Literary Archive Foundation are tax deductible to the full extent
permitted by U.S. federal laws and your state's laws.
The Foundation's principal office is in Fairbanks, Alaska, with the
mailing address: PO Box 750175, Fairbanks, AK 99775, but its
volunteers and employees are scattered throughout numerous
locations. Its business office is located at 809 North 1500 West, Salt
Lake City, UT 84116, (801) 596-1887, email [email protected].
Email contact links and up to date contact information can be found
at the Foundation's web site and official page at
www.gutenberg.org/contact
For additional contact information:

Dr. Gregory B. Newby


Chief Executive and Director
[email protected]
Section 4. Information about Donations to the
Project Gutenberg Literary Archive Foundation

Project Gutenberg™ depends upon and cannot survive without wide


spread public support and donations to carry out its mission of
increasing the number of public domain and licensed works that can
be freely distributed in machine readable form accessible by the
widest array of equipment including outdated equipment. Many
small donations ($1 to $5,000) are particularly important to
maintaining tax exempt status with the IRS.
The Foundation is committed to complying with the laws
regulating charities and charitable donations in all 50 states of the
United States. Compliance requirements are not uniform and it takes
a considerable effort, much paperwork and many fees to meet and
keep up with these requirements. We do not solicit donations in
locations where we have not received written confirmation of
compliance. To SEND DONATIONS or determine the status of
compliance for any particular state visit
https://www.gutenberg.org/donate
While we cannot and do not solicit contributions from states
where we have not met the solicitation requirements, we know of no
prohibition against accepting unsolicited donations from donors in
such states who approach us with offers to donate.
International donations are gratefully accepted, but we cannot
make any statements concerning tax treatment of donations
received from outside the United States. U.S. laws alone swamp our
small staff.
Please check the Project Gutenberg Web pages for current
donation methods and addresses. Donations are accepted in a
number of other ways including checks, online payments and credit
card donations. To donate, please visit:
https://www.gutenberg.org/donate

Section 5. General Information About Project


Gutenberg™ electronic works.

Professor Michael S. Hart was the originator of the Project


Gutenberg™ concept of a library of electronic works that could be
freely shared with anyone. For thirty years, he produced and
distributed Project Gutenberg™ eBooks with only a loose network of
volunteer support.
Project Gutenberg™ eBooks are often created from several
printed editions, all of which are confirmed as not protected by
copyright in the U.S. unless a copyright notice is included. Thus, we
do not necessarily keep eBooks in compliance with any particular
paper edition.
Most people start at our Web site which has the main PG search
facility:

https://www.gutenberg.org

This Web site includes information about Project Gutenberg™,


including how to make donations to the Project Gutenberg Literary
Welcome to our website – the ideal destination for book lovers and
knowledge seekers. With a mission to inspire endlessly, we offer a
vast collection of books, ranging from classic literary works to
specialized publications, self-development books, and children's
literature. Each book is a new journey of discovery, expanding
knowledge and enriching the soul of the reade

Our website is not just a platform for buying books, but a bridge
connecting readers to the timeless values of culture and wisdom. With
an elegant, user-friendly interface and an intelligent search system,
we are committed to providing a quick and convenient shopping
experience. Additionally, our special promotions and home delivery
services ensure that you save time and fully enjoy the joy of reading.

Let us accompany you on the journey of exploring knowledge and


personal growth!

ebookgate.com

You might also like