100% found this document useful (1 vote)
14 views

Immediate download Python Programming for Data Analysis 1st Edition José Unpingco ebooks 2024

Unpingco

Uploaded by

enserneysamq
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
100% found this document useful (1 vote)
14 views

Immediate download Python Programming for Data Analysis 1st Edition José Unpingco ebooks 2024

Unpingco

Uploaded by

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

Download the Full Version of textbook for Fast Typing at textbookfull.

com

Python Programming for Data Analysis 1st Edition


José Unpingco

https://textbookfull.com/product/python-programming-for-
data-analysis-1st-edition-jose-unpingco/

OR CLICK BUTTON

DOWNLOAD NOW

Download More textbook Instantly Today - Get Yours Now at textbookfull.com


Recommended digital products (PDF, EPUB, MOBI) that
you can download immediately if you are interested.

Python for Probability Statistics and Machine Learning


José Unpingco

https://textbookfull.com/product/python-for-probability-statistics-
and-machine-learning-jose-unpingco/

textboxfull.com

Python for Probability, Statistics, and Machine Learning


2nd Edition José Unpingco

https://textbookfull.com/product/python-for-probability-statistics-
and-machine-learning-2nd-edition-jose-unpingco/

textboxfull.com

Vertically Integrated Architectures: Versioned Data


Models, Implicit Services, and Persistence-Aware
Programming 1st Edition Jos Jong
https://textbookfull.com/product/vertically-integrated-architectures-
versioned-data-models-implicit-services-and-persistence-aware-
programming-1st-edition-jos-jong/
textboxfull.com

Practical Machine Learning for Data Analysis Using Python


1st Edition Abdulhamit Subasi

https://textbookfull.com/product/practical-machine-learning-for-data-
analysis-using-python-1st-edition-abdulhamit-subasi/

textboxfull.com
Python for Data Analysis Data Wrangling with Pandas NumPy
and IPython Wes Mckinney

https://textbookfull.com/product/python-for-data-analysis-data-
wrangling-with-pandas-numpy-and-ipython-wes-mckinney/

textboxfull.com

Python for Excel A Modern Environment for Automation and


Data Analysis 1st Edition Felix Zumstein

https://textbookfull.com/product/python-for-excel-a-modern-
environment-for-automation-and-data-analysis-1st-edition-felix-
zumstein/
textboxfull.com

Python for Data Analysis Data Wrangling with pandas NumPy


and Jupyter 3rd Edition Wes Mckinney

https://textbookfull.com/product/python-for-data-analysis-data-
wrangling-with-pandas-numpy-and-jupyter-3rd-edition-wes-mckinney/

textboxfull.com

Functional Programming in R: Advanced Statistical


Programming for Data Science, Analysis and Finance 1st
Edition Thomas Mailund
https://textbookfull.com/product/functional-programming-in-r-advanced-
statistical-programming-for-data-science-analysis-and-finance-1st-
edition-thomas-mailund/
textboxfull.com

Python Data Analysis: Perform data collection, data


processing, wrangling, visualization, and model building
using Python 3rd Edition Avinash Navlani
https://textbookfull.com/product/python-data-analysis-perform-data-
collection-data-processing-wrangling-visualization-and-model-building-
using-python-3rd-edition-avinash-navlani/
textboxfull.com
José Unpingco

Python
Programming
for Data
Analysis
Python Programming for Data Analysis
José Unpingco

Python Programming
for Data Analysis
José Unpingco
University of California
San Diego
CA, USA

ISBN 978-3-030-68951-3 ISBN 978-3-030-68952-0 (eBook)


https://doi.org/10.1007/978-3-030-68952-0

© The Editor(s) (if applicable) and The Author(s), under exclusive license to Springer Nature Switzerland
AG 2021
This work is subject to copyright. All rights are solely and exclusively licensed by the Publisher, whether
the whole or part of the material is concerned, specifically the rights of translation, reprinting, reuse
of illustrations, recitation, broadcasting, reproduction on microfilms or in any other physical way, and
transmission or information storage and retrieval, electronic adaptation, computer software, or by similar
or dissimilar methodology now known or hereafter developed.
The use of general descriptive names, registered names, trademarks, service marks, etc. in this publication
does not imply, even in the absence of a specific statement, that such names are exempt from the relevant
protective laws and regulations and therefore free for general use.
The publisher, the authors, and the editors are safe to assume that the advice and information in this book
are believed to be true and accurate at the date of publication. Neither the publisher nor the authors or
the editors give a warranty, expressed or implied, with respect to the material contained herein or for any
errors or omissions that may have been made. The publisher remains neutral with regard to jurisdictional
claims in published maps and institutional affiliations.

This Springer imprint is published by the registered company Springer Nature Switzerland AG
The registered company address is: Gewerbestrasse 11, 6330 Cham, Switzerland
To Irene, Nicholas, and Daniella, for all their
patient support.
Preface

This book grew out of notes for the ECE143 Programming for Data Analysis class
that I have been teaching at the University of California, San Diego, which is a
requirement for both graduate and undergraduate degrees in Machine Learning and
Data Science. The reader is assumed to have some basic programming knowledge
and experience using another language, such as Matlab or Java. The Python idioms
and methods we discuss here focus on data analysis, notwithstanding Python’s
usage across many other topics. Specifically, because raw data is typically a mess
and requires much work to prepare, this text focuses on specific Python language
features to facilitate such cleanup, as opposed to only focusing on particular Python
modules for this.
As with ECE143, here we discuss why things are the way they are in Python
instead of just that they are this way. I have found that providing this kind of
context helps students make better engineering design choices in their codes, which
is especially helpful for newcomers to both Python and data analysis. The text is
sprinkled with little tricks of the trade to make it easier to create readable and
maintainable code suitable for use in both production and development.
The text focuses on using the Python language itself effectively and then moves
on to key third-party modules. This approach improves effectiveness in different
environments, which may or may not have access to such third-party modules. The
Numpy numerical array module is covered in depth because it is the foundation
of all data science and machine learning in Python. We discuss the Numpy array
data structure in detail, especially its memory aspects. Next, we move on to Pandas
and develop its many features for effective and fluid data processing. Because data
visualization is key to data science and machine learning, third-party modules such
as Matplotlib are developed in depth, as well as web-based modules such as Bokeh,
Holoviews, Plotly, and Altair.
On the other hand, I would not recommend this book to someone with no
programming experience at all, but if you can do a little Python already and want to
improve by understanding how and why Python works the way it does, then this is
a good book for you.

vii
viii Preface

To get the most out of this book, open a Python interpreter and type-along with
the many code samples. I worked hard to ensure that all of the given code samples
work as advertised.

Acknowledgments I would like to acknowledge the help of Brian Granger and Fernando Perez,
two of the originators of the Jupyter Notebook, for all their great work, as well as the Python
community as a whole, for all their contributions that made this book possible. Hans Petter
Langtangen was the author of the Doconce [1] document preparation system that was used to
write this text. Thanks to Geoffrey Poore [2] for his work with PythonTeX and LATEX, both key
technologies used to produce this book.

San Diego, CA, USA José Unpingco


February, 2020

References

1. H.P. Langtangen, DocOnce markup language. https://github.com/hplgit/doconce


2. G.M. Poore, Pythontex: reproducible documents with latex, python, and more. Comput. Sci.
Discov. 8(1), 014010 (2015)
Contents

1 Basic Programming . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
1.1 Basic Language . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
1.1.1 Getting Started . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
1.1.2 Reserved Keywords . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
1.1.3 Numbers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
1.1.4 Complex Numbers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
1.1.5 Strings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
1.1.6 Loops and Conditionals. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
1.1.7 Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
1.1.8 File Input/Output . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34
1.1.9 Dealing with Errors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36
1.1.10 Power Python Features to Master . . . . . . . . . . . . . . . . . . . . . . . . . . . 40
1.1.11 Generators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43
1.1.12 Decorators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48
1.1.13 Iteration and Iterables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52
1.1.14 Using Python Assertions to Pre-debug Code . . . . . . . . . . . . . . . 60
1.1.15 Stack Tracing with sys.settrace . . . . . . . . . . . . . . . . . . . . . . 61
1.1.16 Debugging Using IPython . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63
1.1.17 Logging from Python . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63
2 Object-Oriented Programming. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67
2.1 Properties/Attributes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67
2.2 Methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69
2.3 Inheritance . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71
2.4 Class Variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73
2.5 Class Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74
2.6 Static Methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75
2.7 Hashing Hides Parent Variables from Children . . . . . . . . . . . . . . . . . . . . . . 76
2.8 Delegating Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76
2.9 Using super for Delegation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77
2.10 Metaprogramming: Monkey Patching . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79

ix
x Contents

2.11 Abstract Base Classes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80


2.12 Descriptors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 82
2.13 Named Tuples and Data Classes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85
2.14 Generic Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 89
2.15 Design Patterns . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91
2.15.1 Template . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91
2.15.2 Singleton . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 92
2.15.3 Observer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 93
2.15.4 Adapter . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 94
References . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 94
3 Using Modules . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 95
3.1 Standard Library . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 95
3.2 Writing and Using Your Own Modules. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 96
3.2.1 Using a Directory as a Module . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 98
3.3 Dynamic Importing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 98
3.4 Getting Modules from the Web . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 99
3.5 Conda Package Management . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 99
References . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 101
4 Numpy. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103
4.1 Dtypes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103
4.2 Multidimensional Arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 104
4.3 Reshaping and Stacking Numpy Arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 105
4.4 Duplicating Numpy Arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 106
4.5 Slicing, Logical Array Operations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 107
4.6 Numpy Arrays and Memory . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 108
4.7 Numpy Memory Data Structures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 111
4.8 Array Element-Wise Operations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 114
4.9 Universal Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 114
4.10 Numpy Data Input/Output. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 115
4.11 Linear Algebra . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 115
4.12 Broadcasting . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 116
4.13 Masked Arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 120
4.14 Floating Point Numbers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 121
4.15 Advanced Numpy dtypes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 125
References . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 126
5 Pandas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 127
5.1 Using Series . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 127
5.2 Using DataFrame . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 131
5.3 Reindexing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 135
5.4 Deleting Items . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 136
5.5 Advanced Indexing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 137
5.6 Broadcasting and Data Alignment . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 138
5.7 Categorical and Merging . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 140
Contents xi

5.8 Memory Usage and dtypes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 143


5.9 Common Operations. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 146
5.10 Displaying DataFrames. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 148
5.11 Multi-index. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 150
5.12 Pipes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 152
5.13 Data Files and Databases . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 153
5.14 Customizing Pandas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 154
5.15 Rolling and Filling Operations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 155
6 Visualizing Data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 157
6.1 Matplotlib . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 158
6.1.1 Setting Defaults . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 160
6.1.2 Legends . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 160
6.1.3 Subplots . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 161
6.1.4 Spines . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 161
6.1.5 Sharing Axes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 162
6.1.6 3D Surfaces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 164
6.1.7 Using Patch Primitives . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 164
6.1.8 Patches in 3D . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 165
6.1.9 Using Transformations. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 168
6.1.10 Annotating Plots with Text . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 170
6.1.11 Annotating Plots with Arrows . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 171
6.1.12 Embedding Scalable and Non-scalable Subplots . . . . . . . . . . . 173
6.1.13 Animations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 175
6.1.14 Using Paths Directly . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 177
6.1.15 Interacting with Plots Using Sliders . . . . . . . . . . . . . . . . . . . . . . . . 179
6.1.16 Colormaps . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 181
6.1.17 Low-Level Control Using setp and getp . . . . . . . . . . . . . . . 183
6.1.18 Interacting with Matplotlib Figures . . . . . . . . . . . . . . . . . . . . . . . . . 183
6.1.19 Keyboard Events . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 184
6.1.20 Mouse Events . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 185
6.2 Seaborn . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 186
6.2.1 Automatic Aggregation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 190
6.2.2 Multiple Plots . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 194
6.2.3 Distribution Plots . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 196
6.3 Bokeh. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 204
6.3.1 Using Bokeh Primitives. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 204
6.3.2 Bokeh Layouts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 206
6.3.3 Bokeh Widgets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 207
6.4 Altair . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 213
6.4.1 Detailing Altair. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 215
6.4.2 Aggregations and Transformations. . . . . . . . . . . . . . . . . . . . . . . . . . 217
6.4.3 Interactive Altair . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 222
6.5 Holoviews . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 224
6.5.1 Dataset . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 230
xii Contents

6.5.2 Image Data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 232


6.5.3 Tabular Data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 232
6.5.4 Customizing Interactivity . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 235
6.5.5 Streams . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 236
6.5.6 Pandas Integration with hvplot . . . . . . . . . . . . . . . . . . . . . . . . . . 237
6.5.7 Network Graphs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 243
6.5.8 Holoviz Panel for Dashboards . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 247
6.6 Plotly . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 251
References . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 259

Index . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 261
Chapter 1
Basic Programming

1.1 Basic Language

Before we get into the details, it is a good idea to get a high-level orientation to
Python. This will improve your decision-making later regarding software develop-
ment for your own projects, especially as these get bigger and more complex. Python
grew out of a language called ABC, which was developed in the Netherlands in the
1980s as an alternative to BASIC to get scientists to utilize microcomputers, which
were new at the time. The important impulse was to make non-specialist scientists
able to productively utilize these new computers. Indeed, this pragmatic approach
continues to this day in Python which is a direct descendent of the ABC language.
There is a saying in Python—come for the language, stay for the community.
Python is an open source project that is community driven so there is no corporate
business entity making top-down decisions for the language. It would seem that such
an approach would lead to chaos but Python has benefited over many years from
the patient and pragmatic leadership of Guido van Rossum, the originator of the
language. Nowadays, there is a separate governance committee that has taken over
this role since Guido’s retirement. The open design of the language and the quality
of the source code has made it possible for Python to enjoy many contributions from
talented developers all over the world over many years, as embodied by the richness
of the standard library. Python is also legendary for having a welcoming community
for newcomers so it is easy to find help online for getting started with Python.
The pragmatism of the language and the generosity of the community have long
made Python a great way to develop web applications. Before the advent of data
science and machine learning, upwards of 80% of the Python community were web
developers. In the last five years (at the time of this writing), the balance is tilted to
an almost even split between web developers and data scientists. This is the reason
you find a lot of web protocols and technology in the standard library.
Python is an interpreted language as opposed to a compiled language like C
or FORTRAN. Although both cases start with a source code file, the compiler

© The Editor(s) (if applicable) and The Author(s), under exclusive license 1
to Springer Nature Switzerland AG 2021
J. Unpingco, Python Programming for Data Analysis,
https://doi.org/10.1007/978-3-030-68952-0_1
2 1 Basic Programming

examines the source code end-to-end and produces an executable that is linked to
system-specific library files. Once the executable is created, there is no longer any
need for the compiler. You can just run the executable on the system. On the other
hand, an interpreted language like Python you must always have a running Python
process to execute the code. This is because the Python process is an abstraction on
the platform it is running on and thus must interpret the instructions in the source
code to execute them on the platform. As the intermediary between the source
code on the platform, the Python interpreter is responsible for the platform specific
issues. The advantage of this is that source code can be run on different platforms as
long as there is a working Python interpreter on each platform. This makes Python
source codes portable between platforms because the platform specific details are
handled by the respective Python interpreters. Portability between platforms was
a key advantage of Python, especially in the early days. Going back to compiled
languages, because the platform specific details are embedded in the executable, the
executable is tied to a specific platform and to those specific libraries that have been
linked into the executable. This makes these codes are less portable than Python,
but because the compiler is able to link to the specific platform it has the option
to exploit platform- specific level optimizations and libraries. Furthermore, the
compiler can study the source code file and apply compiler-level optimizations that
accelerate the resulting executable. In broad strokes, those are the key differences
between interpreted and compiled languages. We will later see that there are many
compromises between these two extremes for accelerating Python codes.
It is sometimes said that Python is slow as compared to compiled languages,
and pursuant to the differences we discussed above, that may be expected, but it
is really a question of where the clock starts. If you start the clock to account for
developer time, not just code runtime, then Python is clearly faster, just because
the development iteration cycle does not require a tedious compile and link step.
Furthermore, Python is just simpler to use than compiled languages because so
many tricky elements like memory management are handled automatically. Pythons
quick turnaround time is a major advantage for product development, which requires
rapid iteration. On the other hand, codes that are compute-limited and must run
on specialized hardware are not good use-cases for Python. These include solving
systems of parallel differential equations simulating large-scale fluid mechanics or
other large-scale physics calculations. Note that Python is used in such settings but
mainly for staging these computations or postprocessing the resulting data.

1.1.1 Getting Started

Your primary interface to the Python interpreter is the commandline. You can type
in python in your terminal you should see something like the following,
Python 3.7.3 (default, Mar 27 2019, 22:11:17)
[GCC 7.3.0] :: Anaconda, Inc. on linux
1.1 Basic Language 3

Type "help", "copyright", "credits" or "license" for more


→ information.
>>>

There is a lot of useful information including the version of Python and its
provenance. This matters because sometimes the Python interpreter is compiled to
allow fast access to certain preferred modules (i.e., math module). We will discuss
this more when we talk about Python modules.

1.1.2 Reserved Keywords

Although Python will not stop you, do not use these as variable or function names.
and del from not while
as elif global or with
assert else if pass yield
break except import print
class exec in raise
continue finally is return
def for lambda try

nor these neither


abs all any ascii bin bool breakpoint bytearray bytes callable
chr classmethod compile complex copyright credits delattr
dict dir display divmod enumerate eval exec filter float
format frozenset getattr globals hasattr hash help hex id
input int isinstance issubclass iter len list locals map max
memoryview min next object oct open ord pow print property
range repr reversed round set setattr slice sorted
staticmethod str sum super tuple type vars zip

For example, a common mistake is to assign sum=10, not realizing that now the
sum() Python function is no longer available.

1.1.3 Numbers

Python has common-sense number-handling capabilities. The comment character is


the hash (#) symbol.
>>> 2+2
4
>>> 2+2 # and a comment on the same line as code
4
>>> (50-5*6)/4
5.0

Note that division in Python 2 is integer-division and in Python 3 it is floating


point division with the // symbol providing integer-division. Python is dynamically
4 1 Basic Programming

typed, so we can do the following assignments without declaring the types of


width and height.
>>> width = 20
>>> height = 5*9
>>> width * height
900
>>> x = y = z = 0 # assign x, y and z to zero
>>> x
0
>>> y
0
>>> z
0
>>> 3 * 3.75 / 1.5
7.5
>>> 7.0 / 2 # float numerator
3.5
>>> 7/2
3.5
>>> 7 // 2 # double slash gives integer division
3

It is best to think of assignments as labeling values in memory. Thus, width is a


label for the number 20. This will make more sense later.1 Since Python 3.8, the
walrus assignment operator allows the assignment itself to have the value of the
assignee, as in the following,
>>> print(x:=10)
10
>>> print(x)
10

The operator has many other subtle uses and was introduced to improve readability
in certain situations. You can also cast among the numeric types in a common-sense
way:
>>> int(1.33333)
1
>>> float(1)
1.0
>>> type(1)
<class 'int'>
>>> type(float(1))
<class 'float'>

Importantly, Python integers are of arbitrary length and can handle extremely large
integers. This is because they are stored as a list of digits internally. This means that
they are slower to manipulate than Numpy integers which have fixed bit-lengths,
provided that the integer can fit into allocated memory.

1 Notehttp://www.pythontutor.com is a great resource for exploring how variables are assigned in


Python.
1.1 Basic Language 5

Programming Tip: IPython


The default Python interpreter is useful and you should be familiar with it
but the IPython interpretera is a useful extension that provides features like
sophisticated tab-completion and many other conveniences that make it easier
to work with Python in the terminal.
a
See http://github.com/ipython/ipython for the latest on how to get started with IPython.

1.1.4 Complex Numbers

Python has rudimentary support for complex numbers.


>>> 1j * 1J
(-1+0j)
>>> 1j * complex(0,1)
(-1+0j)
>>> 3+1j*3
(3+3j)
>>> (3+1j)*3
(9+3j)
>>> (1+2j)/(1+1j)
(1.5+0.5j)
>>> a=1.5+0.5j
>>> a.real # the dot notation gets an attribute
1.5
>>> a.imag
0.5
>>> a=3.0+4.0j
>>> float(a)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: can't convert complex to float
>>> a.real
3.0
>>> a.imag
4.0
>>> abs(a) # sqrt(a.real**2 + a.imag**2)
5.0
>>> tax = 12.5 / 100
>>> price = 100.50
>>> price * tax
12.5625
>>> price + _
113.0625
>>> # the underscore character is the last evaluated result
>>> round(_, 2) # the underscore character is the last evaluated
→ result
113.06
6 1 Basic Programming

We typically use Numpy for complex numbers, though.

1.1.5 Strings

String-handling is very well developed and highly optimized in Python. We just


cover the main points here. First, single or double quotes define a string and there is
no precedence relationship between single and double quotes.
>>> 'spam eggs'
'spam eggs'
>>> 'doesn\'t' # backslash defends single quote
"doesn't"
>>> "doesn't"
"doesn't"
>>> '"Yes," he said.'
'"Yes," he said.'
>>> "\"Yes,\" he said."
'"Yes," he said.'
>>> '"Isn\'t," she said.'
'"Isn\'t," she said.'

Python strings have C-style escape characters for newlinewsnewlines, tabs, etc.
String literals defined this way are by default encoded using UTF-8 instead of
ASCII, as in Python 2. The triple single (’) or triple double quote (") denotes a
block with embedded newlines or other quotes. This is particularly important for
function documentation docstrings that we will discussed later.
>>> print( '''Usage: thingy [OPTIONS]
... and more lines
... here and
... here
... ''')
Usage: thingy [OPTIONS]
and more lines
here and
here

Strings can be controlled with a character before the single or double quote. For
example, see the comments (#) below for each step,
>>> # the 'r' makes this a 'raw' string
>>> hello = r"This long string contains newline characters \n, as
→ in C"
>>> print(hello)
This long string contains newline characters \n, as in C
>>> # otherwise, you get the newline \n acting as such
>>> hello = "This long string contains newline characters \n, as
→ in C"
>>> print(hello)
This long string contains newline characters
, as in C
1.1 Basic Language 7

>>> u'this a unicode string μ ±' # the 'u' makes it a unicode


→ string for Python2
'this a unicode string μ ±'
>>> 'this a unicode string μ ±' # no 'u' in Python3 is still
→ unicode string
'this a unicode string μ ±'
>>> u'this a unicode string \xb5 \xb1' # using hex-codes
'this a unicode string μ ±'

Note that a f-string evaluates (i.e., interpolates) the Python variables in the
current scope,
>>> x = 10
>>> s = f'{x}'
>>> type(s)
<class 'str'>
>>> s
'10'

Beware that an f-string is not resolved until run-time because it has to resolve
the embedded variables. This means that you cannot use f-strings as docstrings.
Importantly, Python strings are immutable which means that once a string is created,
it cannot be changed in-place. For example,
>>> x = 'strings are immutable '
>>> x[0] = 'S' # not allowed!
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'str' object does not support item assignment

This means you have to create new strings to make this kind of change.
Strings vs Bytes In Python 3, the default string encoding for string literals is UTF-
8. The main thing to keep in mind is that bytes and strings are now distinct objects,
as opposed to both deriving from basestring in Python 2. For example, given
the following unicode string,
>>> x='Ø'
>>> isinstance(x,str) # True
True
>>> isinstance(x,bytes) # False
False
>>> x.encode('utf8') # convert to bytes with encode
b'\xc3\x98'

Note the distinction between bytes and strings. We can convert bytes to strings using
decode,
>>> x=b'\xc3\x98'
>>> isinstance(x,bytes) # True
True
>>> isinstance(x,str) # False
False
>>> x.decode('utf8')
'Ø'
8 1 Basic Programming

An important consequence is that you cannot append strings and bytes as in the
following: u"hello"+b"goodbye". This used to work fine in Python 2 because
bytes would automatically be decoded using ASCII, but this no longer works in
Python 3. To get this behavior, you have to explicitly decode/encode. For
example,
>>> x=b'\xc3\x98'
>>> isinstance(x,bytes) # True
True
>>> y='banana'
>>> isinstance(y,str) # True
True
>>> x+y.encode()
b'\xc3\x98banana'
>>> x.decode()+y
'Øbanana'

Slicing Strings Python is a zero-indexed language (like C). The colon (:) character
denotes .
>>> word = 'Help' + 'A'
>>> word
'HelpA'
>>> '<' + word*5 + '>'
'<HelpAHelpAHelpAHelpAHelpA>'
>>> word[4]
'A'
>>> word[0:2]
'He'
>>> word[2:4]
'lp'
>>> word[-1] # The last character
'A'
>>> word[-2] # The last-but-one character
'p'
>>> word[-2:] # The last two characters
'pA'
>>> word[:-2] # Everything except the last two characters
'Hel'

String Operations Some basic numerical operations work with strings.


>>> 'hey '+'you' # concatenate with plus operator
'hey you'
>>> 'hey '*3 # integer multiplication duplicates strings
'hey hey hey '
>>> ('hey ' 'you') # using parentheses without separating comma
'hey you'

Python has a built-in and very powerful regular expression module (re) for string
manipulations. String substitution creates new strings.
>>> x = 'This is a string'
>>> x.replace('string','newstring')
'This is a newstring'
>>> x # x hasn't changed
'This is a string'
1.1 Basic Language 9

Formatting Strings There are so many ways to format strings in Python, but here
is the simplest that follows C-language sprintf conventions in conjunction with
the modulo operator %.
>>> 'this is a decimal number %d'%(10)
'this is a decimal number 10'
>>> 'this is a float %3.2f'%(10.33)
'this is a float 10.33'
>>> x = 1.03
>>> 'this is a variable %e' % (x) # exponential format
'this is a variable 1.030000e+00'

Alternatively, you can just join them using +,


>>> x = 10
>>> 'The value of x = '+str(x)
'The value of x = 10'

You can format using dictionaries as in the following,


>>> data = {'x': 10, 'y':20.3}
>>> 'The value of x = %(x)d and y = %(y)f'%(data)
'The value of x = 10 and y = 20.300000'

You can use the format method on the string,


>>> x = 10
>>> y = 20
>>> 'x = {0}, y = {1}'.format(x,y)
'x = 10, y = 20'

The advantage of format is you can reuse the placeholders as in the following,
>>> 'x = {0},{1},{0}; y = {1}'.format(x,y)
'x = 10,20,10; y = 20'

And also the f-string method we discussed above.

Programming Tip: Python 2 Strings


In Python 2, the default string encoding was 7-bit ASCII. There was no
distinction between bytes and strings. For example, you could read from a
binary-encoded JPG file as in the following,
with open('hour_1a.jpg','r') as f:
x = f.read()

This works fine in Python 2 but throws a UnicodeDecodeError error in


Python 3. To fix this in Python 3, you have to read using the rb binary mode
instead of just the r file mode.

Basic Data Structures Python provides many powerful data structures. The two
most powerful and fundamental are the list and dictionary. Data structures and
10 1 Basic Programming

algorithms go hand-in-hand. If you do not understand data structures, then you


cannot effectively write algorithms and vice versa. Fundamentally, data structures
provide guarantees to the programmer that will be fulfilled if the data structures are
used in the agreed-upon manner. These guarantees are known as the invariants for
the data structure.
Lists The list is an order-preserving general container that implements the
sequence data structure. The invariant for the list is that indexing a non-empty list
will always give you the next valid element in order. Indeed, the list is Python’s
primary ordered data structure. This means that if you have a problem where order
is important, then you should be thinking about the list data structure. This will
make sense with following examples.
>>> mix = [3,'tree',5.678,[8,4,2]] # can contain sublists
>>> mix
[3, 'tree', 5.678, [8, 4, 2]]
>>> mix[0] # zero-indexed Python
3
>>> mix[1] # indexing individual elements
'tree'
>>> mix[-2] # indexing from the right, same as strings
5.678
>>> mix[3] # get sublist
[8, 4, 2]
>>> mix[3][1] # last element is sublist
4
>>> mix[0] = 666 # lists are mutable
>>> mix
[666, 'tree', 5.678, [8, 4, 2]]
>>> submix = mix[0:3] # creating sublist
>>> submix
[666, 'tree', 5.678]
>>> switch = mix[3] + submix # append two lists with plus
>>> switch
[8, 4, 2, 666, 'tree', 5.678]
>>> len(switch) # length of list is built-in function
6
>>> resize=[6.45,'SOFIA',3,8.2E6,15,14]
>>> len(resize)
6
>>> resize[1:4] = [55] # assign slices
>>> resize
[6.45, 55, 15, 14]
>>> len(resize) # shrink a sublist
4
>>> resize[3]=['all','for','one']
>>> resize
[6.45, 55, 15, ['all', 'for', 'one']]
>>> len(resize)
4
>>> resize[4]=2.87 # cannot append this way!
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
IndexError: list assignment index out of range
>>> temp = resize[:3]
1.1 Basic Language 11

>>> resize = resize + [2.87] # add to list


>>> resize
[6.45, 55, 15, ['all', 'for', 'one'], 2.87]
>>> len(resize)
5
>>> del resize[3] # delete item
>>> resize
[6.45, 55, 15, 2.87]
>>> len(resize) # shorter now
4
>>> del resize[1:3] # delete a sublist
>>> resize
[6.45, 2.87]
>>> len(resize) # shorter now
2

Programming Tip: Sorting Lists


The built-in function sorted sorts lists,
>>> sorted([1,9,8,2])
[1, 2, 8, 9]

Lists can also be sorted in-place using the sort() list method,
>>> x = [1,9,8,2]
>>> x.sort()
>>> x
[1, 2, 8, 9]

Both of these use the powerful Timsort algorithm. Later, we will see more
variations and uses for these sorting functions.

Now that we have a feel for how to index and use lists, let us talk about the invariant
that it provides: as long as you index a list within its bounds, it provides the next
ordered element of the list. For example,
>>> x = ['a',10,'c']
>>> x[1] # return 10
10
>>> x.remove(10)
>>> x[1] # next element
'c'

Notice that the list data structure filled in the gap after removing 10. This is extra
work that the list data structure did for you without explicitly programming. Also,
list elements are accessible via integer indices and integers have a natural ordering
and thus so does the list. The work of maintaining the invariant does not come for
free, however. Consider the following,
>>> x = [1,3,'a']
>>> x.insert(0,10) # insert at beginning
12 1 Basic Programming

>>> x
[10, 1, 3, 'a']

Seem harmless? Sure, for small lists, but not so for large lists. This is because
to maintain the invariant the list has to scoot (i.e., memory copy) the remaining
elements over to the right to accommodate the new element added at the beginning.
Over a large list with millions of elements and in a loop, this can take a substantial
amount of time. This is why the default append() and pop() list methods work
at the tail end of the list, where there is no need to scoot items to the right.
Tuples Tuples are another general purpose sequential container in Python, very
similar to lists, but these are immutable. Tuples are delimited by commas (parenthe-
ses are grouping symbols). Here are some examples,
>>> a = 1,2,3 # no parenthesis needed!
>>> type(a)
<class 'tuple'>
>>> pets=('dog','cat','bird')
>>> pets[0]
'dog'
>>> pets + pets # addition
('dog', 'cat', 'bird', 'dog', 'cat', 'bird')
>>> pets*3
('dog', 'cat', 'bird', 'dog', 'cat', 'bird', 'dog', 'cat', 'bird')
>>> pets[0]='rat' # assignment not work!
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'tuple' object does not support item assignment

It may seem redundant to have tuples which behave in terms of their indexing like
lists, but the key difference is that tuples are immutable, as the last line above shows.
The key advantage of immutability is that it comes with less overhead for Python
memory management. In this sense, they are lighter weight and provide stability for
codes that pass tuples around. Later, we will see this for function signatures, which
is where the major advantages of tuples arise.

Programming Tip: Understanding List Memory


Python’s id function shows an integer corresponding to the internal reference
for a given variable. Earlier, we suggested considering variable assignment as
labeling because internally Python works with a variable’s id, not its variable
name/label.
>>> x = y = z = 10.1100
>>> id(x) # different labels for same id
140271927806352
>>> id(y)
140271927806352
>>> id(z)
140271927806352

(continued)
1.1 Basic Language 13

This is more consequential for mutable data structures like lists. Consider the
following,
>>> x = y = [1,3,4]
>>> x[0] = 'a'
>>> x
['a', 3, 4]
>>> y
['a', 3, 4]
>>> id(x),id(y)
(140271930505344, 140271930505344)

Because x and y are merely two labels for the same underlying list, changes to
one of the labels affects both lists. Python is inherently stingy about allocating
new memory so if you want to have two different lists with the same content,
you can force a copy as in the following,
>>> x = [1,3,4]
>>> y = x[:] # force copy
>>> id(x),id(y) # different ids now!
(140271930004160, 140271929640448)
>>> x[1] = 99
>>> x
[1, 99, 4]
>>> y # retains original data
[1, 3, 4]

Tuple Unpacking Tuples unpack assignments in order as follows:,


>>> a,b,c = 1,2,3
>>> a
1
>>> b
2
>>> c
3

Python 3 can unpack tuples in chunks using the * operator,


>>> x,y,*z = 1,2,3,4,5
>>> x
1
>>> y
2
>>> z
[3, 4, 5]

Note how the z variable collected the remaining items in the assignment. You can
also change the order of the chunking,
>>> x,*y,z = 1,2,3,4,5
>>> x
1
14 1 Basic Programming

>>> y
[2, 3, 4]
>>> z
5

This unpacking is sometimes called de-structuring, or splat, in case you read this
term elsewhere.
Dictionaries Python dictionaries are central to Python because many other ele-
ments (e.g., functions, classes) are built around them. Effectively programming
Python means using dictionaries effectively. Dictionaries are general containers that
implement the mapping data structure, which is sometimes called a hash table or
associative array. Dictionaries require a key/value pair, which maps the key to the
value.
>>> x = {'key': 'value'}

The curly braces and the colon make the dictionary. To retrieve the value from the
x dictionary, you must index it with the key as shown,
>>> x['key']
'value'

Let us get started with some basic syntax.


>>> x={'play':'Shakespeare','actor':'Wayne','direct':'Kubrick',
... 'author':'Hemmingway','bio':'Watson'}

>>> len(x) # number of key/value pairs


5
>>> x['pres']='F.D.R.' # assignment to key 'pres'
>>> x
{'play': 'Shakespeare', 'actor': 'Wayne', 'direct': 'Kubrick',
→ 'author': 'Hemmingway', 'bio': 'Watson', 'pres': 'F.D.R.'}
>>> x['bio']='Darwin' # reassignment for 'bio' key
>>> x
{'play': 'Shakespeare', 'actor': 'Wayne', 'direct': 'Kubrick',
→ 'author': 'Hemmingway', 'bio': 'Darwin', 'pres': 'F.D.R.'}
>>> del x['actor'] # delete key/value pair
>>> x
{'play': 'Shakespeare', 'direct': 'Kubrick', 'author':
→ 'Hemmingway', 'bio': 'Darwin', 'pres': 'F.D.R.'}

Dictionaries can also be created with the dict built-in function,


>>> # another way of creating a dict
>>> x=dict(key='value',
... another_key=1.333,
... more_keys=[1,3,4,'one'])
>>> x
{'key': 'value', 'another_key': 1.333, 'more_keys': [1, 3, 4,
→ 'one']}
>>> x={(1,3):'value'} # any immutable type can be a valid key
>>> x
{(1, 3): 'value'}
>>> x[(1,3)]='immutables can be keys'
1.1 Basic Language 15

As generalized containers, dictionaries can contain other dictionaries or lists or other


Python types.

Programming Tip: Unions of Dictionaries


What if you want to create a union of dictionaries in one- line?
>>> d1 = {'a':1, 'b':2, 'c':3}
>>> d2 = {'A':1, 'B':2, 'C':3}
>>> dict(d1,**d2) # combo of d1 and d2
{'a': 1, 'b': 2, 'c': 3, 'A': 1, 'B': 2, 'C': 3}
>>> {**d1,**d2} # without dict function
{'a': 1, 'b': 2, 'c': 3, 'A': 1, 'B': 2, 'C': 3}

Pretty slick.

The invariant that the dictionary provides is that as long as you provide a valid key,
then it will always retrieve the corresponding value; or, in the case of assignment,
store the value reliably. Recall that lists are ordered data structures in the sense that
when elements are indexed, the next element can be found by a relative offset from
the prior one. This means that these elements are laid out contiguously in memory.
Dictionaries do not have this property because they will put values wherever they
can find memory, contiguous or not. This is because dictionaries do not rely upon
relative offsets for indexing, they rely instead on a hash function. Consider the
following,
>>> x = {0: 'zero', 1: 'one'}
>>> y = ['zero','one']
>>> x[1] # dictionary
'one'
>>> y[1] # list
'one'

Indexing both variables looks notationally the same in both cases, but the process
is different. When given a key, the dictionary computes a hash function and the
stores the value at a memory location based upon the hash function. What is a hash
function? A hash function takes an input and is designed to return, with very high
probability, a value that is unique to the key. In particular, this means that two keys
cannot have the same hash, or, equivalently, cannot store different values in the
same memory location. Here are two keys which are almost identical, but have very
different hashes.
>>> hash('12345')
3973217705519425393
>>> hash('12346')
3824627720283660249

All this is with respect to probability, though. Because memory is finite, it could
happen that the hash function produces values that are the same. This is known
as a hash collision and Python implements fallback algorithms to handle this
16 1 Basic Programming

case. Nonetheless, as memory becomes scarce, especially on a small platform, the


struggle to find suitable blocks of memory can be noticeable if your code uses many
large dictionaries.
As we discussed before, inserting/removing elements from the middle of a list
causes extra memory movement as the list maintains its invariant but this does
not happen for dictionaries. This means that elements can be added or removed
without any extra memory overhead beyond the cost of computing the hash function
(i.e., constant-time lookup). Thus, dictionaries are ideal for codes that do not need
ordering. Note that since Python 3.6+, dictionaries are ordered in the sense of the
order in which items were inserted to the dictionary. In Python 2.7, this was known
as collections.OrderedDict but has since become the default in Python
3.6+.
Now that we have a good idea of how dictionaries work, consider the inputs to
the hash function: the keys. We have mainly used integers and strings for keys, but
any immutable type can also be used, such as a tuple,
>>> x= {(1,3):10, (3,4,5,8):10}

However, if you try to use a mutable type as a key,


>>> a = [1,2]
>>> x[a]= 10
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'list'

Let us think about why this happens. Remember that the hash function guarantees
that when given a key it will always be able to retrieve the value. Suppose that it
were possible use mutable keys in dictionaries. In the above code, we would have
hash(a) -> 132334, as an example, and let us suppose the 10 value is inserted
in that memory slot. Later in the code, we could change the contents of a as in
a[0]=3. Now, because the hash function is guaranteed to produce different outputs
for different inputs, the hash function output would be different from 132334 and
thus the dictionary could not retrieve the corresponding value, which would violate
its invariant. Thus we have arrived at a contradiction that explains why dictionary
keys must be immutable.
Sets Python provides mathematical sets and corresponding operations with the
set() data structure, which are basically dictionaries without values.
>>> set([1,2,11,1]) # union-izes elements
{1, 2, 11}
>>> set([1,2,3]) & set([2,3,4]) # bitwise intersection
{2, 3}
>>> set([1,2,3]) and set([2,3,4])
{2, 3, 4}
>>> set([1,2,3]) ^ set([2,3,4]) # bitwise exclusive OR
{1, 4}
>>> set([1,2,3]) | set([2,3,4]) # OR
{1, 2, 3, 4}
>>> set([ [1,2,3],[2,3,4] ]) # no sets of lists
1.1 Basic Language 17

(without more work)


Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'list'

Note that since Python 3.6+, keys can be used as set objects, as in the following,
>>> d = dict(one=1,two=2)
>>> {'one','two'} & d.keys() # intersection
{'one', 'two'}
>>> {'one','three'} | d.keys() # union
{'one', 'two', 'three'}

This also works for dictionary items if the values are hashable,
>>> d = dict(one='ball',two='play')
>>> {'ball','play'} | d.items()
{'ball', 'play', ('one', 'ball'), ('two', 'play')}

Once you create a set, you can add individual elements or remove them as follows:,
>>> s = {'one',1,3,'10'}
>>> s.add('11')
>>> s
{1, 3, 'one', '11', '10'}
>>> s.discard(3)
>>> s
{1, 'one', '11', '10'}

Remember sets are not ordered and you cannot directly index any of the constituent
items. Also, the subset() method is for a proper subset not a partial subset. For
example,
>>> a = {1,3,4,5}
>>> b = {1,3,4,5,6}
>>> a.issubset(b)
True
>>> a.add(1000)
>>> a.issubset(b)
False

And likewise for issuperset. Sets are optimal for fast lookups in Python, as in
the following,
>>> a = {1,3,4,5,6}
>>> 1 in a
True
>>> 11 in a
False

which works really fast, even for large sets.

1.1.6 Loops and Conditionals

There are two primary looping constructs in Python: the for loop and the while
loop. The syntax of the for loop is straightforward:
18 1 Basic Programming

>>> for i in range(3):


... print(i)
...
0
1
2

Note the colon character at the end. This is your hint that the next line should be
indented. In Python, blocks are denoted by whitespace indentation (four spaces
is recommended) which makes the code more readable anyway. The for loop
iterates over items that provided by the iterator, which is the range(3) list
in the above example. Python abstracts the idea of iterable out of the looping
construction so that some Python objects are iterable all by themselves and are just
waiting for an iteration provider like a for or while loop to get them going.
Interestingly, Python has an else clause, which is used to determine whether or
not the loop exited with a break3 or not.
>>> for i in [1,2,3]:
... if i>20:
... break # won't happen
... else:
... print('no break here!')
...
no break here!

The else block is only executed when the loop terminates without breaking.
The while loop has a similar straightforward construct:
>>> i = 0
>>> while i < 3:
... i += 1
... print(i)
...
1
2
3

This also has a corresponding optional else block. Again, note that the presence
of the colon character hints at indenting the following line. The while loop will
continue until the boolean expression (i.e., i<10) evaluates False. Let us consider
boolean and membership in Python.
Logic and Membership Python is a truthy language in the sense that things are
true except for the following:
• None
• False
• zero of any numeric type, for example, 0, 0L, 0.0, 0j.
• any empty sequence, for example, ”, (), [].

3 There is also a continue statement which will jump to the top of the for or while loop.
Random documents with unrelated
content Scribd suggests to you:
Főpincér. Pardon. Szabóhoz viszi.
Szabó. Ez olyan régi huszárfogás, ismerem, pajtás. A civilt
biztatjátok és azalatt ti elcsíptek minden asszonyt az orrunk elől.
Zágon. Ördögöt, fiam. Nem fenékig tejföl a huszárnak se. Nekem
most csíptek el egyet a civilek az orrom elől, a mult héten. Azt
siratom itt Pesten.
Szabó. Asszony, lány?
Zágon. Lány.
Szabó. Férjhez ment?
Zágon. Ühüm.
Szabó. Az pech. Ismerem.
Zágon. A lányt?
Szabó. Nem. Ezt a pechet. Szervusz. Koccintanak.
Kelemen. Most már nem kell egy szót se szólnod.
Vilma. Menjünk haza, fiam, jó?
Kelemen erélyesen. Nem.
Vilma. Kérlek, azonnal menjünk haza.
Kelemen. Nem megyünk.
Vilma főpincérhez. Kérem, fizetni?
Zágon. Nem jösz velünk az Operába?
Főpincér Kelemenhez. Parancsol?
Kelemen. Nem, kérem. Nem híttam.
Főpincér. A nagyságos asszony…
Kelemen. Köszönöm, ráér.
Zágon. A cimborámat nem ismered?
Mikhál Aurél, császári királyi kamarás, nagyon jó gyerek. Gyere,
van egy páholyunk. És egy barnakalapos nő.
Szabó. Köszönöm pajtás, dolgom van.
Zágon. Aha. Kérlek. Egy szót se szóltam.
Szabó. Ugyan. Azt hiszed, nekem is mindig nők járnak a
fejemben? Én ebből már kiöregedtem.
Zágon. Ja! Tudom… hallottam valamit…
Szabó. Nem hallhattál semmit.
Zágon, Dehogy nem… Sokat hallottam… De annak már jó pár éve.
Kelemen. Most fizessünk? Most menjünk el? Ép, mikor a színház
kezdődik?
Vilma. Jenő… én fölkelek és elmegyek magam… haza…
Kelemen. Itt fogsz maradni.
Zágon. Azóta még mindig nőgyűlölő vagy? Mi is volt az? Valami
asszonyba voltál szerelmes…
Szabó. Semmi.
Zágon. De igen… már tudom… várj csak…
Kelemen. Kérek egy feketét.
Pincér. Igenis. El.
Szabó Zágon füléhez hajol, könyökölve. Pista. Odainti a szemével.
Súg neki valamit.
Zágon. Tessék? Közelebb hajol.
Szabó súg neki. Majd hangosan. De ne nézz most oda.
Vilma nagyon izgatottan. A gyereket is el kell altatni… Tudod,
hogy ha nem mesélsz neki, nem alszik el. Most már fél kilenc és a
gyereknek ilyenkor már rég aludnia kell.
Kelemen. Ne beszélj most, fiacskám. Most üljünk így egy kicsit
csöndesen. Most egyszerre megjött a diskuráló kedved.
Vilma. Most már egész feltünően hallgatózol.
Kelemen. Nagyon sajnálom, ha nem tetszik neked. Igenis,
hallgatózom.
Vilma. Itt hagylak.
Kelemen. Ahogy gondolod.
Vilma. Nem jössz?
Kelemen. Nem.
Vilma. Itt akarsz most hallgatózni?
Kelemen. Most már sok újat nem hallhatok tőlük, de most már
csak azért is itt maradok.
Zágon megnézi Vilmát.
Szabó foga közt. Ne nézd olyan feltünően. Felnéz a plafondra.
Zágon. Te… Összehajolva suttognak.
Vilma majdnem suttogva, nagy izgalomban. Könyörgöm, édes
fiam… menjünk haza…
Kelemen. Mitől félsz? Nem lesz vendéglői botrány, ne félj.
Vilma. De miért is lenne?
Kelemen. Miért is lenne? Semmi ok rá. Izgatottan. Amíg valami
olyat nem mond, vagy csinál…
Zágon. Azt hallottad, hogy Méray Tóni megvette a Stössel
birtokot?
Szabó. Ne mondd. Stössel eladta a birtokát?
Zágon. Hát mondom, hogy Tóni megvette.
Szabó. Mennyiért?
Zágon. Nyolcszázötvenezer koronáért, készpénzben.
Kelemen. Más téma.
Vilma. Mert észrevették, hogy hallgatóztál. Jaj de szégyellem
magam…
Kelemen. Vagyis jól tudod, kicsoda. Különben mit szégyelnéd
magadat.
Szabó. Honnan volt neki annyi pénze?
Zágon. A felesége gazdag asszony. Most is örököltek vagy
kétszázezer koronát. És még van egy tanti Bécsben.
Kelemen. Most, – látod fiam, – most már fizethetek. Fizetni! Most
már vége a színháznak. Amire kíváncsi voltam, azt tudom. Tóni
megvette a Stössel birtokát. A főpincérhez. Két hideg lazac volt… két
pohár sör… kenyér… hány Kuglered volt fiam?
Vilma. Kettő.
Kelemen. Nekem egy. Három Kugler – És egy fekete.
Főpincér leteszi a számlát.
Kelemen a már készenlétben tartott pénzt odaadja. A többit ossza
el.
Főpincér. Köszönöm alássan. Odébb megy.
Vilma. Most… most félek veled menni.
Kelemen. Most te akarsz itt maradni?
Vilma. A világért sem… csak tudom, mi következik most.
Kelemen. Semmi se következik, ha bevallod, hogy ez az, akit
szerettél.
Vilma. Gyerünk fiam… mert elsirom magam itt…
Kelemen. Azt nem fogod tenni. Arra semmi okod sincs.
Vilma kínlódva. Agyonkinozol.
Kelemen. Nem igaz. Csak őszinteséget kívánok tőled. Kutya
kötelességed megnyugtatni engem. Látod, hogy ez a kérdés izgat,
hogy ez az ember, ez az arc kihoz a sodromból… és… mégis
meghagysz a gyanuban, a félelemben…
Vilma. Hát azt akarod, hogy hazudjam?
Kelemen. Nem. Az igazat akarom. Most hazudsz… ahelyett, hogy
nyiltan beszélnél. Még van rá időd.
Vilma sírva fakad.
Kelemen fölkel. Kérem a ruhát. Vilma is fölkel, zsebkendőjét az
arca elé tartva. Fordulj el, mert meglátják, hogy sirsz… Még félre
találja érteni. Groom és pincér jönnek a ruhával. Menj fiam előre,
jövök én is… A ruhák felvétele közben.
Vilma. Mit akarsz itt csinálni?
Kelemen. Semmi közöd hozzá. Menj csak előre, fiam. Köszönj
szépen oda.
Vilma. Nem.
Kelemen. Olyan intimek vagytok?
Vilma. Mit akarsz tőlem?
Kelemen. Köszönj oda.
Vilma odaköszön.
Szabó némán, fölemelkedve köszön vissza.
Kelemen szintén meghajlik Szabó felé. Indul, megáll, aztán
karonfogva Vilmát, sietve elmennek mind a ketten.
Pincérek a bejárónál. Kezét csókolom. Ajánlom magamat. Szünet.
Zágon csöndesen, melegen. Ez volt az?
Szabó szintúgy. Ez.
Zágon. Sírt.
Szabó búsan igent int.
Zágon. Ez volt az ura?
Szabó. Biztosan. Pszt?
Főpincér. Parancsol?
Szabó. Nem ismeri ezeket, akik…
Főpincér. Nem, kérem.
Szabó. Nem szoktak idejárni?
Főpincér. Nem, kérem. Szünet.
Főpincér elmegy.
Zágon. Rég nem láttad?
Szabó. Hét éve.
Zágon. Szép.
Szabó. Szép.
Zágon. Miféle ember az ura?
Szabó. Bánom is én. Szünet.
Zágon. Hát szervusz, fiam. Mikhál, ezt hallva feláll. Még
meggondolhatod. Jössz velünk az Operába?
Szabó. Köszönöm, nem.
Zágon. Szervusz.
Szabó. Szervusz. Mikhál és Szabó némán üdvözlik egymást. A két
tiszt el. Szünet.
Szabó nagyon elfogódottan. Pincér!
Pincér. Parancsol?
Szabó. Hozzon egy üveg Pommeryt.
Pincér. Igenis kérem. El, a többi pincér is vele megy.
Szabó merengve dobol az ujjaival az asztalon. Szünet. Aztán
kívülről, egyre távolodva, egyre halkabban hallatszik, amint a
pincérek egymásnak mondják: «Egy üveg Pommeryt!» –
«Pommeryt» – «Pommeryt» – «Pommeryt»…
Függöny.
MÁSODIK FELVONÁS.

ELSŐ VÁLTOZÁS.

Uriszoba Kelemenék lakásán. Este van, a szobában lámpa ég. Az


íróasztalon is lámpa, színes ernyővel. Történik egy fél órával az első
felvonás után. Mikor a függöny felgördül a szobában nincs senki. Egy
pillanat mulva csöngetés hallatszik.
A csöngetésre besiet balról a kisasszony és a szobalány. A
kisasszony a szobában marad, a szobalány kimegy a bejáratajtón,
nyitva hagyja, ajtót nyit a hazatérő Kelemen-párnak, velük együtt
jön vissza a szobába.
Kelemenék izgatottan, sebbel-lobbal jönnek, éreztetve, hogy az
egész uton hevesen vitatkoztak. A párbeszéd már az előszobában
kezdődik, hangosan, veszekedve.
Kelemen. Az nem igaz. Az nem igaz.
Vilma. De igaz.
Kelemen. Nem igaz.
Vilma. Uri felfogás dolga.
Kelemen. Nem tűröm, hogy ebbe az uraság fogalmát belekeverd.
Annak ehhez semmi köze. Nincs igazad. Szobalány kimegy.
Vilma. Igenis van, mert uri ember bízik annyira a feleségében,
hogy nem piszkálja a leánykori gyerekségeit.
Kelemen nekihevülve. Hogy úri ember mit csinál, azt tessék…
Meglátja a kisasszonyt. Alszik már a gyerek, kisasszony?
Kisasszony. Nem, nagyságos úr. Nem akar aludni, amíg a
nagyságos úr a mindennapi esti mesét el nem meséli neki.
Kelemen. Mindjárt jövök, kisasszony.
Vilma. Csak menj fiam most. Jobb lesz, ha mesélsz a Janikának.
Ettől ő majd elalszik, te pedig talán lecsöndesedel. Én már nem
birom. Én már kifáradtam…
Kelemen. Igazad van. Ez fontosabb, mint ez a… ez a… Haragosan
indul, már fogja is a kilincset.
Vilma. Alig állok a lábamon… ez az izgalom…
Kelemen. Jól van, jól van.
Vilma. Ez tán meg fog nyugtatni. Menj.
Kelemen. Tessék?
Vilma. Azt mondom: a mesélés majd meg fog nyugtatni téged is.
Kelemen elereszti a kilincset és visszajön. Engem nem lehet
ilyesmivel megnyugtatni. Nekem nem az idegeim nyugtalanok.
Vilma. Hát mid nyugtalan?
Kelemen. Az életem. Az megy lassan tönkre. Újra kezdi. Én neked
ma este már egyszer megmondtam…
Vilma. Cette fille entend tout. Je n’en vois pas la nécessité!
Kelemen. Megmondtam, hogy mi az egyetlen oka ennek az egyre
rosszabbodó idegállapotomnak. Kérem kisasszony, menjen be a
gyerekhez, mindjárt jövök és mesélek neki.
Kisasszony kimegy.
Kelemen hevesen. Ez az úr. Ez a titokzatos úr, aki a paradicsomot
nem tudja enni. Ez az én bajom, illetve nem is ez az ember, hanem
az, hogy te évek óta hazudsz nekem.
Vilma nagyon izgatottan. Ezt a szót most hallom tőled először.
Kelemen. Sajnálom.
Vilma. Nem érdemlem meg, hogy inzultálj. Mutass még egy
asszonyt Pesten, aki úgy él, mint én. Egész nap itthon ülök, nem
járok sehova, szerényen öltözöm, a konyhát vezetem, a harisnyádat
foltozom. Ha valaki bolond, csukassa be magát.
Kelemen. A «hazudsz»-ért bocsánatot kérek. Nem lett volna
szabad ezt mondanom. De mi a tény? A tény az, hogy te ismered ezt
az embert és velem el akarod hitetni, hogy nem is emlékszel a
nevére.
Vilma. Nem emlékszem rá.
Kelemen nyomatékkal. Ez az ember az oka az én egész
betegségemnek. Ez a titok ma egy véletlen folytán kipattant. Most itt
az alkalom belehalni a betegségbe, vagy kigyógyulni belőle.
Vilma hirtelen elhatározással. Hát jó. Figyelj ide.
Kelemen. Figyelek,
Vilma. Hiszel nekem?
Kelemen. Akarok.
Vilma. És megnyugszol, ha megtudod az igazat?
Kelemen. Meg.
Vilma. Akármi is lesz az, amit megtudsz?
Kelemen. Akármi.
Vilma. És vége lesz ennek a nyugtalan, gyanakvó életnek? Ennek
a pokolnak?
Kelemen. Vége.
Vilma. Hát most jól figyelj ide. Ez az ember három évvel azelőtt,
hogy veled megismerkedtem, egy csomó más emberrel együtt
udvarolt nekem, tudja isten tán szerelmes is volt belém. Azóta nem
láttam. És… hangsúlyozva… a nevére sem emlékszem. Na.
Kelemen. Az más.
Vilma. Végre. Hiszed?
Kelemen. Hiszem.
Vilma. Nyugodt vagy?
Kelemen. Nyugodt.
Vilma. Nem lesz miatta több bajom?
Kelemen. Nem.
Vilma kezét nyujtja. Erre adod nekem a becsületszavadat.
Kelemen. Vilma, te egy derék, jó, tisztességes nő vagy. De okos
vagy. Én neked nem adom a becsületszavamat. Tudod mit? Nem is
vagyok nyugodt.
Vilma fokozódó izgalommal. Nem?
Kelemen. Nem.
Vilma. Hát jó. Én megpróbáltam ezt a módszert, mert ez az
egyszerűbb és ugyanoda vezet, ahova a másik. Okos és derék
asszonynak kötelessége azt csinálni, amit én most csináltam. De te
olyan vagy, amilyen vagy, hát most megkapod tőlem a másik
módszert.
Kelemen. Hát az milyen?
Vilma. Fájdalmasabb, mint az előbbi. Nekem ahhoz az emberhez
semmi közöm. Én egyszerűen letagadtam ezt az embert, mert én
kokainnal akartam a fájós fogadat kihúzni. De ugyanazt az
eredményt elérhetem úgy is, hogy fájni fog neked. A fog így is, úgy
is kint lesz a végén. Ilyenek vagytok.
Kelemen mohón. Nos?
Vilma. Fájni fog.
Kelemen mint fent. Nem bánom.
Vilma dacosan. György a neve.
Az itt következő párbeszéd egészen a levélig nagyon gyors,
nagyon izgatott.
Kelemen. Azt hallottam a tisztektől a vendéglőben.
Vilma. Szabó György.
Kelemen. Aha. Szép szürke név.
Vilma. Mint az egész história.
Kelemen mohón. Szeretett téged?
Vilma. Szeretett.
Kelemen. Nagyon?
Vilma. Nem.
Kelemen. Nagyon?
Vilma. Egy kicsit.
Kelemen. Nagyon?
Vilma. Úgy, ahogy szoktak.
Kelemen. Nagyon?
Vilma. Hát szeretett.
Kelemen. Nagyon?
Vilma. Jobban, mint a többiek.
Kelemen a legmagasabb fokon. Nagyon?
Vilma. Nagyon. Szünet.
Kelemen. Nna. Leül.
Vilma. Most boldog vagy, mert kezd fájni?
Kelemen. És te? Szeretted?
Vilma. Szó sincs róla.
Kelemen. Szeretted?
Vilma. Aki ismer, tudhatja.
Kelemen. Szeretted?
Vilma. Tetszett.
Kelemen. Szeretted?
Vilma. Lehet, hogy ő azt hitte.
Kelemen. Szeretted?
Vilma. Nem.
Kelemen. No végre. Mindjárt mondhattad volna, hogy igen.
Szünet.
Vilma. Nem volt egyszerűbb és becsületesebb, ahogy én akartam?
Kelemen. Megkérte a kezedet?
Vilma. Meg. Szünet.
Vilma. Most kérdezd, hogy feleségül mentem-e hozzá.
Kelemen Köszönöm, nem. – Kitől kért meg?
Vilma. Beszélt Félix nagybátyámmal. A bácsi udvariasan
megmondta neki, hogy ne is próbálkozzék nálam.
Kelemen. Nem is próbálkozott?
Vilma. Nem.
Kelemen. Mikor volt az a tennisverseny?
Vilma. Akkor.
Kelemen más, egyszerűbb hangon. Jól játszott?
Vilma. Még ezzel is kínozod magad? Elég jól játszott.
Kelemen. Jól játszott?
Vilma. Hát jól, ha díjat nyert.
Kelemen. Jól játszott?
Vilma. Nagyszerűen játszott.
Kelemen. Na végre. Szünet.
Kelemen. Félix végleg elküldte?
Vilma. Végleg.
Kelemen. Ő mit felelt erre? A kisasszony belép.
Kelemen. Mit akar?
Kisasszony. A Janika várja a nagyságos urat.
Kelemen. Jövök. A kisasszony áll és vár. Mindjárt jövök kérem, nem
hallotta? A kisasszony kimegy.
Rövid szünet.
Vilma hidegen. Ott hagytuk el, hogy ő mit felelt erre.
Kelemen. Mit felelt?
Vilma. Meghajtotta magát és elment. Elutazott. Kulcsot vesz elő a
táskájából, amit eddig a kezében tartott.
Kelemen. Hova?
Vilma. Párisba, Amerikába.
Kelemen. Miféle kulcs az?
Vilma. Semmi. – Kulcs.
Kelemen. Ezzel vége volt?
Vilma. Vége.
Kelemen. Nem írt neked?
Vilma. Nem.
Kelemen. Egy szót se?
Vilma. Egy betűt se.
Kelemen. Mutasd meg a levelet, amit írt.
Vilma. Nem írt.
Kelemen. A jobb felső fiókban tartod a leánykori leveleidet. Ott kell
lenni az övének is. Hol van ennek a fióknak a kulcsa?
Vilma. Itt van. Átadja a kulcsot.
Kelemen átveszi, már nyitja is a fiókot.
Vilma. Képes vagy és kiveszed, elolvasod.
Kelemen. Képes vagyok. Kezében a levélcsomó.
Vilma. Ne keresd, ez az, felül. Kihúzza, átadja. Tessék.
Kelemen visszaadja. Tessék.
Vilma. Én olvassam fel? Nem veszi át a levelet.
Kelemen. Nem szoktam a más leveleit elolvasni.
Vilma nyugodtan. Ezt el fogod olvasni.
Kelemen. Azt nem. De tőled meghallgatom. Kínálja.
Vilma. El fogod olvasni.
Kelemen. Még ha külön felkérsz rá, akkor sem.
Vilma. El fogod olvasni.
Kelemen megadja magát. Olvas. «Kedves kisasszony – ön azt
üzente nekem Félix bátyjával, hogy nem lehet az enyém, mert nem
szeret. Ön azt üzente nekem, hogy nem az a baj, hogy szegény
vagyok és nincs állásom, hanem az, hogy ön nem szeret engem.»
Vilma. Csak olvasd tovább.
Kelemen. Muszáj?
Vilma. Most már illik.
Kelemen olvas. «… Én ezt nem hiszem el magának. Maga szeret
engem és ha én most elutazom, hogy embert csináljak magamból,
ezt azzal fogja bebizonyítani»… beszélve… kezd nekem igazam
lenni… olvas «… hogy megvár engem és nem megy férjhez addig,
amíg én vissza nem jövök.» Beszélve. Kezd neked igazad lenni.
Vilma. Megvártam?
Kelemen. Elismerem, nem vártad meg. Olvas: «Elmegyek,
kivándorlok, ember leszek. De visszajövök. Talán mint győztes
katona, talán mint országok sorsát intéző hatalmas úr, talán mint
világhírű művész, de lehet, hogy mint koldus, szegény cseléd jövök
vissza magához szolgálatért könyörögni. Egyetlen kérésem: ha
szeret, várjon meg. Eljövök érte, visszajövök érte.» Gúnyosan
mosolyog.
Vilma. Nos?
Kelemen. Szegény fiú. Ez a tipikus, ostoba, vidéki szerelmes bucsu-
levele. Ez nem is lehet más.
Vilma. Nekem akkor sem tetszett, amikor kaptam.
Kelemen a levéllel. Ez az a jó kisvárosi romantika. Egy szegény
ügyvédbojtár… visszajön, mint diadalmas hadvezér. Hogy képzeli ő
ezt?
Vilma. Azt ő tudja, szegény.
Kelemen. Napoleonra gondol. Olvas… «Mint országok sorsát intéző
hatalmas úr.» Miniszterelnök? Kancellár? Szabó úr, mint kancellár.
Olvas. «Világhírű művész».
Vilma. Mit akarsz tőle?
Kelemen. Hogy ne legyen ilyen közönséges… Tisztelet, becsület
egy szép szerelmes levélnek. De ezt a cselédromantikát ki kell
nevetni… Ez komikus. A legmálébb azonban az utolsó: nézi… «mint
koldus, szegény cseléd jön vissza, szolgálatért könyörögni». Hogy
képzeli ő ezt?
Vilma. Fiatal volt.
Kelemen nevetve. Hadvezér, nagyúr, művész… Komikus
hangrezgetéssel… vagy mint szegény cseléd… ah, jó romantikus
vidék! Eldobja a levelet.
Vilma fölveszi a földről. Minek dobod el? Látod, annyi elnézés
lehetne benned…
Kelemen. Nem az bánt, hogy szerelmes. Hanem, hogy ilyen
ostoba. Ez a tiszta sablón: a hadvezértől a cselédig. Nevetni kell.
Vilma. Ugyan mit nevetsz rajta?
Kelemen. Nem is nevetek. Sajnálom szegénykét. Nem úgy ült a
vendéglőben, mint egy csatanyertes katona.
Vilma. Talán… ha azzá lett volna…
Kelemen komikus páthosszal… Visszajött volna érted!
Vilma. Biztos, hogy ügyvédbojtár maradt. Tán a vizsgáit se tette
le.
Kelemen. Nagyon szegényesen ült ott. Ez nem intézi országok
sorsát. Paradicsomot, azt nem eszik.
Vilma. Ez minden megjegyzésed? Visszateszi a levelet.
Kelemen. Nem. Akkor tényleg elutazott?
Vilma. El.
Kelemen. Azóta nem láttad?
Vilma. Nem.
Kelemen. Ma láttad először?
Vilma. Ma.
Kelemen. És nem éreztél semmit, amikor bejött? Nem érezted,
hogy visszajött érted?
Vilma. Most már ne gúnyolj engem.
Kelemen. Igen. Szünet. Angyalom. Angyalom. Bocsáss meg
nekem. Most már igazán minden rendben van.
Vilma. Hát nem lett volna egyszerűbb, ha abban maradtunk volna,
hogy a nevét sem tudom?
Kelemen. Ebben is neked volt igazad. Ezt a tíz rossz percet
megtakaríthattam volna. De nem baj. Kint van a fájós fogam.
Vilma. Látod, milyen ostoba vagy?
Kelemen. Látom.
Vilma. Most mindent, mindent tudsz.
Kelemen. Mindent.
Vilma. Lesz most nyugtom?
Kelemen. Lesz.
Vilma. És neked?
Kelemen. Nekem is. Felsóhajt. Most egy okos, szép élet következik.
Mert ez volt a baj. Ez rág rajtam hat hónap óta, amikor Temesvárott
voltam és Leviczkyné elmondta. Fáradt vagy, angyalom?
Vilma. Nagyon… kimerített… ez az este. De az utolsó ilyen volt,
úgy-e?
Kelemen. Az utolsó. Kisasszony megjelenik a gyerekszoba
ajtajában.
Kelemen fölkel. Jövök kisasszony. Kisasszony el, Kelemen a
kilincshez nyúl. Más ember lettem. Visszajön. Tudod… ahogy úgy
bejött szegény a vendéglőbe… olyan hetykén…
Vilma. Ugyan kérlek.
Kelemen. Nem nézett ki rosszul.
Vilma. Ilyenek vagytok. Olyan volt, mint egy vasárnapi fűszeres
legény.
Kelemen. A kancellár nagyon feltünően volt öltözve.
Vilma. Most már te is látod?
Kelemen. Mert tiszta a fejem. A világhírű művész… túlhangosan
beszélt… ízetlenül. Sajnálom.
Vilma. Én nem. Üres ember. Kicsit ostoba is. Ezek hamar
vigasztalódnak. Vidéki gigerli.
Kelemen. Még ha szegény cselédnek jött volna vissza…
Vilma. Ugyan hagyd már azt a gyerekes levelet. Ez is elég szép
volt tőle. Te ilyet nem írtál volna…
Kelemen. Soha.
Vilma. Te édes… okos… Boldog vagyok, hogy megnyugodtál.
Kelemen. Bocsáss meg.
Vilma elérzékenyülve. Nehéz veled, fiam. Nagyon nehéz veled.
Kelemen. Csak volt. Te vagy az okos…
Vilma. Oh…
Kelemen. Csak ne szerénykedjél. Különb vagy, mint én.
Meggyógyítottál, mint egy beteg gyereket. Talán örök életemre. Még
ha szeretted is.
Vilma. De…
Kelemen. Most már ezt se bánnám. Így, nyugodt szemmel látom,
hogy nincs semmibb, mint egy ilyen kihűlt, felületes érzés. És még
jobb, mintha semmi se lett volna. Mert akkor talán most… de így…
boldog vagyok. A gyerekszoba ajtaja megnyílik.
Kelemen. Pihend ki magad, fiam. Még hátra van az estély, bál,
hangverseny… Jövök, kisasszony. Bemegy a gyerekszobába, az ajtó
nyitva marad, úgy, hogy a közönség a benn történőket jól látja és
hallja… Na Janikám, hát még nem alszol?
Jani. Nem.
Kisasszony. A papa sokáig váratta a Janikát a mesével.
Kelemen leül az ágy mellé. Imádkoztál már?
Kisasszony. Oh igen, nagyon jó volt a Janika.
Kelemen. Hát miről meséljek neked?
Jani. A farkasról.
Kelemen. Megint a farkasról. Hiszen már két hét óta minden este a
farkast mesélem neked.
Jani. De a végit még nem mondta.
Kelemen. Mert mindig elalszol a közepén.
Jani. Mesélje megint, de előlről.
Kelemen. Megint? Hát jó. Hát… volt egyszer… Vilma is bemegy a
gyerekhez.
Kelemen. Volt egyszer egy szegény ember, akinek volt egy kis
fehér báránya.
Jani. A falu végén lakott.
Kelemen. Igen fiam, ott lakott a falu végin egy kicsi, kicsi, kicsi
házban. Hát aztán egyszer… mikor este lett… Sötét volt, nagyon
sötét… hát hogy lefeküdt aludni, kint hagyta a bárányt a kertben.
Sötét éjszaka volt és fönt a hegyen volt egy nagy erdő. Abba laktak
a farkasok. Mérges farkasok, nagy foguk volt…
Jani. Igen.
Kelemen… ahogy elaludt a szegény ember a kis házban, hát…
nagy csönd volt, mert már mindenki aludt a faluban… hát egyszerre
csak kijött az erdőből egy farkas. Jött le a hegyen. A szeme világított
a sötétben. Jött, jött.
Jani. Igen.
Kelemen. A szegény ember csak feküdt az ágyában és nem is
gondolta, hogy a farkas ki fog jönni az erdőből. A következőket
egyre fokozódó érzéssel, szinte elárulva magát, már Vilma címére
mondja. Pedig mindig nagyon féltette a kis bárányát, mert nem volt
neki egyebe ezen a világon, csak az a kis báránya… Csak azt
szerette, mindig azt szerette, azért féltette olyan nagyon, és
majdnem sírt, amikor arra gondolt, hogy egyszer csak jöhet egy
farkas, akinek minden mindegy, mert csak enni akar, és elviszi az ő
tiszta kis bárányát. Azért nem lehet mondani, hogy a szegény ember
bolond volt, mert mit csináljon ő egyedül ennyi sok éhes farkas
ellen?
Jani. Igen. Vilma kimegy a szobából és megáll a küszöbön.
Jani. A mama mért megy ki?
Vilma a kanapé felé megy. Fáradt vagyok, fiacskám.
Kelemen. A mamuska nem szereti ezt a mesét. Szünet. Vilma ledől
a kanapéra.
Jani. Hát aztán?
Kelemen. Hát aztán egyszerre csak már ott volt a farkas a falu
végén. Hüü, hogy villogott a szeme a sötétben. Olyan lassan jött,
olyan puhán lépett, hogy nem hallotta senki. Jött, jött, egyre
közelebb.
Jani. Igen.
Kelemen. A kis bárány nem is tudta, mi az: egy farkas. Ő nem
tudta, hogy a farkas őtet meg akarja enni. Csak nézte a kertből,
nézte, amint jött az égő szemeivel, a nagy fogával. Hát egyszerre
csak megállt a kert mellett a farkas. A szegény ember aludt. Hát
csak zsupsz, átugrott a farkas a kerítésen. És ott állt a kis bárány
mellett. Csak akkor ijedt meg a kis bárány. Elkezdett szegény
bégetni, és szaladt az ajtóhoz, kaparta a küszöböt, de a szegény
ember nem hallotta, mert aludt. Akkor a farkas elordította magát!
bu, bu és nekiugrott a kis báránynak. Kitátotta a száját, lehetett látni
a nagy fogait…
Kisasszony aki az ágy lábánál áll, a szájára illeszti ujjait.
Kelemen fölkel, halkan. Alszik?
Kisasszony halkan. Alszik. Tessék csak csöndesen kijönni.
Eloltja a lámpát, csak éjjeli lámpa marad a gyerekszobában.
E pillanatban a szomszédban gyerekes, kezdő zongorázó játéka
hallatszik. Divatos keringőt játszik.
Kelemen és kisasszony kijönnek a színpadra, kisasszony becsukja
a gyerekszoba ajtaját.
Kelemen hangosan. Máskor korábban kell majd…
Kisasszony meglátja, hogy a kanapén fekvő Vilma is elaludt.
Pssszt!
Kelemen halkan. Mi az?
Kisasszony. Alszik.
Kelemen. Szegényke… őt is elaltattuk a mesével. Menjen csak ki,
kisasszony, hagyja aludni, fáradt volt, jó lesz, ha pihen egy órát…
addig csak készítsék elő az estélyruháját… úgy háromnegyed óra
mulva költse fel… Nézi. Szegénykém… hadd pihenje ki magát.
Kisasszony. Ez itt a szomszédban… a tanárnak a lánya… minden
este pont kilenckor jut neki eszébe zongorázni.
Kelemen. Nem baj.
Kisasszony. Átmegyek talán hozzájuk… ha megkérjük,
abbahagyja…
Kelemen. Ne bántsa. Ez még tán jobban elringatja. Az íróasztalról
írásokat vesz fel. Nekem is van még dolgom… majd elvégzem a
szalonban…
Kisasszony pléddel letakarja Vilma lábát, eloltja a csillárt és
kimegy.
Kelemen az íróasztalon megnézi a levelet… a diadalmas hadvezér…
nagyúr… művész… komikus sóhaj esetleg szegény cseléd…
mosolyog. Összepakolja az írásokat és lábujjhegyen megy balra a
lakás ajtaja felé, miután színes kendőt borított az íróasztal
lámpájára. Mikor Vilma előtt elhalad. Egy mesétől… elaludt mind a
két gyerek… El balra.
A színpadon sötét van. Csend, csak a zongoraszó hallatszik
szeliden. Most elkezd az íróasztal lámpája halványodni, s a
zongoraszó ereje nőni, növekedni. Egyre erősebb lesz. A lámpa
végleg kialszik és a koromsötétben egyre erősebben, szebben szól a
zongora. Négykézre. Majd egy hegedű kezdi kísérni, majd kettő,
majd sok, majd egyre több zenekari hangszer: kisbőgő, klarinét szól
vele, végül nagybőgők, nagydob, a szegény, kezdő zongoramuzsika
lassan, szinte észrevétlenül egy teljes nagy zenekar játékává válik,
amely még mindig erősbödik, végül fortissimó szól, harsogva, zúgva,
trombitákkal, nagydobbal. Ezalatt megtörtént a nyílt változás a
színpadon egy fekete függöny mögött.
Vilma amikor már készen van a változás, a koromsötétben,
álmában felsikolt. Ne bánts! Ne bánts! Nem tettem semmi rosszat!
Ne bánts!
Erre a harmadik «ne bánts»-ra hirtelen ragyogó világosság gyúl a
színpadon.

MÁSODIK VÁLTOZÁS.

A hirtelen kivilágosodott színpad a kegyelmes asszony nagyszerű


kastélyának lépcsős, oszlopos csarnokát, hallját ábrázolja. A felső
emelt részen látható a zenekar, amely tovább játssza a keringőt,
fortissimo. A szinen nincs senki.
Csak egy pillanatig üres a szín, mert rögtön berohan balról
sikoltozva Vilma, tulzottan fényes és erősen dekolletált estélyi
toalettben, folytatva a sötétben megkezdett sikoltozását.
Vilma. Ne bánts! Ne bánts! Semmi rosszat nem tettem!
Rohan felfelé a lépcsőn.
Kegyelmes asszony, Mici, Titkár, sietve jönnek utána.
Innen kezdve ez a kép a következő változásig több mint gyors,
valóságos vihartempóban játszandó, természetesen meglassítva a
tempót, azokon a helyeken, ahol a cselekmény vagy a dialog
megkívánja.
Kegyelmes. Nagyon izgatottan, szaladva. Vilma… az istenért!
Felszaladnak utána, a kegyelmes karonfogja. Vilma oda van az
izgalomtól. Az istenért, édes fiam, mit akar? Jöjjön! Lefelé vonszolja
a lépcsőn. Titkár úr kérem… húzza be azonnal ott azt a függönyt…
Titkár már rohan is és ráhúzza a zenekarra a függönyt.
Titkár kiáltva a zenekarhoz. Elég… menjenek fel a nagy szalonba!
Zene lassan elhallgat.
Kegyelmes. Micike, azonnal kérek egy pohár vizet.
Mici felrohan a lépcsőn, de ép jön bal 3. egy lakáj, azt kituszkolja,
vele együtt elrohan fenn, oldalt balra. Vizet hozzon!
Kegyelmes idegesen, szakgatottan, arisztokratikus gőggel, mereven
beszél, titkolja hallatlan izgalmát. Nagyon gyorsan beszél. Titkár úr
kérem, gondoskodjék, hogy a hangverseny az emeleten a
legnagyobb rendben menjen tovább; senki abból, ami itt történt,
semmit észre ne vegyen és igyekezzék, hogy mi itt most magunk
maradhassunk.
Titkár. Parancsára, kegyelmes grófné. Jobbra, fenn, elrohan.
Mici, Lakáj ugyanakkor balra fenn megjelennek, Mici üvegekkel,
lakáj tálcán vízzel.
Kegyelmes. Üljön le édes gyermekem, erre a székre.
Vilma. Nem… Nem… Vizet, üveget nyújtanak feléje. Lakáj el.
Kegyelmes. Micike ugorjon és vigyázzon, hogy senki semmit ne
vegyen észre. Mici rohanva el. Mi volt az, fiam?
Vilma lihegve. Az uram…
Kegyelmes. Mit csinált?
Vilma. Berontott… egy szobába… ahol én beszélgettem…
Kegyelmes. Kivel?
Vilma. A főhadnaggyal…
Kegyelmes. És… és… és…??
Vilma. Meg akar ölni!… Felszalad a lépcsőre. Rohanva jön bal 1.
Kelemen.
Kelemen. Ne szaladj előlem!
Kegyelmes útját állja. Az istenért, doktor, mit csinál?
Vilma. Kegyelmes asszonyom… mentsen meg… A kegyelmes
asszony mögé menekül.
Kelemen. Itt hiába minden kegyelmes asszony… a becsületemről
van szó… Vilmához nagyon izgatottan. Ki volt az a tiszt? Ki volt az az
ulánus tiszt?
Vilma a lépcsőről, boldogan. Ki volt az a tiszt? Jenő, Jenő… az a
tiszt a diadalmas katona volt… Jenő, te kinevetted a levelét és ő
most itt egyszerre elébem lépett, hét év multán visszajött értem!
Ahogy megírta… visszajött, mint győztes hadvezér!
Kelemen. Megcsaltál! Rohan feléjük. Vilma sikoltva fel a lépcsőn,
és az ép akkor beszaladó Micivel fenn, balra el, a kegyelmes útját
állja Kelemennek.
A kegyelmes grófné. Mit akar?! Megőrült?! Mi történt?
Kelemen. Megcsalt a feleségem.
Grófné. Micsoda?
Kelemen. Itt, az ön házában.
Grófné. Csillapodjék kérem. Nem tudom. Hát mi volt?
Kelemen. Fenn az emeleten… a kis szalonban… már egész este
nézem, hogy jár körülötte egy ulánus tiszt. Egy ulánus tiszt kergeti,
üldözi, hajszolja…
Grófné. Csöndesebben, az istenért, meghallják.
Kelemen. Lestem, néztem… függöny mögül, oszlop mögül, a
folyosóról… utánuk mentem lábujjhegyen… megfogtam őket együtt
a kis szalonban, ahol összebújva suttogtak…
Grófné. Kik?
Kelemen. A feleségem és a tiszt. A tiszt átkarolta a feleségemet. A
szalonban sötét volt… csak a szomszéd szobából jött világosság…
Berohantam… az asszony elszaladt és a tisztet kicipelte egy frakkos
úr… azt se tudom, ki volt… a sikoltásra jött be…
Ritterné rohanva jön le. Mi történt itt? Mit csinált a lányommal?
Kelemen. A lánya becstelenül megcsalt engem!
Grófné. Csöndesebben…
Ritterné. Hogy mer ilyet mondani?
Kelemen. Sötét szobában ölelkezett egy katonával!
Ritterné. Hazugság!
Grófné. Szent isten… és mindez az én házamban… az én
estélyemen. Meghalok bele, nagyságos asszonyom, meghalok bele.
Ezt nem élem túl!
Ritterné. Csak nyugalom, kegyelmes asszonyom.
Kelemen. Nincs nyugalom.
Ritterné. Nem igaz.
Kelemen. De igaz! Láttam! Ne védje! Maga is olyan volt!
Grófné. Az istenért.
Ritterné. Mit akar? Mit akar itt csinálni? Vendégségben van!
Kelemen. Nem bánok semmit.
Grófné. Kiméljenek, kérem… tekintsenek engem… tekintsék a
családomat… micsoda rettenetes szégyen!
Kelemen. Nem, nem ölöm meg. Más büntetést kap. Megcsalt,
megölte az életemet… itt, nyilvánosan, a százötven vendég előtt
fogom megszégyeníteni, itt fogom kikiáltani, hogy mit tett… itt
fogom megbüntetni… A két nő közül ki akar szabadulni, hogy
felrohanjon.
Ritterné sírva. Jenő!
Grófné elébük kerülve felszalad a lépcsőre, útját állja és minden
erejét összeszedve, méltóságteljessé válik. Megálljon. Csinálhat, amit
akar, de nem az én házamban. Doktor úr, ezen kijelentésével
elvesztette nálam a vendégjogot. Az én házam minden botránytól
ment és az is marad. Én gróf Walmsdorff püspök huga vagyok és a
házam tisztaságát mindenáron meg kell hogy védelmezzem. Értette?
Közben bejött a titkár.
Kelemen. Én az életemmel is leszámoltam. Nekem semmi nem
fontos.
Grófné. Az én házamban nem lesz házasságtörési botrány.
Kelemen. De volt!
Ritterné. Nem igaz!
Grófné. Önök most el fognak távozni az én házamból minden
feltűnés nélkül. Mit akar, titkár úr.
Titkár. Alázatosan megjegyzem, kegyelmes grófné és egyben
bocsánatot kérek…
Grófné. Ne fecsegjen annyit, mit akar?
Titkár. Alázattal… hogy feltűnés nélkül már nehezen távozhatnak
őnagyságáék… mert a futkosásra többen kijöttek a nagyteremből…
Grófné. És ön mit csinált?
Titkár. Visszaküldtem őket azzal, hogy őnagysága rosszúl lett.
Grófné. Elhitték?
Titkár. Alázattal… nem. Mert a férfihang szitkozódásait, ha nem is
a maguk egészében…
Grófné. Hallották?
Titkár. Legmélyebb sajnálattal kell, jelentsem, hogy: igen. A
kegyelmes grófné minden erélyére van e percben szükség.
Grófné. Tehát nem mehetnek el egyszerűen. Kérem e súlyos
percben szedjük össze az eszünket és az idegeinket. Az én családom
és házam becsülete forog kockán. Doktor úr ön le fog csillapodni és
akkor felesége őnagyságával tüntetőleg végig fog sétálni az összes
termeken. Intézkedni fogok, hogy a nagyteremben odalépjen
önökhöz az a tiszt úr… önök nehány barátságos szót váltanak vele s
azzal távoznak a házból.
Ritterné. Igen… igen… valaki szóljon a katonának… csak botrányt
ne!…
Grófné. Majd megkérem öcsémet…
Ritterné. Igen, az attasé úr…
Titkár. Alázattal… az attasé úr őméltósága volt az, aki a
főhadnagy urat a… botrány színhelyéről elvezette.
Grófné. Rettenetes! Még neki is kellemetlensége lesz! Még őt is
belekeverik!
Titkár. Az attasé úr őméltósága e pillanatban barátságosan
beszélget a főhadnagy úrral.
Grófné. De hát ki az a főhadnagy?
Kelemen. Én nem tudom.
Titkár. Egy ulánus főhadnagy a meghívott tíszt urak közül.
Grófné. Titkár úr azonnal értesíti Kelemenné őnagyságát, hogy
idevárjuk és megkéri az attasé urat, hogy azonnal jöjjön fel hozzám
az ebédlőbe. Két lakájhoz, akik fenn balról jobbfelé vonulnak. Mit
visznek ott?
Titkár. Malotti művész úr az öltözőjében van már és kilenc darab
citromot kéretett az énekhangjához. Lakájok el.
Grófné. Csak nem hallott a művész valamit?
Titkár. Nem hiszem. Az ajtó vastag. El.
Kelemen. Kegyelmes grófné…
Grófné nagyon idegesen. Kérem doktor, lekötelez, ha egy szót
sem beszél, mert félek, hogy elveszítem azt a nyugalmamat, amit…
reszketve… most minden erőm megfeszítésével is… de meg kell
tartanom… e súlyos pillanatban… nekem, szegény
özvegyasszonynak…
Kelemen bűnbánattal. Bocsásson meg, grófné.
Grófné idegesen nyújta csókra kezét. Doktor… ezt nem
érdemeltem öntől… aki azért jött, hogy családom jóságát élvezze…
Ritterné mély meghajlással. Nevükben én is a legőszintébb…
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!

textbookfull.com

You might also like