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

Maya Python for Games and Film A Complete Reference for Maya Python and the Maya Python API 1st Edition Adam Mechtley download

The document provides a comprehensive overview of using Python within Autodesk Maya, detailing various programming interfaces and tools available for executing Python scripts. It covers the differences between MEL, Python, and C++ APIs, as well as practical guidance on using the Command Line, Script Editor, and Shelf for script execution and management. Additionally, it includes a chapter outline and learning objectives to help users effectively interact with Maya through Python programming.

Uploaded by

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

Maya Python for Games and Film A Complete Reference for Maya Python and the Maya Python API 1st Edition Adam Mechtley download

The document provides a comprehensive overview of using Python within Autodesk Maya, detailing various programming interfaces and tools available for executing Python scripts. It covers the differences between MEL, Python, and C++ APIs, as well as practical guidance on using the Command Line, Script Editor, and Shelf for script execution and management. Additionally, it includes a chapter outline and learning objectives to help users effectively interact with Maya through Python programming.

Uploaded by

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

Maya Python for Games and Film A Complete

Reference for Maya Python and the Maya Python


API 1st Edition Adam Mechtley pdf download

https://ebookgate.com/product/maya-python-for-games-and-film-a-
complete-reference-for-maya-python-and-the-maya-python-api-1st-
edition-adam-mechtley/

Get Instant Ebook Downloads – Browse at https://ebookgate.com


Instant digital products (PDF, ePub, MOBI) available
Download now and explore formats that suit you...

Practical Maya Programming with Python 1st Edition


Galanakis

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

ebookgate.com

Python The Complete Manual The essential handbook for


Python users Master Python today First Edition Unknown

https://ebookgate.com/product/python-the-complete-manual-the-
essential-handbook-for-python-users-master-python-today-first-edition-
unknown/
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

Python for Beginners 2018 Edition Learn to Code with


Python Mark Lassoff

https://ebookgate.com/product/python-for-beginners-2018-edition-learn-
to-code-with-python-mark-lassoff/

ebookgate.com
Python Essential Reference 3rd Edition Beazley

https://ebookgate.com/product/python-essential-reference-3rd-edition-
beazley/

ebookgate.com

MEL Scripting for Maya Animators 1st Edition Mark R.


Wilkins

https://ebookgate.com/product/mel-scripting-for-maya-animators-1st-
edition-mark-r-wilkins/

ebookgate.com

Python pocket reference 5ed. Edition Mark Lutz

https://ebookgate.com/product/python-pocket-reference-5ed-edition-
mark-lutz/

ebookgate.com

Python for Finance 1st Edition Yuxing Yan

https://ebookgate.com/product/python-for-finance-1st-edition-yuxing-
yan/

ebookgate.com

Python Tricks A Buffet of Awesome Python Features Dan


Bader

https://ebookgate.com/product/python-tricks-a-buffet-of-awesome-
python-features-dan-bader/

ebookgate.com
Chapter

Maya Command Engine


1
and User Interface

CHAPTER OUTLINE
Interacting with Maya 4
Maya Embedded Language 5
Python 5
C++ Application Programming Interface 6
Python API 6
Executing Python in Maya 6
Command Line 6
Script Editor 8
Maya Shelf 10
Maya Commands and the Dependency Graph 11
Introduction to Python Commands 15
Flag Arguments and Python Core Object Types 19
Numbers 20
Strings 20
Lists 20
Tuples 21
Booleans 21
Flag = Object Type 21
Command Modes and Command Arguments 22
Create Mode 22
Edit Mode 23
Query Mode 23
Python Command Reference 24
Synopsis 25
Return Value 25
Related 25
Flags 25
Python Examples 26
Python Version 26
Python Online Documentation 26
Concluding Remarks 27
Maya Python for Games and Film. DOI: 10.1016/B978-0-12-378578-7.00001-6
© 2012 Elsevier Inc. All rights reserved. 3
4 CHAPTER 1 Maya Command Engine and User Interface

BY THE END OF THIS CHAPTER, YOU WILL BE ABLE TO:


■ Compare and contrast the four Maya programming interfaces.
■ Use the Command Line and Script Editor to execute Python commands.
■ Create a button in the Maya GUI to execute custom scripts.
■ Describe how Python interacts with Maya commands.
■ Define nodes and connections.
■ Describe Maya’s command architecture.
■ Learn how to convert MEL commands into Python.
■ Locate help for Python commands.
■ Compare and contrast command arguments and flag arguments.
■ Define the set of core Python data types that work with Maya commands.
■ Compare and contrast the three modes for using commands.
■ Identify the version of Python that Maya is using.
■ Locate important Python resources online.

To fully understand what can be done with Python in Maya, we must first
discuss how Maya has been designed. There are several ways that users
can interact with or modify Maya. The standard method is to create content
using Maya’s graphical user interface (GUI). This interaction works like any
other software application: Users press buttons or select menu items that
create or modify their documents or workspaces. Despite how similar Maya
is to other software, however, its underlying design paradigm is unique in
many ways. Maya is an open product, built from the ground up to be capable
of supporting new features designed by users. Any Maya user can modify or
add new features, which can include a drastic redesign of the main interface
or one line of code that prints the name of the selected object.
In this chapter, we will explore these topics as you begin programming in
Python. First, we briefly describe Maya’s different programming options and
how they fit into Maya’s user interface. Next, we jump into Python by exploring
different means of executing Python code in Maya. Finally, we explore some
basic Maya commands, the primary means of modifying the Maya scene.

INTERACTING WITH MAYA


Although the focus of this book is on using Python to interact with Maya,
we should briefly examine all of Maya’s programming interfaces to better
understand why Python is so unique. Autodesk has created four different
Interacting with Maya 5

Maya user interface

MEL Python C++

Maya Command Engine Maya API

Maya application core

■ FIGURE 1.1 The architecture of Maya’s programming interfaces.

programming interfaces to interact with Maya, using three different pro-


gramming languages. Anything done in Maya will use some combination
of these interfaces to create the result seen in the workspace. Figure 1.1
illustrates how these interfaces interact with Maya.

Maya Embedded Language


Maya Embedded Language (MEL) was developed for use with Maya and is
used extensively throughout the program. MEL scripts fundamentally define
and create the Maya GUI. Maya’s GUI executes MEL instructions and Maya
commands. Users can also write their own MEL scripts to perform most
common tasks. MEL is relatively easy to create, edit, and execute, but it is
also only used in Maya and has a variety of technical limitations. Namely,
MEL has no support for object-oriented programming. MEL can only com-
municate with Maya through a defined set of interfaces in the Command
Engine (or by calling Python). We will talk more about the Command
Engine later in this chapter.

Python
Python is a scripting language that was formally introduced to Maya in
version 8.5. Python can execute the same Maya commands as MEL using
Maya’s Command Engine. However, Python is also more robust than MEL
because it is an object-oriented language. Moreover, Python has existed
since 1980 and has an extensive library of built-in features as well as a
large community outside of Maya users.
6 CHAPTER 1 Maya Command Engine and User Interface

C++ Application Programming Interface


The Maya C++ application programming interface (API) is the most
flexible way to add features to Maya. Users can add new Maya objects
and features that can execute substantially faster than MEL alternatives.
However, tools developed using the C++ API must be compiled for new
versions of Maya and also for each different target platform. Because of
its compilation requirements, the C++ API cannot be used interactively
with the Maya user interface, so it can be tedious to test even small bits
of code. C++ also has a much steeper learning curve than MEL or Python.

Python API
When Autodesk introduced Python into Maya, they also created wrappers
for many of the classes in the Maya C++ API. As such, developers can use
much of the API functionality from Python. The total scope of classes acces-
sible to the Python API has grown and improved with each new version of
Maya. This powerful feature allows users to manipulate Maya API objects
in ordinary scripts, as well as to create plug-ins that add new features to Maya.
In this book, we focus on the different uses of Python in Maya, including
commands, user interfaces, and the Python API. Before we begin our
investigation, we will first look at the key tools that Maya Python program-
mers have at their disposal.

EXECUTING PYTHON IN MAYA


Maya has many tools built into its GUI that allow users to execute Python
code. Before you begin programming Python code in Maya, you should
familiarize yourself with these tools so that you know not only what tool
is best for your current task, but also where to look for feedback from your
scripts.

Command Line
The first tool of interest is the Command Line. It is located along the
bottom of the Maya GUI. You can see the Command Line highlighted in
Figure 1.2.
The Command Line should appear in the Maya GUI by default. If you
cannot see the Command Line, you can enable it from the Maya main
menu by selecting Display → UI Elements → Command Line.
The far left side of the Command Line has a toggle button, which says
“MEL” by default. If you press this button it will display “Python.”
Executing Python in Maya 7

■ FIGURE 1.2 Programming interfaces in the Maya GUI.

The language displayed on this toggle button tells Maya which scripting
language to use when executing commands entered in the text field imme-
diately to the right of the button. The right half of the Command Line, a
gray bar, displays the results of the commands that were entered in the text
field. Let’s create a polygon sphere using the Command Line.
1. Switch the Command Line button to “Python.” The button is located on
the left side of the Command Line.
2. Click on the text field in the Command Line and enter the following
line of text.
import maya.cmds;

3. Press Enter.
4. Next enter the following line of code in the text field.
maya.cmds.polySphere();

5. Press Enter. The above command will create a polygon sphere object
in the viewport and will print the following results on the right side
of the Command Line.
# Result: [u'pSphere1', u'polySphere1']
8 CHAPTER 1 Maya Command Engine and User Interface

You can use the Command Line any time you need to quickly execute a
command. The Command Line will only let you enter one line of code at
a time though, which will not do you much good if you want to write a
complicated script. To perform more complex operations, you need the
Script Editor.

Script Editor
One of the most important tools for the Maya Python programmer is the Script
Editor. The Script Editor is an interface for creating short scripts to interact
with Maya. The Script Editor (shown on the right side in Figure 1.2) consists
of two panels. The top panel is called the History Panel and the bottom panel
is called the Input Panel. Let’s open the Script Editor and execute a command
to make a sphere.
1. Open a new scene by pressing Ctrl + N.
2. Open the Script Editor using either the button located near the bottom
right corner of Maya’s GUI, on the right side of the Command Line
(highlighted in Figure 1.2), or by navigating to Window → General
Editors → Script Editor in Maya’s main menu. By default the Script
Editor displays two tabs above the Input Panel. One tab says “MEL”
and the other tab says “Python.”
3. Select the Python tab in the Script Editor.
4. Click somewhere inside the Input Panel and type the following lines of
code.
import maya.cmds;
maya.cmds.polySphere();

5. When you are finished press the Enter key on your numeric keypad. If
you do not have a numeric keypad, press Ctrl + Return.
The Enter key on the numeric keypad and the Ctrl + Return shortcut are
used only for executing code when working in the Script Editor. The reg-
ular Return key simply moves the input cursor to the next line in the Input
Panel. This convention allows you to enter scripts that contain more than
one line without executing them prematurely.
Just as in the Command Line example, the code you just executed created a
generic polygon sphere. You can see the code you executed in the History
Panel, but you do not see the same result line that you saw when using the
Command Line. In the Script Editor, you will only see a result line printed
when you execute a single line of code at a time.
6. Enter the same lines from step 4 into the Input Panel, but do not execute
them.
Executing Python in Maya 9

7. Highlight the second line with your cursor by triple-clicking it and then
press Ctrl + Return. The results from the last command entered should
now be shown in the History Panel.
# Result: [u'pSphere2', u'polySphere2']

Apart from printing results, there are two important things worth noting
about the previous step. First, highlighting a portion of code and then press-
ing Ctrl + Return will execute only the highlighted code. Second, high-
lighting code in this way before executing it prevents the contents of the
Input Panel from emptying out.
Another useful feature of the Script Editor is that it has support for marking
menus. Marking menus are powerful, context-sensitive, gesture-based
menus that appear throughout the Maya application. If you are unfamiliar
with marking menus in general, we recommend consulting any basic Maya
user’s guide.
To access the Script Editor’s marking menu, click and hold the right mouse
button (RMB) anywhere in the Script Editor window. If you have nothing
selected inside the Script Editor, the marking menu will allow you to
quickly create new tabs (for either MEL or Python) as well as navigate
between the tabs. As you can see, clicking the RMB, quickly flicking to
the left or right, and releasing the RMB allows you to rapidly switch
between your active tabs, no matter where your cursor is in the Script Edi-
tor window. However, the marking menu can also supply you with context-
sensitive operations, as in the following brief example.

1. Type the following code into the Input Panel of the Script Editor, but
do not execute it.
maya.cmds.polySphere()

2. Use the left mouse button (LMB) to highlight the word polySphere in
the Input Panel.
3. Click and hold the RMB to open the Script Editor’s marking menu. You
should see a new set of options in the bottom part of the marking menu.
4. Move your mouse over the Command Documentation option in the
bottom of the marking menu and release the RMB. Maya should
now open a web browser displaying the help documentation for the
polySphere command.

As you can see, the Script Editor is a very useful tool not only for creating
and executing Python scripts in Maya, but also for quickly pulling up infor-
mation about commands in your script. We will look at the command
documentation later in this chapter.
10 CHAPTER 1 Maya Command Engine and User Interface

At this point, it is worth mentioning that it can be very tedious to continually


type common operations into the Script Editor. While the Script Editor
does allow you to save and load scripts, you may want to make your script
part of the Maya GUI. As we indicated earlier, clicking GUI controls
in Maya simply calls commands or executes scripts that call commands.
Another tool in the Maya GUI, the Shelf, allows you to quickly make a
button out of any script.

Maya Shelf
Now that you understand how to use the Command Line and the Script
Editor, it is worth examining one final tool in the Maya GUI that will be
valuable to you. Let’s say you write a few lines of code in the Script Editor
and you want to use that series of commands later. Maya has a location for
storing custom buttons at the top of the main interface, called the Shelf,
which you can see in Figure 1.3. If you do not see the Shelf in your GUI
layout, you can enable it from Maya’s main menu using the Display →
UI Elements → Shelf option.
You can highlight lines of code in the Script Editor or Command Line and
drag them onto the Shelf for later use with the middle mouse button

■ FIGURE 1.3 The Shelf.


Maya Commands and the Dependency Graph 11

(MMB). In the following example, you will create a short script and save it
to the Shelf.
1. Type in the following code into the Script Editor, but do not execute
it (when executed, this script will create a polygon sphere and then
change the sphere’s vertex colors to red).
import maya.cmds;
maya.cmds.polySphere(radius=5);
maya.cmds.polyColorPerVertex(
colorRGB=[1,0,0],
colorDisplayOption=True
);

2. Click the Custom tab in the Shelf. You can add buttons to any shelf, but
the Custom shelf is a convenient place for users to store their own
group of buttons.
3. Click and drag the LMB over the script you typed into the Script Editor
to highlight all of its lines.
4. With your cursor positioned over the highlighted text, click and hold
the MMB to drag the contents of your script onto the Shelf.
5. If you are using Maya 2010 or an earlier version, a dialog box will
appear. If you see this dialog box, select “Python” to tell Maya that
the script you are pasting is written using Python rather than MEL.
6. You will now see a new button appear in your Custom tab. Left-click on
your new button and you should see a red sphere appear in your viewport
as in Figure 1.3. If you are in wireframe mode, make sure you enter shaded
mode by clicking anywhere in your viewport and pressing the number 5 key.
You can edit your Shelf, including tabs and icons, by accessing the
Window → Settings/Preferences → Shelf Editor option from the main
Maya window. For more information on editing your Shelf, consult the
Maya documentation or a basic Maya user’s guide. Now that you have an
understanding of the different tools available in the Maya GUI, we can start
exploring Maya commands in greater detail.

MAYA COMMANDS AND THE DEPENDENCY GRAPH


To create a polygonal sphere with Python, the polySphere command must
be executed in some way or other. The polySphere command is part of the
Maya Command Engine. As we noted previously, the Maya Command
Engine includes a set of commands accessible to both MEL and Python.
As we briefly discussed previously, Maya is fundamentally composed of a core
and a set of interfaces for communicating with that core (see Figure 1.1).
The core contains all the data in a scene and regulates all operations on these
12 CHAPTER 1 Maya Command Engine and User Interface

data—creation, destruction, editing, and so on. All of the data in the core are
represented by a set of objects called nodes and a series of connections that
establish relationships among these nodes. Taken together, this set of relation-
ships among nodes is called the Dependency Graph (DG).
For example, the polygon sphere object you created earlier returned the
names of two nodes when you created it: a node that describes the geome-
try of the sphere and a transform node that determines the configuration of
the sphere shape in space. You can see information on nodes in an object’s
network using the Attribute Editor (Window → Attribute Editor in the
main menu) or as a visual representation in the Hypergraph (Window →
Hypergraph: Connections in the main menu). Because this point is so
important, it is worth looking at a brief example.
1. If you no longer have a polygon sphere in your scene, create one.
2. With your sphere object selected, open the Hypergraph displaying
connections by using the Window → Hypergraph: Connections option
from the main menu.
3. By default, the Hypergraph should display the connections for your
currently selected sphere as in Figure 1.4. If you do not see anything,

■ FIGURE 1.4 The Hypergraph.


Maya Commands and the Dependency Graph 13

then select the option Graph → Input and Output Connections from
the Hypergraph window’s menu.
As you can see, a default polygon sphere consists of four basic nodes
connected by a sequence of arrows that show the flow of information. The
first node in the network is a polySphere node, which contains the para-
meters and functionality for outputting spherical geometry (e.g., the radius,
the number of subdivisions, and so on). In fact, if you highlight the arrow
showing the connection to the next node, a shape node, you can see what
data are being sent. In this case, the polySphere node’s output attribute is
piped into the inMesh attribute of the shape node.
If you were to delete the construction history of this polygonal sphere
(Edit → Delete by Type → History from the main menu), the polySphere
node would disappear and the sphere’s geometry would then be statically
stored in the shape node (pSphereShape1 in Figure 1.4). In short, if the
polySphere node were destroyed, its mesh information would be copied into
the pSphereShape node, and you would no longer be able to edit the radius
or number of subdivisions parametrically; you would have to use modeling
tools to do everything by hand.
While you can also see that information is piped from the shape node into a
shadingGroup node (to actually render the shape), there is a node that
appears to be floating on its own (pSphere1 in Figure 1.4). This separate
node is a special kind of object, a transform node, which describes the posi-
tion, scale, and orientation of the polygonal sphere’s geometry in space. The
reason why this node is not connected is because it belongs to a special part
of the DG, called the Directed Acyclic Graph (DAG). For right now, it suf-
fices to say that the DAG essentially describes the hierarchical relationship of
objects that have transform nodes, including what nodes are their parents
and what transformations they inherit from their parents.
The Maya DG is discussed in greater detail in Chapter 11 in the context of
the Maya API, yet this principle is critical for understanding how Maya
works. We strongly recommend consulting a Maya user guide if you feel
like you need further information in the meantime.
Although Maya is, as we pointed out, an open product, the data in the core
are closed to users at all times. Autodesk engineers may make changes
to the core from one version to another, but users may only communicate
with the application core through a defined set of interfaces that Autodesk
provides.
One such interface that can communicate with the core is the Command
Engine. In the past, Maya commands have often been conflated with
14 CHAPTER 1 Maya Command Engine and User Interface

Maya user interface

MEL Python C++

Maya Command Engine Maya API

Maya application core

■ FIGURE 1.5 Python’s interaction with the Maya Command Engine.

MEL. Indeed, commands in Maya may be issued using MEL in either


scripts or GUI elements like buttons. However, with the inclusion of
Python scripting in Maya, there are now two different ways to issue Maya
commands, which more clearly illustrates the distinction.
Figure 1.5 highlights how Python interacts with the Maya Command
Engine. While Python can use built-in commands to retrieve data from
the core, it can also call custom, user-made commands that use API inter-
faces to manipulate and retrieve data in the core. These data can then be
returned to a scripting interface via the Command Engine. This abstraction
allows users to invoke basic commands (which have complex underlying
interfaces to the core) via a scripting language.
MEL has access to over 1,000 commands that ship with Maya and has been
used to create almost all of Maya’s GUI. While Python has access to nearly
all the same commands (and could certainly also be used to create Maya’s
GUI) there is a subset of commands unavailable to Python. The commands
unavailable to Python include those specifically related to MEL or that deal
with the operating system. Because Python has a large library of utilities
that have grown over the years as the language has matured outside of
Maya, this disparity is not a limitation.
Maya has documentation for all Python commands so it is easy to look up
which commands are available. In addition to absent commands mentioned
previously, there are some MEL scripts that appear in MEL command doc-
umentation as though they were commands. Because these are scripts
rather than commands, they do not appear in the Python command
Introduction to Python Commands 15

documentation and are not directly available to Python. Again, this absence
is also not a limitation, as it is possible to execute MEL scripts with Python
when needed. Likewise, MEL can call Python commands and scripts when
required.1
Another important feature of the Maya Command Engine is how easy it is to
create commands that work for MEL and Python. Maya was designed so that
any new command added will be automatically available to both MEL and
Python. New commands can be created with the Maya C++ API or the Python
API. Now that you have a firmer understanding of how Maya commands fit
into the program’s architecture, we can go back to using some commands.

INTRODUCTION TO PYTHON COMMANDS


Let’s return to Maya and open up the Script Editor. As discussed earlier in
this chapter, the top panel of the Script Editor is called the History Panel.
This panel can be very useful for those just learning how to script or even
for advanced users who want to figure out what commands are being
executed. By default, the History Panel will echo (print) most Maya
commands being executed. You can also make the History Panel show
all commands being executed, including commands called by the GUI
when you press a button or open a menu. To see all commands being exe-
cuted, select the History → Echo All Commands option from the Script
Editor’s menu. While this option can be helpful when learning, it is gener-
ally inadvisable to leave it enabled during normal work, as it can degrade
Maya’s performance. Right now, we will go through the process of creating
a cube and look at the results in the History Panel (Figure 1.6).
1. In the menu for the Script Editor window, select Edit → Clear History
to clear the History Panel’s contents.
2. In the main Maya window, navigate to the menu option Create →
Polygon Primitives → Cube.
3. Check the History Panel in the Script Editor and confirm that you see
something like the following results.
polyCube -w 1 -h 1 -d 1 -sx 1 -sy 1 -sz 1 -ax 0 1 0 -cuv 4 -ch 1;
// Result: pCube1 polyCube1 //

The first line shown is the polyCube MEL command, which is very similar
to the polySphere command we used earlier in this chapter. As you can see,

1
MEL can call Python code using the python command. Python can call MEL code
using the eval function in the maya.mel module. Note that using the python command
in MEL executes statements in the namespace of the __main__ module. For more infor-
mation on namespaces and modules, see Chapter 4.
16 CHAPTER 1 Maya Command Engine and User Interface

■ FIGURE 1.6 The results of creating a polygon cube.

a MEL command was called when you selected the Cube option in the
Polygon Primitives menu. That MEL command was displayed in the
Script Editor’s History Panel.
Because Maya’s entire interface is written with MEL, the History Panel
always echoes MEL commands when using the default Maya interface.
Custom user interfaces could call the Python version of a command, in
which case the History Panel would display the Python command.
This problem is not terribly troublesome for Python users though. It does
not take much effort to convert a MEL command into Python syntax, so
this feature can still help you learn which commands to use. The following
example shows what the polyCube command looks like with Python.
import maya.cmds;
maya.cmds.polyCube(
w=1, h=1, d=1, sx=1, sy=1, sz=1,
ax=(0, 1, 0), cuv=4, ch=1
);

If you execute these lines of Python code they will produce the same result as
the MEL version. However, we need to break down the Python version of the
command so we can understand what is happening. Consider the first line:
import maya.cmds;
Introduction to Python Commands 17

This line of code imports a Python module that allows you to use any Maya
command available to Python. There is only one module that holds all
Maya commands and you only need to import it once per Maya session.
Once it is in memory you don’t need to import it again (we only have
you reimport it for each example in case you’re picking the book back
up after a break from Maya). We will discuss modules in greater depth in
Chapter 4. The next line of code is the Python command.
maya.cmds.polyCube(
w=1, h=1, d=1, sx=1, sy=1, sz=1,
ax=(0, 1, 0), cuv=4, ch=1
);

As you can see, the name of the command, polyCube, is prefixed by the
name of the module, maya.cmds. The period between them represents that
this command belongs to the Maya commands module. We then supply the
command several flag arguments inside of parentheses. A key-value pair
separated by the equals sign, such as w=1, represents the name and value
for the flag argument, and each of these pairs is separated by a comma.

Each flag may be added using a shorthand abbreviation or long version of


the flag name. Although many Maya programmers tend to use the shorthand
flag names in their code, it can make the code more difficult to read later. In
the previous example, the command is using the shorthand flags so it is hard
to understand what they mean. Here is the same version of the command
with long flag names.
maya.cmds.polyCube(
width=1,
height=1,
depth=1,
subdivisionsX=1,
subdivisionsY=1,
subdivisionsZ=1,
axis=(0, 1, 0),
createUVs=4,
constructionHistory=1
);

The long names are easier to read and so it can be good practice to use them
when scripting. Code that is easier to read can be much easier to work with—
especially if you or a coworker has to make any changes several months later!
You may now be wondering how to find the long flag names in the future.

1. Type the following lines into the Script Editor and press Ctrl + Return
to execute them.
import maya.cmds;
print(maya.cmds.help('polyCube'));
18 CHAPTER 1 Maya Command Engine and User Interface

2. Look for the results in the History Panel, which should look like the
following lines.
Synopsis: polyCube [flags] [String...]
Flags:
–e –edit
–q –query
–ax –axis Length Length Length
–cch –caching on|off
–ch –constructionHistory on|off
–cuv –createUVs Int
–d –depth Length
–h –height Length
–n –name String
–nds –nodeState Int
–o –object on|off
–sd –subdivisionsDepth Int
–sh –subdivisionsHeight Int
–sw –subdivisionsWidth Int
–sx –subdivisionsX Int
–sy –subdivisionsY Int
–sz –subdivisionsZ Int
–tx –texture Int
–w –width Length

Command Type: Command

As you can see, the result first displays the command for which help was
requested—polyCube in this case. The following items in brackets, [flags]
and [String...], show MEL syntax for executing the command. In
MEL, the command is followed by any number of flag arguments and then
any number of command arguments. We’ll differentiate these two items
momentarily.
Next, the output shows the list of flags for the command, displaying the
short name on the left, followed by the long name in the middle column.
Each flag is prefixed by a minus symbol, which is required to indicate a
flag in MEL syntax, but which you can ignore in Python. To the very right
of each flag name is the data type for each argument, which tells us what
kind of value each flag requires.
We can see how flags work with the polyCube command. Consider the
following example.
import maya.cmds;
maya.cmds.polyCube();
Executing this command causes Maya to create a polygon cube with default
properties. The parentheses at the end of the command basically indicate that
Flag Arguments and Python Core Object Types 19

we want Maya to do something—execute a command in this case. Without


them, the command will not execute. We will discuss this topic further in
Chapter 3 when we introduce functions. For now, it suffices to say that
any command arguments we wish to specify must be typed inside of the
parentheses, as in the following alternative example.
import maya.cmds;
maya.cmds.polyCube(name='myCube', depth=12.5, height=5);

If you execute the previous lines, Maya will create a polygon cube named
“myCube” with a depth of 12.5 units and a height of 5 units. The first flag
we set, name, is a string, as indicated in the help results. A string is a sequence
of letters and numbers inside of quotation marks, and is used to represent a
word or words. Immediately afterward is a comma before the next flag, depth.
We specify that the depth should be the decimal number 12.5. Such values are
listed as type Length in the help results. Last, we provided the height flag and
supplied a value of 5. In this case, we used the long names of the flags, but we
could also have used the short ones to do the same thing.
import maya.cmds;
maya.cmds.polyCube(n='myCube', d=12.5, h=5);

Looking at the help results, you can see that the axis flag takes three decimal
numbers. To specify this kind of argument in Python, we use what is called
a tuple. A tuple is basically a sequence of objects inside of parentheses, sepa-
rated by commas. The following lines show an example of the same command
using a tuple to specify a different axis.
import maya.cmds;
maya.cmds.polyCube(
name='myCube',
depth=12.5,
height=5,
axis=(1,1,0)
);

FLAG ARGUMENTS AND PYTHON CORE


OBJECT TYPES
As you have seen, most Maya Python commands have flags, which allow
you to change the default settings of the command being executed. Each flag
argument must be passed a value. A flag’s value can be one of several
different built-in Python types. Table 1.1 lists Python’s core object types
that are used by Maya commands.
Note that Table 1.1 is not a complete list of Python core object types—
there are many others that you may use for other purposes in your scripts.
20 CHAPTER 1 Maya Command Engine and User Interface

Table 1.1 Python Core Object Types Used by Maya Commands


Type Examples

Numbers 1
−5
3.14159
9.67
Strings "Maya"
'ate'
"my dog's"
"""homework"""
Lists [1, "horse", 'town']
Tuples (1, "two", 'three')
Booleans True
False
1
0

However, the core object types in this list are the only ones that Maya
commands have been designed to use, so we may ignore the others for now.
Other Python data types are discussed in Chapter 2. Let’s focus for now on
the five types in this list.

Numbers
Maya commands expecting Python numbers will accept any real number.
Examples could include integer as well as decimal numbers, which corre-
spond to int/long and float/double types, respectively, in other languages.

Strings
The string type is any sequence of letters or numbers enclosed in single quota-
tion marks, double quotation marks, or a matching pair of triple quotation
marks of either type. For instance, “boat”, “house”, and “car” are equivalent
to ‘boat’, ‘house’, and ‘car’ as well as to “““boat”””, “““house”””, and
“““car”””. However, the string “3” is different from the number object 3.
Strings are typically used to name objects or parameters that are accessible
from the Maya user interface.

Lists
A list is a sequence of any number of Python objects contained within the
bracket characters [ and ]. A comma separates each object in the list. Any
Python object may be in a list, including another list!
Flag Arguments and Python Core Object Types 21

Tuples
The Python tuple is very similar to the list type except that it is not muta-
ble, which means it cannot be changed. We discuss mutability in greater
detail in Chapter 2. Tuples are contained inside of ordinary parentheses,
( and ).

Booleans
A Boolean value in Python can be the word True or False (which must
have the first letter capitalized), or the numbers 1 and 0 (which correspond
to the values True and False, respectively). These values are typically used
to represent states or toggle certain command modes or flags.

Flag = Object Type


To find out what type of object a command flag requires, you can use the
help command. As you saw earlier in this chapter it will give you a list of
the command flags and what type of value they require. The argument type
is not an option—you must pass a value of the required type or you will get
an error. Using the polyCube command as an example, let’s look at its
width flag and pass it correct and incorrect argument types.

1. Create a new scene by pressing Ctrl + N.


2. Execute the Maya help command for the polyCube command in the
Script Editor:
import maya.cmds;
print(maya.cmds.help('polyCube'));

3. Look for the width flag in the results displayed in the History Panel
and find its argument type on the right side:
–w –width Length

As you can see, the width flag requires a Length type argument, as shown
to the right of the flag name. This is technically not a Python type but we
can deduce that Length means a number, so we should pass this flag some
sort of number. If the number needed to be a whole number, the flag would
specify Int to the right of the flag instead of Length. We can therefore also
deduce that the flag may be passed a decimal number in this case. Let’s
first pass a correct argument.
4. Type the following command into the Script Editor and press Ctrl +
Return to execute it.
maya.cmds.polyCube(width=10);
22 CHAPTER 1 Maya Command Engine and User Interface

You should see the following result in the Script Editor’s History Panel.
# Result: [u'pCube1', u'polyCube1'] #

The result lets us know that the command succeeded and also shows that the
command returned a Python list containing the names of two new nodes that
have been created to make our cube object: “pCube1” (a transform node)
and “polyCube1” (a shape node). Now, let’s see what happens when we inten-
tionally supply the width flag with the wrong data type.
5. Type the following command into the Script Editor and press Ctrl +
Return to execute it.
maya.cmds.polyCube(width='ten');

This time the command returns an error.


# Error: TypeError: file <maya console> line 1: Invalid
arguments for flag 'width'. Expected distance, got str #

The error tells you that the argument for the width flag was incorrect and it
expected a distance value. Even though the help command showed the
width flag needed a Length type, Maya is now calling it a distance type.
This can be confusing at first but most of the time it is very clear what
the flag argument requires simply by looking at the flag in context. The
help command does not describe what each flag does, but you can get
more detailed descriptions using the Python Command Reference, which
we will examine shortly.

COMMAND MODES AND COMMAND ARGUMENTS


Maya commands often have more than one mode in which they can work.
Some commands may be available to use in create mode, edit mode, and/or
query mode, while certain flags may only be available in certain modes.

Create Mode
Most commands at least have a create mode. This mode allows users to
create new objects in the scene and specify any optional parameters. By
default, the polyCube command operates in create mode.
1. Create a new Maya scene.
2. Execute the following lines in the Script Editor to create a new cube.
import maya.cmds;
maya.cmds.polyCube();

Note that you do not have to do anything special to execute commands in


create mode. Leave the cube in your scene for the next steps.
Command Modes and Command Arguments 23

Edit Mode
Another mode that many commands support is edit mode. This mode
allows users to edit something the command has created.
3. Execute the following line in the Script Editor to change the cube’s
width.
maya.cmds.polyCube('pCube1', edit=True, width=10);

As you can see, you specified that the command should operate in edit
mode by setting the edit flag with a value of True. In edit mode, you were
able to change the width of the object named “pCube1” to a value of 10. It
is worth mentioning that some flags in MEL do not require an argument,
such as the edit flag (see help output previously). Such flags, when
invoked from Python, simply require that you set some value (True) to
indicate their presence.
Another important point worth noting is the syntax for operating in edit and
query modes. The first argument we pass to the command is called a
command argument, and specifies the name of the node on which to operate.
As we saw in the help output previously, MEL syntax expects command
arguments to follow flag arguments, while Python requires the opposite
order. The reason for Python’s syntax requirement will be discussed in
greater detail in Chapter 3. Leave the cube in the scene for the next step.

Query Mode
The last mode that many commands support is query mode. This mode
permits users to request information about something the command has
already created.
4. Execute the following line in the Script Editor to print the cube’s width.
maya.cmds.polyCube('pCube1', query=True, width=True);

The result in the History Panel should display something like the
following line.
# Result: 10.0 #

As with edit mode, query mode requires that you specify a command argu-
ment first and then set the query flag with a value of True. Another point
worth noting is that, although the width flag normally requires a decimal
number (when being invoked from create or edit mode), you simply pass
it a value of True in query mode. The basic idea is that in this case, the
Command Engine is only interested in whether or not the flag has been
set, and so it will not validate the value you are passing it.
24 CHAPTER 1 Maya Command Engine and User Interface

As you can see, these three modes allowed you to create an object, change
it, and finally pull up information about its current state. We also noted at
the outset of this section that some flags are only compatible with certain
command modes. While the help command will not give you this informa-
tion, the Command Reference documentation will.

PYTHON COMMAND REFERENCE


Another place you can get more help on a command is from the Maya help
documents. These documents detail every Python command available. The
Python Command Reference is shown in Figure 1.7. Let’s browse the Python
Command Reference to find more information on the polyCube command.
1. In the main Maya window select the menu item Help → Python Com-
mand Reference.
2. At the top of the page is a text field. Click in the search field and enter
the word polyCube.
3. The page will update to show you only the polyCube command. Select the
polyCube command from the list under the label “Substring: polyCube”.
Clicking this link will show you detailed information for the polyCube

■ FIGURE 1.7 Python Command Reference.


Python Command Reference 25

command. As you can see, the Command Reference documents break up


information for all commands into different sections, which we will
now look at in more detail.

Synopsis
The synopsis provides a short description of what the command does. In
this case the synopsis states:
polyCube is undoable, queryable, and editable.
The cube command creates a new polygonal cube.

Return Value
The return value section describes what the command will return when it is
executed. In this case the documentation states:
string[] Object name and node name.
This description shows us that it returns a list of string type objects, which
will be the name of the object (transform node) and the (polyCube) node
that were created.

Related
This section can help you with finding commands that are similar to the
command at which you are looking. For the polyCube command, this
section lists other commands for creating primitive polygon objects:
polyCone, polyCylinder, polyPlane, polySphere, polyTorus

Flags
For the polyCube command, the axis flag is listed first. It shows a short
description of what the flag does and then it lists the argument type to pass
to it. The documentation shows the following text:
[linear, linear, linear]
The command requires a Python list (or tuple) type and that list should hold
three real numbers. If int is not specified for an argument type, then the argu-
ment may be a decimal number, though integer numbers are still valid. In
this case, if we were to define the argument for the flag it could be something
like [1.00, 0, 0].
As we noted earlier, the documentation also displays icons to represent the
command mode(s) with which each flag is compatible.
26 CHAPTER 1 Maya Command Engine and User Interface

■ C (Create): The flag can appear in the create mode.


■ E (Edit): The flag can appear in the edit mode.
■ Q (Query): The flag can appear in the query mode.
■ M (Multiuse): The flag can be used multiple times.
In MEL, multiuse flags are invoked by appending them multiple times after a
command. In Python, however, you can only specify a flag once. As such,
Python requires that you pass a tuple or list argument for a multiuse flag,
where each element in the tuple or list represents a separate use of the flag.

Python Examples
This section can be very useful for those just learning how to script with
Python or those learning how to work with Maya using Python. Here
you can find working examples of the command in use. Some example
sections can have several different samples to help you understand how
the command works. The example for the polyCube command in the docu-
ments shows you how to create a polygon cube and also how to query an
existing cube’s width.

PYTHON VERSION
One final point that is worth discussing is how to locate which version of
Python your copy of Maya is using. Python has been integrated into Maya
since version 8.5, and each new version of Maya typically integrates the
newest stable version of Python as well. Since newer versions of Python
will have new features, you may want to investigate them. First, find out
what version of Python your version of Maya is using.
1. Open up the Script Editor and execute the following lines.
import sys;
print(sys.version);

You should see a result print in the Script Editor’s History Panel that looks
something like the following lines.
2.6.4 (r264:75706, Nov 3 2009, 11:26:40)
[GCC 4.0.1 (Apple Inc. build 5493)]

In this example, our copy of Maya is running Python version 2.6.4.

PYTHON ONLINE DOCUMENTATION


Once you know what version of Python you are running, you can look up
the Python documentation online. The Python web site is located at
Concluding Remarks 27

http://www.python.org/. If you navigate to the Documentation section,


you should see documentation for multiple versions of Python.
As you learn to program using Python you might also be interested in down-
loading Python for your operating system if it does not already include it.
You can find the latest versions of Python at the Python web site. If you plan
to write Python scripts that interact with Maya, it is advisable that you install
the same version that Maya is using. For the most part, many versions of
Python that you will see in Maya are almost identical. However, a newer
version of Python, 3.x, may break a few things that work in older versions.
If you choose to install Python for your operating system, you will be able
to use a Python interpreter, such as the Python IDLE, which acts just like
the Maya Script Editor but for your operating system. This can be useful
for creating tools outside of Maya that communicate with Maya using
Python. Moreover, you could write tools using Python that have nothing
to do with Maya, yet may be helpful for your project’s organization or
interaction with other software like MotionBuilder.

CONCLUDING REMARKS
In this chapter you have learned how Maya commands and Python work
within Maya’s architecture. We have introduced a few methods of entering
Maya commands with Python to modify Maya scenes. We have also
explained how to look up help and read the Python Command Reference doc-
umentation and how to find information about your version of Python. In the
chapters that immediately follow, we will further explain some of the underly-
ing mechanics and syntax of Python and then start creating more complicated
scripts to use in Maya.
Chapter
2
Python Data Basics

CHAPTER OUTLINE
Variables and Data 30
Variables in MEL 33
Keywords 33
Python’s Data Model 34
Mutability 35
Reference Counting 36
del() 37
The None Type 37
Using Variables with Maya Commands 37
Capturing Results 39
getAttr and setAttr 40
Compound Attributes 40
connectAttr and disconnectAttr 41
Working with Numbers 43
Number Types 43
Basic Operators 44
Working with Booleans 45
Boolean and Bitwise Operators 45
Working with Sequence Types 46
Operators 46
Concatenation 47
Indexing and Slicing 47
String Types 50
Escape Sequences and Multiline Strings 50
Raw Strings 51
Unicode Strings 51
Formatting Strings 52
More on Lists 53
del() 54
Nested Lists 54
Other Container Types 56
Sets 57
Operators 57
Dictionaries 58
Operators 59
Dictionaries in Practice 60
Concluding Remarks 62
Maya Python for Games and Film. DOI: 10.1016/B978-0-12-378578-7.00002-8
© 2012 Elsevier Inc. All rights reserved. 29
30 CHAPTER 2 Python Data Basics

BY THE END OF THIS CHAPTER, YOU WILL BE ABLE TO:


■ Define and manipulate data in variables.
■ Compare and contrast Python’s and MEL’s typing systems.
■ Recast variables as different data types.
■ Prevent naming conflicts with built-in keywords.
■ Explain how Python manages memory.
■ Compare and contrast mutable and immutable types.
■ Use variables in conjunction with commands to manipulate attributes.
■ Describe the different numeric types in Python.
■ Use mathematical operators with numeric types.
■ Use logical and bitwise operators with Boolean variables.
■ Use common operators with sequence types.
■ Manipulate nested lists.
■ Create Unicode and raw strings.
■ Format strings that contain variable values.
■ Compare and contrast sets and dictionaries with sequence types.

In Chapter 1, we covered executing commands in Maya using Python. To do


anything interesting, however, we need more tools to create programs. In this
chapter we will explore some of the basics for working with variables in
Python. Because much of this information is available in the online Python
documentation, we will not belabor it a great deal. However, because we
make use of certain techniques throughout the text, it is critical that you have
an overview here.
We begin by discussing variables in the context of the data types you learned
in Chapter 1, and show how you can use variables along with some basic
Maya commands. Thereafter, we discuss some more interesting properties
of the basic sequence types we discussed in Chapter 1. Finally, we discuss
two additional, useful container types.

VARIABLES AND DATA


The basic unit of data storage in any programming language is a variable.
A variable is a name that points to some specific data type. The mechanism
for creating a variable in Python is the assignment operator (=). Because
Python does not require (or allow) declaration without an assignment,
Variables and Data 31

creating a variable is as simple as separating a name and a value with the


assignment operator.
1. Execute the following line in a Python tab in the Script Editor, or from
the Command Line. This line simply creates a variable named contents,
and assigns a string value to it.
contents = 'toys';

2. Once you create this variable, you can substitute in this name anywhere
you would like this value to appear. Execute the following line of code.
You should see the string “toys in the box” print on the next line.
print(contents+' in the box');

3. You can change the value assigned to this variable at any time, which
will substitute in the new value anywhere the name appears. Execute
the following lines of code, which should print “shoes in the box” in
the History Panel.
contents = 'shoes';
print(contents+' in the box');

4. You can also assign completely different types of values to the variable.
Execute the following line of code.
contents = 6;
Python is what is called a strong, dynamically typed language. The line of
code in step 4 demonstrates dynamic typing. You are able to change the type
of any Python variable on-the-fly, simply by changing its assignment value.
However, because it is strongly typed, you cannot simply add this new value
to a string.
5. Try to execute the following statement.
print('there are '+contents+' things in the box');
The console should supply an error message like the following one.
# Error: TypeError: file <maya console> line 1: cannot
concatenate 'str' and 'int' objects #

Because Python is strongly typed, you cannot so easily intermix different


types of variables. However, you can now perform addition with another
number.
6. Execute the following line of code, which should print the number 16.
print(contents+10);

In Python, to intermix types, you must explicitly recast variables as the


expected type.
32 CHAPTER 2 Python Data Basics

7. Execute the following line in Python to cast the number stored in


contents to its string representation. You should see “there are 6
things in the box” in the History Panel.

print('there are '+str(contents)+' things in the box');

In this case, we called the str() function to recast contents as a string. We


discuss functions in greater detail in Chapter 3. Table 2.1 lists some other
built-in functions for recasting variables.
Python provides a built-in function, type(), which allows you to determine
the type of a variable at any point.
8. Execute the following line to confirm the type of the contents variable.
type(contents);

You should see the following line in the History Panel, which indicates
that the variable is currently pointing to an integer.

# Result: <type 'int'> #

As you can see, casting the variable to a string as you did in step 7 did not
change its inherent type, but only converted the value we retrieved from the
variable. As such, you would still be able to add and subtract to and from
this variable as a number. You could also reassign a string representation to
it by assigning the recast value.
9. Execute the following lines to convert the variable to a string.
contents = str(contents);
print(type(contents));

You should see the following output in the History Panel.

<type 'str'>

Table 2.1 Python Functions for Recasting Variable Types


Function Casts To Notes

float() Decimal number If argument is string, raises ValueError if not properly formatted
int() Integer number If argument is string, raises ValueError if not properly formatted
If argument is decimal number, result is truncated toward 0
Allows optional argument to specify non-base 10
str() String
unicode() Unicode string Allows optional argument to specify encoding
Variables and Data 33

Variables in MEL
Variables in Python are incredibly flexible. Compare the previous example
with a comparable MEL snippet.
1. Enter the following lines in a MEL tab in the Script Editor. You should
again see the output “toys in the box” in the History Panel.
$contents = "toys";
print($contents+" in the box");

While MEL allows—but does not require—that you explicitly provide the
variable’s type, the variable $contents is statically typed at this point. It is
a string, and so cannot now become a number. Those unfamiliar with MEL
should also note that it requires variable names to be prefixed with a dollar
sign ($).
2. Execute the following lines in MEL.
$contents = 6;
print("there are "+$contents+" things in the box");

Because you get the output you expect (“there are 6 things in the box”), you
may think that MEL has implicitly handled a conversion in the print call. How-
ever, the number 6 stored in $contents is not in fact a number, but is a string.
You can confirm this fact by trying to perform addition with another number.
3. Execute the following line in MEL.
print($contents+10);

Whereas the Python example printed the number 16 in this case, MEL has
printed 610! In MEL, because the type of the variable cannot change, MEL
implicitly assumed that the number 10 following the addition operator (+)
was to be converted to a string, and the two were to be concatenated. While sea-
soned MEL developers should be well aware of this phenomenon, readers who
are new to Maya will benefit from understanding this difference between MEL
and Python, as you may occasionally need or want to call statements in MEL.
On the other hand, all readers who are as yet unfamiliar with Python would
do well to remember that variable types could change on-the-fly. This
feature offers you a great deal of flexibility, but can also cause problems
if you’re frequently reusing vague, unimaginative variable names.

Keywords
Apart from issues that may arise from vague variable names, Python users
have some further restrictions on names available for use. Like any other
language, Python has a set of built-in keywords that have special meanings.
34 CHAPTER 2 Python Data Basics

You saw one of these keywords—import—in Chapter 1. To see a list of


reserved keywords, you can execute the following lines in a Python tab
in the Script Editor.

import keyword;
for kw in keyword.kwlist: print(kw);

The list of reserved keywords printed out are used for various purposes,
including defining new types of objects and controlling program flow.
We will be covering a number of these keywords throughout the text, but
it is always a good idea to refer to the Python documentation if you would
like more information. The important point right now is that these words all
have special meanings, and you cannot give any of these names to your
variables.

Python’s Data Model


It is now worth highlighting a few points about Python’s data model, as it
has some bearing on other topics in this chapter (as well as many topics we
discuss later in this book). Although we must be brief, we recommend
consulting Section 3.1 of Python Language Reference online if you are
interested in more information.
To maximize efficiency, statically typed languages allocate a specific
amount of memory for different types of variables. Because this amount
of memory is specified in advance, you cannot simply assign a new
type to a name at some later point. On the other hand, as you have
seen in this chapter, Python lets you change the type of a variable at
any point. However, the underlying mechanisms are actually somewhat
subtler.
In Python, variables are just names that point to data. All data are objects,
and each object has an identity, a type, and a value.
■ An object’s identity describes its address in memory.
■ An object’s type (which is itself an object) describes the data type it
references.
■ An object’s value describes the actual contents of its data.
While we will discuss objects in greater detail in Chapter 5, programmers
coming from other languages may find this principle novel.
When you create a new variable and assign it a value, your variable is
simply a name pointing to an object with these three properties: an identity,
Variables and Data 35

a type, and a value.1 Consider a situation where you cast an integer to a


string, such as the following lines.
var = 5;
var = str(var);

In this case, you are not actually altering the data’s underlying type, but are
pointing to some different piece of data altogether. You can confirm this
fact by using the built-in id() function, which provides the address to the
data. For instance, printing the identity at different points in the following
short sample will show you different addresses when the variable is an inte-
ger and when it is a string.
var = 5;
print('int id',id(var));
var = str(var);
print('str id',id(var));

Mutability
In Python, objects can be either mutable or immutable. Briefly construed,
mutable objects can have their values changed (mutated), while immutable
objects cannot.2 We briefly mentioned this concept in Chapter 1 when com-
paring lists and tuples.
In fact, tuples, strings, and numbers are all immutable. As a consequence,
when you assign a new integer value to a variable, instead of changing
the underlying value of the object to which the variable is pointing, the
variable instead points to another piece of data. You can see the effects
of this concept in the following short code example, which will print the
identity for the variable after different integer assignments.
var = 5;
print('5 id',id(var));
var = 6;
print('6 id',id(var));

1
C++ programmers should note that although Python variables are references to data, they
cannot simply be used like pointers. To shoehorn Python into the language of C++, it
always passes parameters by value, but the value of a variable in Python is a reference.
The consequence is that reassigning a variable inside of a function has no effect on its
value outside the function. Chapter 9 discusses these consequences of Python’s data
model in Maya’s API.
2
Immutable containers that reference mutable objects can have their values changed if the
value of one of the mutable objects in the container changes. These containers are still
considered immutable, however, because identities to which they refer do not change.
See the “Nested Lists” section in this chapter for more information.
36 CHAPTER 2 Python Data Basics

Variables Data objects


type: int
value: 10

■ FIGURE 2.1 Two variables may point to the same object.

We examine the effects of mutability on sequence types later in this


chapter.

Reference Counting
As part of its data model, Python uses a system known as reference count-
ing to manage its memory. The basic idea is that rather than requiring
developers to manually allocate and deallocate memory, data are garbage
collected when there are no more names referencing them.
An interesting side effect of this paradigm is that two immutable variables
with the same assignment (e.g., data with the same type and value) may in
fact be pointing to the same data in memory (Figure 2.1). You can see this
principle in action by assigning the same numeric value to two different
variables and printing their identities.
v1 = 10;
v2 = 10;
print('v1 id', id(v1));
print('v2 id', id(v2));

In this case, both v1 and v2 are pointing to the same piece of data. If these
two variables are assigned different data (e.g., some other number, a string,
etc.), then the reference count for their previous data (the integer 10) drops
to zero. When the reference count for objects drops to zero, Python nor-
mally automatically garbage collects the data to free up memory as needed.
Although this concept has only a few consequences for our current discus-
sion, it becomes more important in later chapters as we discuss modules,
classes, and using the API.
It is important to note that while variables pointing to data with an immu-
table type may show this behavior, two separate assignments to mutable
objects with the same type and value are always guaranteed to be different.
For example, even though the following lists contain the same items, they
will be guaranteed to have unique identities.
Using Variables with Maya Commands 37

list1 = [1, 2, 3];


list2 = [1, 2, 3];
print('list1 id', id(list1));
print('list2 id', id(list2));

The assignment of one variable to another variable pointing to a mutable


object, however, results in both pointing to the same data.
list1 = [1, 2, 3];
list2 = list1;
print('list1 id', id(list1));
print('list2 id', id(list2));

This concept has important consequences that we will cover later.

del()
Python has a built-in function, del(), which allows you to delete variables.
Note that this process is not the same as deleting the data referenced by the
variable: Python’s garbage collector will still manage those data. Using this
function with a variable name simply clears the name (and thus eliminates a
reference to its data). The following example illustrates that, even though
v1 and v2 will reference the same data, deleting v1 has no effect on v2.
Trying to access v1 after this point would result in a NameError.
v1 = 5;
v2 = 5;
del(v1);
print(v2);

The None Type


Because we use it throughout the text in some cases, it is worth noting that,
because of how Python’s variables work, Python also implements a None type.
var = None;

One use of this type is to initialize a name without wastefully allocating


memory if it is unnecessary. For instance, many of our API examples in
this text use the None type to declare names for class objects whose values
are initialized elsewhere. We will talk more about class objects starting in
Chapter 5.

USING VARIABLES WITH MAYA COMMANDS


As we noted in Chapter 1, a Maya scene is fundamentally composed of
nodes and connections. Each node has a number of different attributes, such
as the radius of a polySphere, the height of a polyCube, or the maximum
38 CHAPTER 2 Python Data Basics

number of influences in a skinCluster. Although we will talk about


attributes in much greater detail when we introduce the API in later chapters,
it suffices for now to say that they describe the actual data housed in a node.
You have already seen some multimodal, built-in commands designed to
work with different node types. For example, the polySphere command
not only creates nodes for a polygon sphere, but also allows you to query
and edit polySphere nodes. You can use these commands along with
variables very easily. Let’s work through a quick example.
1. Create a new Maya scene and execute the following lines in the Script
Editor.
import maya.cmds;
sphereNodes = maya.cmds.polySphere();

Recall that the results of the polySphere command return a list of object
names (a transform node and a shape node). You can store this result in
a variable when you create a cube. The sphereNodes list now contains
the names of the two objects that were created. If you were to print this list,
you would see something like the following line.
[u'pSphere1', u'polySphere1']

Note that this list does not contain the Maya nodes themselves, but simply
contains their names. For example, using the del() function on this list
would not actually delete Maya nodes, but would simply delete a list with
two strings in it.
2. We will discuss this syntax later in this chapter, but you can use square
bracket characters to access items in this list. For example, you can store
the name of the polySphere node (“polySphere1”) in another variable.
sphereShape = sphereNodes[1];

3. Now that you have stored the name of the shape in a variable, you can
use the variable in conjunction with the polySphere command to query
and edit values. For example, the following lines will store the sphere’s
radius in a variable, and then multiply the sphere’s radius by 2. Remem-
ber that in each flag argument, the first name is the flag, and the second
name is the value for the flag.
rad = maya.cmds.polySphere(
sphereShape, q=True, radius=True
);
maya.cmds.polySphere(sphereShape, e=True, radius=rad*2);

4. You could now reread the radius attribute from the sphere and store it
in a variable to create a cube the same size as your sphere.
Using Variables with Maya Commands 39

rad = maya.cmds.polySphere(
sphereShape, q=True, radius=True
);
maya.cmds.polyCube(
width=rad*2,
height=rad*2,
depth=rad*2
);

Hopefully you see just how easy it is to use variables in conjunction with
Maya commands.

Capturing Results
In practice, it is critical that you always capture the results of your commands
in variables rather than making assumptions about the current state of your
nodes’ attributes. For example, Maya will sometimes perform validation
on your data, such as automatically renaming nodes to avoid conflicts.
Some Maya users may insist that this behavior makes certain tools impos-
sible without advanced, object-oriented programming techniques. In reality,
you simply need to take care that you use variables to store your com-
mands’ results, and do not simply insert literal values—especially object
names—into your code. The following example illustrates this point.
1. Create a new Maya scene and execute the following lines in the Script
Editor. This code will create a sphere named “head.”
import maya.cmds;
maya.cmds.polySphere(name='head');

2. Now execute the following line to try to make a cube with the same name.
maya.cmds.polyCube(name='head');

If you actually look at your cube in the scene, you can see that Maya has
automatically renamed it to “head1” so it will not conflict with the name
you gave the sphere. However, if you were writing a standalone tool that
creates objects with specific names and then tries to use those specific
names, your artists may run into problems if they already have objects in
the scene with conflicting names.
3. Try to execute the following line, and you will get an error.
maya.cmds.polyCube('head', q=True, height=True);

Always remember that Maya commands work with nodes and attributes on
the basis of their names, which are simply strings. When using ordinary
Maya commands, you should always capture the results of your commands
40 CHAPTER 2 Python Data Basics

since there is no default mechanism for maintaining a reference to a specific


node. In Chapter 5 we will see how the pymel module provides an alterna-
tive solution to this problem.

getAttr and setAttr


While there are many commands that pair with common node types, not all
nodes have such commands (and sometimes not all attributes have flags).
It may also become tedious to memorize and use commands with modes,
flags, and so on. Fortunately, Maya provides two universal commands for
getting and setting attribute values that will work with any nodes: getAttr
and setAttr. We’ll demonstrate a quick example.
1. Open a new Maya scene and execute the following lines of code. These
lines will create a new locator and store the name of its transform node
in a variable called loc.
import maya.cmds;
loc = maya.cmds.spaceLocator()[0];

2. Execute the following lines to store the locator’s x-scale in a variable


and print the result, which will be 1 by default.
sx = maya.cmds.getAttr(loc+'.scaleX');
print(sx);

The getAttr command allows you to get the value of any attribute on any
node by simply passing in a string with the node’s name, a period, and the
attribute name. We’ll talk more about working with strings shortly, but the
complete string that we passed to the getAttr command was actually “loca-
tor1.scaleX” in this case.
3. Execute the following lines to double the sx value and assign the new
value to the node’s attribute.
sx *= 2;
maya.cmds.setAttr(loc+'.scaleX', sx);

The setAttr command works just like the getAttr command, and allows
you to set any attribute value on any node by passing a string with the
node’s name, a period, and the attribute name.

Compound Attributes
Many attributes will simply be a string, a Boolean, or a number value.
However, some attributes are called compound attributes, and may contain
several values. It is important to note that these attribute types work differ-
ently with the getAttr and setAttr commands compared to other built-in
commands.
Using Variables with Maya Commands 41

The reason for this difference is that the getAttr and setAttr commands do
not know what data type the particular attribute expects or contains until they
look it up by name. Other commands only work with specific attributes on
specific nodes, and so can work in a more straightforward way, as you will
see in the remainder of this example.
4. In the scene you created in the previous steps, execute the following
line to print the locator’s translation using the xform command.
print(maya.cmds.xform(loc, q=True, translation=True));

As you would expect the result is simply a list: [0.0, 0.0, 0.0].
5. Likewise, when using the xform command, you can set a new translation
value using a list, as in the following line.
maya.cmds.xform(loc, translation=[0,1,0]);

The xform command can work in this way because it is designed to work
exclusively with transform nodes, and the command internally knows
about the data type for the appropriate attribute. On the other hand,
getAttr and setAttr are not so straightforward.

6. Execute the following line to print the locator’s translation using the
getAttr command.

print(maya.cmds.getAttr(loc+'.translate'));

As you can see from the output, the command returns a list that contains
a tuple: [(0.0, 1.0, 0.0)].
7. Using setAttr for a compound attribute also uses a different paradigm.
Execute the following line to set a new translation value for the locator.
maya.cmds.setAttr(loc+'.translate', 1, 2, 3);

As you can see, setting a compound attribute like translation using setAttr
requires that you specify each value in order (x, y, z in this case).

connectAttr and disconnectAttr


The mechanism for transforming data in the Maya scene is to connect
attributes: an output of one node connects to some input on another node.
For instance, you saw in Chapter 1 how the output attribute of a polySphere
node is connected to the inMesh attribute of a shape node when you execute
the polySphere command. While Chapter 1 showed how you can delete
the construction history of an object to consolidate its node network, the
connectAttr and disconnectAttr commands allow you to reroute con-
nections in altogether new ways.
The basic requirement for attributes to be connected is that they be of the same
type. For example, you cannot connect a string attribute to a decimal number
42 CHAPTER 2 Python Data Basics

attribute. However, Maya does perform some built-in conversions for you
automatically, such as converting angle values into decimal numbers. The finer
distinctions between these types of values will be clearer when we discuss the
API later in this book. In the following short example, you will create a basic
connection to control one object’s translation with another object’s rotation.
1. Open a new Maya scene and execute the following lines to create a
sphere and a cube and store the names of their transform nodes.
import maya.cmds;
sphere = maya.cmds.polySphere()[0];
cube = maya.cmds.polyCube()[0];

2. Execute the following lines to connect the cube’s y-rotation to the


sphere’s y-translation.
maya.cmds.connectAttr(cube+'.ry', sphere+'.ty');
maya.cmds.select(cube);

Use the Rotate tool (E) to rotate the cube around its y-axis and observe the
behavior. The result is very dramatic! Because you are mapping a rotation
in degrees to a linear translation, small rotations of the cube result in large
translations in the sphere.
It is also worth mentioning that the connection is only one way. You cannot
translate the sphere to rotate the cube. In Maya, without some very compli-
cated hacks, connections can only flow in one direction. Note, too, that an
output attribute can be connected to as many inputs as you like, but an
input attribute can only have a single incoming connection.
3. Execute the following line to disconnect the two attributes you just
connected.
maya.cmds.disconnectAttr(cube+'.ry', sphere+'.ty');

The disconnectAttr command works very similarly to the connectAttr


command. It simply expects two strings that name the nodes and their attributes.
4. Execute the following lines to create a multiplyDivide node between
the two attributes to scale the effect.
mult = maya.cmds.createNode('multiplyDivide');
maya.cmds.connectAttr(cube+'.ry', mult+'.input1X');
maya.cmds.setAttr(mult+'.input2X', 1.0/90.0);
maya.cmds.connectAttr(mult+'.outputX', sphere+'.ty');
maya.cmds.select(cube);

Now if you rotate the cube, the sphere translates 1 unit for every 90 degrees
of rotation.
Working with Numbers 43

WORKING WITH NUMBERS


In Chapter 1, we introduced some basic object types with which Maya
commands have been designed to work. Although we lumped numbers
together generally, they are actually decomposable into more specific types.
Because you may want to take advantage of these specific types’ features,
and because you may encounter them when testing the types of your
variables, it is worth briefly discussing them.

Number Types
Although you can often intermix different types of numbers in Python,
there are four types of numbers: integers, long integers, floating-point num-
bers, and complex numbers. We briefly cover them here, but you can read
more about these different types in Section 5.4 of Python Standard Library.
As you saw in the beginning of this chapter, an integer is simply a whole
(nonfractional) number. Integers can be positive or negative. The type of
an integer in Python is given as int, as the following code illustrates.
var = -5;
print(type(var));

A long integer differs from an integer only in that it occupies more space in
memory. In many cases, ordinary integers suffice and are more efficient, but
long integers may be useful for computation that deals with large numbers.
In a language like C or C++, a long integer occupies twice as many bits in
memory as an ordinary integer. In Python, a long integer can occupy as
much memory as you require. To create a long integer, you can simply
assign a really long value to your variable and it will become a long integer
automatically, or you can suffix the value with the character l or L. The type
in Python is given as long.
var = -5L;
print(type(var));

Floating-point numbers are any numbers, positive or negative, with digits


after a decimal point. You can explicitly indicate that a whole number value
is to be a floating-point number by adding a decimal point after it. The type
of a floating-point number is float.
var = -5.0;
print(type(var));

Finally, Python allows you to use complex numbers, which consist of both a
real and an imaginary component. It is highly unlikely that you will need to
work with complex numbers regularly. You can create a complex number by
44 CHAPTER 2 Python Data Basics

suffixing the imaginary part with the character j or J. The type is given as
complex.
var = -5+2j;
print(type(var));

You can also access the individual real and imaginary parts of complex
numbers using the real and imag attributes.
print(var.real, var.imag);

Basic Operators
Once you start creating variables, you will want to do things with them.
Operators are special symbols you can include in your code to perform spe-
cial functions. (Note that we also include some related built-in functions and
object methods in our tables.) Section 5 of Python Standard Library includes
information on various operators, and Section 3.4 of Python Language
Reference contains information on overloading operators, which allows
you to assign special functionality to these symbols. Here, we briefly review
some of the basic operators for working with numeric values.
Thus far, you’ve seen some of the basic math operators, such as + for addition
and – for subtraction or negation. Section 5.4 in Python Standard Library con-
tains a table of Python’s built-in operators for working with numeric types.
In Table 2.2 we have recreated the parts of this table containing the most
common operators.
Note that many of these operators also allow in-place operations when used
in conjunction with the assignment operator (=). For example, the following

Table 2.2 Important Numeric Operators


Operation Result Notes

x+y Sum of x and y


x−y Difference of x and y
x*y Product of x and y
x/y Quotient of x and y If x and y are integers, result is
rounded down
x // y Floored quotient of x and y Use with floating-point numbers
to return a decimal result identical
to x/y if x and y were integers
x%y Remainder of x / y
divmod(x, y) Tuple that is (x // y, x % y)
pow(x, y) x to the y power
x ** y x to the y power
Working with Booleans 45

lines create a variable, v1, with a value of 2, and then subtracts 4 from the
same variable, resulting in −2.
v1 = 2;
v1 -= 4;
print(v1);

Note that Python does not support incremental operators such as ++ and −−.
For those readers who are new to programming, it is important to point out
how division works with integer numbers. Remember that integers are
whole numbers. Consequently, the result is always rounded down. The fol-
lowing floating-point division results in 0.5.
1.0/2.0;

The following integer division results in 0.


1/2;

On the other hand, the following integer division results in −1.


-1/2;

You can also mix an integer and a floating-point number, in which case
both are treated as floats. The following division results in 0.5.
1.0/2;

It is also worth mentioning, for those unacquainted with the finer points of
computer arithmetic, that floating-point operations often result in minor
precision errors as a consequence of how they are represented internally.
It is not uncommon to see an infinitesimally small number where you might
actually expect zero. These numbers are given in scientific notation, such as
the following example.
-1.20552649145e-10

WORKING WITH BOOLEANS


Another basic type that is used with Maya commands is the Boolean type
(called bool in Python). Recall that in practice, Boolean values True and False
are interchangeable with 1 and 0, respectively. This principle becomes more
important when using conditional statements, as you will see in Chapter 3.

Boolean and Bitwise Operators


Some operators are especially important when you are working with
Boolean values. You will use these operators widely in Chapter 3 as we
discuss using conditional statements to control program flow. In Table 2.3
46 CHAPTER 2 Python Data Basics

Table 2.3 Important Boolean and Bitwise Operators


Operation Result Notes

x or y True if either x or y is True Only evaluates y if x is False


x and y True only if both x and y are True Only evaluates y if x is True
not x False if x is True; True if x is False
x|y Bitwise or of x and y
x&y Bitwise and of x and y
x^y Bitwise exclusive-or of x and y

we have consolidated the most common operators from tables in Sections


5.2 and 5.4.1 of Python Standard Library.
When working with Boolean variables, the bitwise operators for and (&)
and or (|) function just like their Boolean operator equivalents. The exclu-
sive-or operator (^), however, will only return True if either x or y is True,
but will return False if they are both True or both False.
There are more bitwise operators that we have not shown here only because
we do not use them throughout this text. Programmers who are comfortable
with binary number systems should be aware that bitwise operators also
work with int and long types.3

WORKING WITH SEQUENCE TYPES


In Chapter 1, three of the variable types introduced can be called sequence
types. Sequence types include strings, lists, and tuples. These types basically
contain a group of data in a linear sequence. While each of these types is
obviously unique, they also share some properties, which we briefly discuss
in this section.

Operators
As with numbers and Booleans, sequence types have a set of operators that
allow you to work with them conveniently. Section 5.6 of Python Standard
Library has a table of operations usable with sequence types. We have
selected the most common of these operations to display in Table 2.4.
Because they are perhaps not as immediately obvious as math operators,
some merit a bit of discussion.

3
It is also worth noting that the bitwise inversion operator (~) is not equivalent to the Boolean
not operator when working with Boolean variables. Booleans are not simply 1-bit values, but
are built on top of integers. Consequently, ~False is −1 and ~True is −2.
Working with Sequence Types 47

Table 2.4 Important Sequence Operators


Operation Result Notes

x in s True if x is in s Searches for item in lists/tuples


Searches for character sequence in strings
x not in s True if x is not in s (see in operator)
s+t Concatenation of s and t
s[i] ith item in s First index is 0
Negative value for i is relative to len(s)
s[i:j] Slice of s from i to j (see index operator)
i is starting index, j is end of slice
If i is omitted, i is 0
If j is omitted or greater than len(s), j is len(s)
s[i:j:k] Slice of s from i to j with step k (see index operator)
len(s) Length of s
min(s) Smallest item in s Corresponds to ASCII code for strings
max(s) Largest item in s Corresponds to ASCII code for strings
s.index(x) Index of first x in s
s.count(x) Total occurrences of x in s

Concatenation
The first operator worthy of a little discussion is the concatenation operator
(+). As you saw in the examples at the outset of this chapter, MEL concate-
nated two strings that we expected to be numbers. Python allows sequence
concatenation in the same way. Concatenation creates a new sequence com-
posed of all of the elements of the first sequence, followed by all of the ele-
ments in the second sequence. You can concatenate any sequence types, but
only with other sequences of the same type. You cannot concatenate a list with
a tuple, for instance.
The following line produces the string “Words make sentences.”
'Words' + ' ' + 'make' + ' ' + 'sentences.';

Likewise, the following line produces the list [1, 2, 3, 4, 5, 6].


[1,2,3] + [4,5,6];

Indexing and Slicing


An important operator for sequence types is the index operator, represented
by the square bracket characters ([ and ]). At its most basic, it corresponds
to the index operator found in most languages. Note also that sequence
types all use zero-based indices (Figure 2.2). For example, the following
line results in just the “c” character, as it occupies index 2 in the string.
48 CHAPTER 2 Python Data Basics

string value: a b c d e
indices: 0 1 2 3 4

■ FIGURE 2.2 Sequences use zero-based indices.

tuple elements: 1 2 3 4 5
negative indices: -5 -4 -3 -2 -1

■ FIGURE 2.3 Negative indices are relative to sequence length.

string value: H o l y c a t s , P y t h o n i s a w e s o m e
indices: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27

■ FIGURE 2.4 Slicing a string from index 5 to 9.

'abcde'[2];

Because lists are mutable, you can also use this operator to set individual
values for a list. The following line would result in the list [0, 2, 3].
[1,2,3][0] = 0;

However, because they are immutable, you cannot use the index operator to
change individual items in a tuple or characters in a string. The following
two lines would fail.
'abcde'[2] = 'C';
(1,2,3)[0] = 0;

You can use a series of index operators to access elements from sequences
embedded in sequences. For instance, the following example will extract
just the “x” character.
('another', 'example')[1][1];

Another important feature of Python’s index operator is that it allows you to


supply a negative index. Supplying a negative index gives the result relative
to the length of the sequence (which is one index beyond the final element;
Figure 2.3). For example, the following line would print the number 4.
print((1,2,3,4,5)[-2]);

Python’s index operator also offers powerful, concise syntax for generating
slices from sequences. You can think of a slice as a chunk extracted from a
sequence. The most basic syntax for a slice includes two numbers inside
the square brackets, separated by a colon. The first number represents the
start index, and the second number represents the end index of the slice
(Figure 2.4). Consider the following example.
Another Random Scribd Document
with Unrelated Content
that the Gaunts were not rich, that even the illness itself would tax all their
resources, and that the money, the debts to pay, would ruin them, and break
their hearts. “I don’t say he has not been wrong, aunt Caroline—oh, I
suppose he has been very wrong!—but there he is lying: and oh, how pitiful
it is to hear him! and the old General, who was so proud of him; and Mrs
Gaunt, dear Mrs Gaunt, who always was so good to me!”
“Frances, my child, I am not a hard-hearted woman, though you seem to
think so,—I can understand all that. I am very, very sorry for the poor
mother; and for the young man even, who has been led astray: but I don’t
see what you can do.”
“What!” cried Frances, her eyes flashing through her tears—“for their
son, who is the same as a brother—for them, whom I have always known,
who have helped to bring me up? Oh, you don’t know how people live
where there are only a few of them,—where there is no society, if you say
that. If he had been ill there, at home, we should all have nursed him, every
one. We should have thought of nothing else. We would have cooked for
him, or gone errands, or done anything. Perhaps those ladies are better who
go to the hospitals. But to tell me that you don’t know what I could do!
Oh,” cried the girl, springing to her feet, throwing up her hands, “if I had
the money, if I had only the money, I know what I would do!”
Mrs Clarendon was a woman who did not spend money, who had
everything she wanted, who thought little of what wealth could procure; but
she was a Quixote in her heart, as so many women are where great things
are in question, though not in small. “Money?” she said, with a faint quiver
of alarm in her voice. “My dear, if it was anything that was feasible,
anything that was right, and you wanted it very much—the money might be
found,” she said. The position, however, was too strange to be mastered in a
moment, and difficulties rose as she spoke. “A young man. People might
suppose—— And then Sir Thomas—what would Sir Thomas think?”
“That is why I came to you; for he will not give me my own money—if I
have any money. Aunt Caroline, if you will give it me now, I will pay you
back as soon as I am of age. Oh, I don’t want to take it from you—I want
—— If everything could be paid before he is better, before he knows—if
we could hide it, so that the General and his mother should never find out.
That would be worst of all, if they were to find out—it would break their
hearts. Oh, aunt Caroline, she thinks there is no one like him. She loves him
so; more than—more than any one here loves anybody: and to find out all
that would break her heart.”
Mrs Clarendon rose at this moment, and stood up with her face turned
towards the door. “I can’t tell what is the matter with me,” she said; “I can
scarcely hear what you are saying. I wonder if I am going to be ill, or what
it is. I thought just then I heard a voice. Surely there is some one at the door.
I am sure I heard a voice—— Oh, a voice you ought to know, if it was true.
Frances—I will think of all that after—just now—— He must be dead, or
else he is here!”
Frances, who thought of no possibility of death save to one, caught her
aunt’s arm with a cry. The great house was very still—soft carpets
everywhere—the distant sound of a closing door scarcely penetrating from
below. Yet there was something, that faint human stir which is more subtle
than sound. They stood and waited, the elder woman penetrated by sudden
excitement and alarm, she could not tell why; the girl indifferent, yet ready
for any wonder in the susceptibility of her anxious state. As they stood, not
knowing what they expected, the door opened slowly, and there suddenly
stood in the opening, like two people in a dream—Constance, smiling,
drawing after her a taller figure. Frances, with a start of amazement, threw
from her her aunt’s arm, which she held, and calling “Father!” flung herself
into Waring’s arms.
CHAPTER XLV.
“I found him in the mood; so I thought it best to strike while the iron was
hot,” Constance said. She had settled down languidly in a favourite corner,
as if she had never been away. She had looked for the footstool where she
knew it was to be found, and arranged the cushion as she liked it. Frances
had never made herself so much at home as Constance did at once. She
looked on with calm amusement while her aunt poured out her delight, her
wonder, her satisfaction, in Waring’s ears. She did not budge herself from
her comfortable place; but she said to Frances in an undertone: “Don’t let
her go on too long. She will bore him, you know; and then he will repent.
And I don’t want him to repent.”
As for Frances, she saw the ground cut away entirely from under her
feet, and stood sick and giddy after the first pleasure of seeing her father
was over, feeling her hopes all tumble about her. Mrs Clarendon, who had
been so near yielding, so much disposed to give her the help she wanted,
had forgotten her petition and her altogether in the unexpected delight of
seeing her brother. And here was Constance, the sight of whom perhaps
might call the sick man out of his fever, who might restore life and
everything, even happiness to him, if she would. But would she? Frances
asked herself. Most likely, she would do nothing, and there would be no
longer any room left for Frances, who was ready to do all. She would have
been more than mortal if she had not looked with a certain bitterness at this
new and wonderful aspect of affairs.
“I saw mamma’s brougham at the door,” Constance said; “you must take
me home. Of course, this was the place for papa to come; but I must go
home. It would never do to let mamma think me devoid of feeling. How is
she, and Markham—and everybody? I have scarcely had any news for three
months. We met Algy Muncastle on the boat, and he told us some things—a
great deal about Nelly Winterbourn—the widow, as they call her—and
about you.”
“There could be nothing to say of me.”
“Oh, but there was, though. What a sly little thing you are, never to say a
word! Sir Thomas.—Ah, you see I know. And I congratulate you with all
my heart, Fan. He is rolling in money, and such a good kind old man. Why,
he was a lover of mamma’s dans les temps. It is delightful to think of you
consoling him. And you will be as rich as a little princess, with mamma to
see that all the settlements are right.”
“I don’t know what you mean,” Frances said abruptly. She was so
preoccupied and so impatient, that she would not even allow herself to
inquire. She went to where her father sat talking to his sister, and stood
behind his chair, putting her hand upon his arm. He did not perhaps care for
her very much. He had aunt Caroline to think of, from whom he had been
separated so long; and Constance, no doubt, had made him her own too, as
she had made everybody else her own; but still he was all that Frances had,
the nearest, the one that belonged to her most. To touch him like this gave
her a little consolation. And he turned round and smiled at her, and put his
hand upon hers. That was a little comfort too; but it did not last long. It was
time she should return to her mother; and Constance was anxious to go,
notwithstanding her fear that her father might be bored. “I must go and see
my mother, you know, papa. It would be very disrespectful not to go. And
you won’t want me, now you have got aunt Caroline. Frances is going to
drive me home.” She said this as if it was her sister’s desire to go; but as a
matter of fact, she had taken the command at once. Frances, reluctant
beyond measure to return to the house, in which she felt she would no
longer be wanted—which was a perverse imagination, born of her
unhappiness—wretched to lose the prospect of help, which she had been
beginning to let herself believe in, was yet too shy and too miserable to
make any resistance. She remembered her mother’s note for Mr Clarendon
before she went away, and she made one last appeal to her aunt. “You will
not forget what we were talking about, aunt Caroline?”
“Dear me,” said Mrs Clarendon, putting up her hand to her head. “What
was it, Frances? I have such a poor memory; and your father’s coming, and
all this unexpected happiness, have driven everything else away.”
Frances went down-stairs with a heart so heavy that it seemed to lie dead
in her breast. Was there no help for her, then? no help for him, the victim of
Constance and of Markham? no way of softening calamity to the old
people? Her temper rose as her hopes fell. All so rich, so abounding, but no
one who would spare anything out of his superfluity, to help the ruined and
heartbroken. Oh yes, she said to herself in not unnatural bitterness, the
hospitals, yes; and Trotter’s Buildings in Whitechapel. But for the people to
whom they were bound so much more closely, the man who had sat at their
tables, whom they had received and made miserable, nothing! oh, nothing!
not a finger held out to save him. The little countenance that had been like a
summer day, so innocent and fresh and candid, was clouded over. Pride
prevented—pride, more effectual than any other defence—the outburst
which in other circumstances would have relieved her heart. She sat in her
corner, withdrawn as far as possible from Constance, listening dully,
making little response. After several questions, her sister turned upon her
with a surprise which was natural too.
“What is the matter?” she said. “You don’t talk as you used to do. Is it
town that has spoiled you? Do you think I will interfere with you? Oh, you
need not be at all afraid. I have enough of my own without meddling with
you.”
“I don’t know what I have that you could interfere with,” said Frances.
“Nothing here.”
“Do you want to quarrel with me?” Constance said.
“It is of no use to quarrel; there is nothing to quarrel about. I might have
thought you would interfere when you came first to Bordighera. I had
people then who seemed to belong to me. But here—you have the first
place. Why should I quarrel? You are only coming back to your own.”
“Fan, for goodness’ sake, don’t speak in that dreadful tone. What have I
done? If you think papa likes me best, you are mistaken. And as for the
mother, don’t you know her yet? Don’t you know that she is nice to
everybody, and cares neither for you nor me?”
“No,” cried Frances, raising herself bolt upright; “I don’t know that!
How dare you say it, you who are her child? Perhaps you think no one cares
—not one, though you have made an end of my home. Did you hear about
George Gaunt, what you have done to him? He is lying in a brain-fever,
raving, raving, talking for ever, day and night; and if he dies, Markham and
you will have killed him—you and Markham; but you have been the worst.
It will be murder, and you should be killed for it!” the girl cried. Her eyes
blazed upon her sister in the close inclosure of the little brougham. “You
thought he did not care, either, perhaps.”
“Fan! Good heavens! I think you must be going out of your senses,”
Constance cried.
Frances was not able to say any more. She was stifled by the commotion
of her feelings, her heart beating so wildly in her breast, her emotion
reaching the intolerable. The brougham stopped, and she sprang out and ran
into the house, hurrying up-stairs to her own room. Constance, more
surprised and disconcerted than she could have believed possible,
nevertheless came in with an air of great composure, saying a word in
passing to the astonished servant at the door. She was quite amiable always
to the people about her. She walked up-stairs, remarking, as she passed, a
pair of new vases with palms in them, which decorated the staircase, and
which she approved. She opened the drawing-room door in her pretty,
languid-stately, always leisurely way.
“How are you, mamma? Frances has run up-stairs; but here am I, just
come back,” she said.
Lady Markham rose from her seat with a little scream of astonishment.
“Constance! It is not possible. Who would have dreamed of seeing you!”
she cried.
“Oh yes, it is quite possible,” said Constance, when they had kissed,
with a prolonged encounter of lips and cheeks. “Surely, you did not think I
could keep very long away?”
“My darling, did you get home-sick, or mammy-sick as Markham says,
after all your philosophy?”
“I am so glad to see you, mamma, and looking so well. No, not home-
sick, precisely, dear mother, but penetrated with the folly of staying there,
where nothing was ever doing, when I might have been in the centre of
everything: which is saying much the same thing, though in different
words.”
“In very different words,” said Lady Markham, resuming her seat with a
smile. “I see you have not changed at all, Con. Will you have any tea? And
did you leave—your home there—with as little ceremony as you left me!”
“May I help myself, mamma? don’t you trouble. It is very nice to see
your pretty china, instead of Frances’ old bizarre cups, which were much
too good for me. Oh, I did not leave my—home. I—brought it back with
me.”
“You brought——?”
“My father with me, mamma.”
“Oh!” Lady Markham said. She was too much astonished to say more.
“Perhaps it was because he got very tired of me, and thought there was
no other way of getting rid of me; perhaps because he was tired of it
himself. He came at last like a lamb. I did not really believe it till we were
on the boat, and Algy Muncastle turned up, and I introduced him to my
father. You should have seen how he stared.”
“Oh!” said Lady Markham again; and then she added faintly: “Is—is he
here?”
“You mean papa? I left him at aunt Caroline’s. In the circumstances, that
seemed the best thing to do.”
Lady Markham leaned back in her chair; she had become very pale. One
shock after another had reduced her strength. She closed her eyes while
Constance very comfortably sipped her tea. It was not possible that she
could have dreamed it or imagined it, when, on opening her eyes again, she
saw Constance sitting by the tea-table with a plate of bread and butter
before her. “I have really,” she explained seriously, “eaten nothing to-day.”
Frances came down some time after, having bathed her eyes and
smoothed her hair. It was always smooth like satin, shining in the light. She
came in, in her unobtrusive way, ashamed of herself for her outburst of
temper, and determined to be “good,” whatever might happen. She was
surprised that there was no conversation going on. Constance sat in a chair
which Frances at once recognised as having been hers from the beginning
of time, wondering at her own audacity in having sat in it, when she did not
know. Lady Markham was still leaning back in her chair. “Oh, it’s nothing
—only a little giddiness. So many strange things are happening. Did you
give your uncle Clarendon my note? I suppose Frances told you, Con, how
we have been upset to-day?”
“Upset?” said Constance over her bread and butter. “I should have
thought you would have been immensely pleased. It is about Sir Thomas, I
suppose?”
“About Sir Thomas! Is there any news about Sir Thomas?” said Lady
Markham, with an elaborately innocent look. “If so, it has not yet been
confided to me.” And then she proceeded to tell to her daughter the story of
Nelly Winterbourn.
“I should have thought that would all have been set right in the
settlements,” Constance said.
“So it ought. But she had no one to see to the settlements—no one with a
real interest in her; and it was such a magnificent match.”
“No better than Sir Thomas, mamma.”
“Ah, Sir Thomas. Is there really a story about Sir Thomas? I can only
say, if it is so, that he has never confided it to me.”
“I hope no mistake will be made about the settlements in that case. And
what do you suppose Markham will do?”
“What can he do? He will do nothing, Con. You know, after all, that is
the rôle that suits him best. Even if all had been well, unless Nelly had
asked him herself——”
“Do you think she would have minded, after all this time? But I suppose
there’s an end of Nelly now,” Constance said, regretfully.
“I am afraid so,” Lady Markham replied. And then recovering, she began
to tell her daughter the news—all the news of this one and the other, which
Frances had never been able to understand, which Constance entered into as
one to the manner born. They left the subject of Nelly Winterbourn, and not
a word was said of young Gaunt and his fever; but apart from these
subjects, everything that had happened since Constance left England was
discussed between them. They talked and smiled and rippled over into
laughter, and passed in review the thousand friends whose little follies and
freaks both knew, and skimmed across the surface of tragedies with a
consciousness, that gave piquancy to the amusement, of the terrible depths
beneath. Frances, keeping behind, not willing to show her troubled
countenance, from which the traces of tears were not easily effaced, listened
to this light talk with a wonder which almost reached the height of awe. Her
mother at least must have many grave matters in her mind; and even on
Constance, the consciousness of having stirred up all the quiescent evils in
the family history, of her father in England, of the meeting which must take
place between the husband and wife so long parted, all by her influence,
must have a certain weight. But there they sat and talked and laughed, and
shot their little shafts of wit. Frances, at last feeling her heart ache too much
for further repression, and that the pleasant interchange between her mother
and sister exasperated instead of lightened her burdened soul, left them, and
sought refuge in her room, where presently she heard their voices again as
they came up-stairs to dress. Constance’s boxes had in the meantime arrived
from the railway, and the conversation was very animated upon fashions
and new adaptations and what to wear. Then the door of Constance’s room
was closed, and Lady Markham came tapping at that of Frances. She took
the girl into her arms. “Now,” she said, “my dream is going to be realised,
and I shall have my two girls, one on each side of me. My little Frances, are
you not glad?”
“Mother——” the girl said, faltering, and stopped, not able to say any
more.
Lady Markham kissed her tenderly, and smiled, as if she were content.
Was she content? Was the happiness, now she had it, as great as she said?
Was she able to be light-hearted with all these complications round her? But
to these questions who could give any answer? Presently she went to dress,
shutting the door; and, between her two girls, retired so many hundred, so
many thousand miles away—who could tell?—into herself.
In the evening there was considerable stir and commotion in the house.
Markham, warned by one of his mother’s notes, came to dinner full of
affectionate pleasure in Con’s return, and cheerful inquiries for her. “As yet,
you have lost nothing, Con. As yet, nobody has got well into the swim. As
to how the mammy will feel with two daughters to take about, that is a
mystery. If we had known, we’d have shut up little Fan in the nursery for a
year more.”
“It is I that should be sent to the nursery,” said Constance. “Three
months is a long time. Algy Muncastle thought I was dead and buried. He
looked at me as if he were seeing a ghost.”
“A girl might just as well be dead and buried as let half the season slip
over and never appear.”
“Unless she were a widow,” said Con.
“Ah! unless she were a widow, as you say. That changes the face of
affairs.” Markham made a slight involuntary retreat when he received that
blow, but no one mentioned the name of Nelly Winterbourn. It was much
too serious to be taken any notice of now. In the brightness of Lady
Markham’s drawing-room, with all its softened lights, grave subjects were
only discussed tête-à-tête. When the company was more than two,
everything took a sportive turn. Of the two visitors, however, who came in
later, one was not at all disposed to follow this rule. Sir Thomas said but
little to Constance, though her arrival was part of the news which had
brought him here; but he held Lady Markham’s hand with an anxious look
into her eyes, and as soon as he could, drew Frances aside to the distant
corner in which she was fond of placing herself. “Do you know he has
come?” he cried.
“I have seen papa, Sir Thomas, if that is what you mean.”
“What else could I mean?” said Sir Thomas. “You know how I have
tried for this. What did he say? I want to know what disposition he is in.
And what disposition is she in? Frances, you and I have a great deal to do.
We have the ball at our feet. There is nobody acting in both their interests
but you and I.”
There was something in Frances’ eyes and in her look of mute endurance
which startled him, even in the midst of his enthusiasm. “What is the
matter?” he said. “I have not forgotten our bargain. I will do much for you,
if you will work for me. And you want something. Come, tell me what it
is?”
She gave him a look of reproach. Had he, too, forgotten the sick and
miserable, the sufferer, of whom no one thought? “Sir Thomas,” she said,
“Constance has money; she has stopped at Paris to buy dresses. Oh, give me
what is my share.”
“I remember now,” he said.
“Then you know the only thing that any one can do for me. Oh, Sir
Thomas, if you could but give it me now.”
“Shall I speak to your father?” he asked.
These words Markham heard by chance, as he passed them to fetch
something his mother wanted. He returned to where she sat with a curious
look in his little twinkling eyes. “What is Sir Thomas after? Do you know
the silly story that is about? They say that old fellow is after Lady
Markham’s daughter. It had better be put a stop to, mother. I won’t have
anything go amiss with little Fan.”
“Go amiss! with Sir Thomas. There is nobody he might not marry,
Markham—not that anything has ever been said.”
“Let him have anybody he pleases except little Fan. I won’t have
anything happen to Fan. She is not one that would stand it, like the rest of
us. We are old stagers; we are trained for the stake; we know how to grin
and bear it. But that little thing, she has never been brought up to it, and it
would kill her. I won’t have anything go wrong with little Fan.”
“There is nothing going wrong with Frances. You are not talking with
your usual sense, Markham. If that was coming, Frances would be a lucky
girl.”
Markham looked at her with his eyes all pursed up, nearly disappearing
in the puckers round them. “Mother,” he said, “we know a girl who was a
very lucky girl, you and I. Remember Nelly Winterbourn.”
It gave Lady Markham a shock to hear Nelly’s name. “O Markham, the
less we say of her the better,” she cried.
There was another arrival while they talked—Claude Ramsay, with the
flower in his coat a little rubbed by the greatcoat which he had taken off in
the hall, though it was now June. “I heard you had come back,” he said,
dropping languidly into a chair by Constance. “I thought I would come and
see if it was true.”
“You see it is quite true.”
“Yes; and you are looking as well as possible. Everything seems to agree
with you. Do you know I was very nearly going out to that little place in the
Riviera? I got all the renseignements; but then I heard that it got hot and the
people went away.”
“You ought to have come. Don’t you know it is at the back of the east
wind, and there are no draughts there?”
“What an ideal place!” said Claude. “I shall certainly go next winter, if
you are going to be there.”
CHAPTER XLVI.
Frances slept very little all night; her mind was jarred and sore almost at
every point. The day with all its strange experiences, and still more strange
suggestions, had left her in a giddy round of the unreal, in which there
seemed no ground to stand upon. Nelly Winterbourn was the first prodigy in
that round of wonders. Why, with that immovable tragic face, had she
intimated to Lady Markham the tenure upon which she held her fortune?
Why had it been received as something conclusive on all sides? “There is
an end of Nelly.” But why? And then came her mission to her aunt, the
impression that had been made on her mind—the hope that had dawned on
Frances; and then the event which swept both hope and impression away,
and the bitter end that seemed to come to everything in the reappearance of
Constance. Was it that she was jealous of Constance? Frances asked herself
in the silence of the night, with noiseless bitter tears. The throbbing of her
heart was all pain; life had become pain, and nothing more. Was it that she
was jealous—jealous of her sister? It seemed to Frances that her heart was
being wrung, pressed till the life came out of it in great drops under some
giant’s hands. She said to herself, No, no. It was only that Constance came
in her careless grace, and the place was hers, wherever she came; and all
Frances had done, or was trying to do, came to nought. Was that jealousy?
She lay awake through the long hours of the summer night, seeing the early
dawn grow blue, and then warm and lighten into the light of day. And then
all the elements of chaos round her, which whirled and whirled and left no
honest footing, came to a pause and disappeared, and one thing real, one
fact remained—George Gaunt in his fever, lying rapt from all common life,
taking no note of night or day. Perhaps the tide might be turning for death
or life, for this was once more the day that might be the crisis. The other
matters blended into a phantasmagoria, of which Frances could not tell
which part was false and which true, or if anything was true; but here was
reality beyond dispute. She thought of the pale light stealing into his room,
blinding the ineffectual candles; of his weary head on the pillow growing
visible; of the long endless watch; and far away among the mountains, of
the old people waiting and praying, and wondering what news the morning
would bring them. This thought stung Frances into a keen life and energy,
and took from her all reflection upon matters so abstract as that question
whether or not she was jealous of Constance. What did it matter? so long as
he could be brought back from the gates of death and the edge of the grave,
so long as the father and mother could be saved from that awful and
murderous blow. She got up hastily long before any one was stirring. There
are moments when all our ineffectual thinkings, and even futile efforts, end
in a sudden determination that the thing must be done, and revelation of
how to do it. She got up with a little tremor upon her, such as a great
inventor might have when he saw at last his way clearly, or a poet when he
had caught the spark of celestial fire. Is there any machine that was ever
invented, or even any power so divine as the right way to save a life and
deliver a soul? Frances’ little frame was all tingling, but it made her mind
clear and firm. She asked herself how she could have thought of any other
but this way.
It was very early in the morning when she set out. If it had not been
London, in which no dew falls, the paths would have been wet with dew;
even in London, there was a magical something in the air which breathed of
the morning, and which not all the housemaids’ brooms and tradesmen’s
carts in the world could dispel. Frances walked on in the stillness, along the
long silent line of the Park, where there was nobody save a little early
schoolmistress, or perhaps a belated man about town, surprised by the
morning, with red eyes and furtive looks, in the overcoat which hid his
evening clothes, hurrying home—to break the breadth of the sunshine, the
soft morning light, which was neither too warm nor dazzling, but warmed
gently, sweetly to the heart. Her trouble had departed from her in the
resolution she had taken. She was very grave, not knowing whether death or
life, sorrow or hope, might be in the air, but composed, because, whatever it
was, it must now come, all being done that man could do. She did not
hasten, but walked slowly, knowing how early she was, how astonished her
aunt’s servants would be to see her, unattended, walking up to the door. “I
will arise and go to my father.” Wherever these words can be said, there is
peace in them, a sense of safety at least. There are, alas! many cases in
which, with human fathers, they cannot be said; but Waring, whatever his
faults might be, had not forfeited his child’s confidence, and he would
understand. To all human aches and miseries, to be understood is the one
comfort above all others. Those to whom she had appealed before, had been
sorry; they had been astonished; they had gazed at her with troubled eyes.
But her father would understand. This was the chief thing and the best. She
went along under the trees, which were still fresh and green, through the
scenes which, a little while later, would be astir with all the movements, the
comedies, the tragedies, the confusions and complications of life. But now
they lay like a part of the fair silent country, like the paths in a wood, like
the glades in a park, all silent and mute, birds in the branches, dew upon the
grass—a place where Town had abdicated, where Nature reigned.
Waring awoke betimes, being accustomed to the early hours of a
primitive people. It was a curious experience to him to come down through
a closed-up and silent house, where the sunshine came in between the
chinks of the shutters, and all was as it had been in the confusion of the
night. A frightened maid-servant came before him to open the study, which
his brother-in-law Clarendon had occupied till a late hour. Traces of the
lawyer’s vigil were still apparent enough—his waste-paper basket full of
fragments; the little tray standing in the corner, which, even when holding
nothing more than soda-water and claret, suggests dissipation in the
morning. Waring was jarred by all this unpreparedness. He thought with a
sigh of the bookroom in the Palazzo all open to the sweet morning air,
before the sun had come round that way; and when he stepped out upon the
little iron balcony attached to the window and looked out upon other backs
of houses, all crowding round, the recollection of the blue seas, the waving
palms, the great peaks, all carved against the brilliant sky, made him turn
back in disgust. The mean London walls of yellow brick, the narrow
houses, the little windows, all blinded with white blinds and curtains, so
near that he could almost touch them—“However, it will not be like this at
Hilborough,” he said to himself. He was no longer in the mood in which he
had left Bordighera; but yet, having left it, he was ready to acknowledge
that Bordighera was now impossible. His life there had continued from year
to year—it might have continued for ever, with Frances ignorant of all that
had gone before; but the thread of life once broken, could be knitted again
no more. He acknowledged this to himself; and then he found that, in
acknowledging it, he had brought himself face to face with all the gravest
problems of his life. He had held them at arm’s-length for years; but now
they had to be decided, and there was no alternative. He must meet them; he
must look them in the face. And her, too, he must look in the face. Life
once more had come to a point at which neither habit nor the past could
help him. All over again, as if he were a boy coming of age, it would have
to be decided what it should be.
Waring was not at all surprised by the appearance of Frances fresh with
the morning air about her. It seemed quite natural to him. He had forgotten
all about the London streets, and how far it was from one point to another.
He thought she had gained much in her short absence from him,—perhaps
in learning how to act for herself, to think for herself, which she had
acquired since she left him; for he was entirely unaware, and even quite
incapable of being instructed, that Frances had lived her little life as far
apart from him, and been as independent of him while sitting by his side at
Bordighera, as she could have been at the other end of the world. But he
was impressed by the steady light of resolution, the cause of which was as
yet unknown to him, which was shining in her eyes. She told him her story
at once, without the little explanations that had been necessary to the others.
When she said George Gaunt, he knew all that there was to say. The only
thing that it was expedient to conceal was Markham’s part in the
catastrophe, which was, after all, not at all clear to Frances; and as Waring
was not acquainted with Markham’s reputation, there was no suggestion in
his mind of the name that was wanting to explain how the young officer,
knowing nobody, had found entrance into the society which had ruined him.
Frances told her tale in few words. She was magnanimous, and said nothing
of Constance on the one hand, any more than of Markham on the other. She
told her father of the condition in which the young man lay—of his constant
mutterings, so painful to hear, the Red and Black that came up, over and
over again, in his confused thoughts, the distracting burden that awaited
him if he ever got free of that circle of confusion and pain—of the old
people in Switzerland waiting for the daily news, not coming to him as they
wished, because of that one dread yet vulgar difficulty which only she
understood. “Mamma says, of course they would not hesitate at the
expense. Oh no, no! they would not hesitate. But how can I make her
understand? yet we know.”
“How could she understand?” he said with a pale smile, which Frances
knew. “She has never hesitated.” It was all that jarred even upon her excited
nerves and mind. The situation was so much more clear to him than to the
others, to whom young Gaunt was a stranger. And Waring, too, was in his
nature something of a Quixote to those who took him on the generous side.
He listened—he understood; he remembered all that had been enacted
under his eyes. The young fellow had gone to London in desperation,
unsettled, and wounded by the woman to whom he had given his love—and
he had fallen into the first snare that presented itself. It was weak, it was
miserable; but it was not more than a man could understand. When Frances
found that at last her object was attained, the unlikeliness that it ever should
have been attained, overwhelmed her even in the moment of victory. She
clasped her arms round her father’s arm, and laid down her head upon it,
and, to his great surprise, burst into a passion of tears. “What is the matter?
What has happened? Have I said anything to hurt you?” he cried, half
touched, half vexed, not knowing what it was, smoothing her glossy hair
half tenderly, half reluctantly, with his disengaged hand.
“Oh, it is nothing, nothing! It is my folly; it is—happiness. I have tried to
tell them all, and no one would understand. But one’s father—one’s father
is like no one else,” cried Frances, with her cheek upon his sleeve.
Waring was altogether penetrated by these simple words, and by the
childish action, which reminded him of the time when the little forlorn child
he had carried away with him had no one but him in the world. “My dear,”
he said, “it makes me happy that you think so. I have been rather a failure, I
fear, in most things; but if you think so, I can’t have been a failure all
round.” His heart grew very soft over his little girl. He was in a new world,
though it was the old one. His sister, whom he had not seen for so long, had
half disgusted him with her violent partisanship, though his was the party
she upheld so strongly. And Constance, who had no hold of habitual union
upon him, had exhibited all her faults to his eyes. But his little girl was still
his little girl, and believed in her father. It brought a softening of all the ice
and snow about his heart.
They walked together through the many streets to inquire for poor
Gaunt, and were admitted with shakings of the head and downcast looks.
He had passed a very disturbed night, though at present he seemed to sleep.
The nurse who had been up all night, and was much depressed, was afraid
that there were symptoms of a “change.” “I think the parents should be sent
for, sir,” she said, addressing herself at once to Waring. These attendants did
not mind what they said over the uneasy bed. “He don’t know what we are
saying, any more than the bed he lies on. Look at him, miss, and tell me if
you don’t think there is a change?” Frances held fast by her father’s arm.
She was more diffident in his presence than she had been before. The
sufferer’s gaunt face was flushed, his lips moved, though, in his weakness,
his words were not audible. The other nurse, who had come to relieve her
colleague, and who was fresh and unwearied, was far more hopeful. But
she, too, thought that “a change” might be approaching, and that it would be
well to summon the friends. She went down-stairs with them to talk it over
a little more. “It seems to me that he takes more notice than we are aware
of,” she said. “The ways of sick folks are that wonderful, we don’t
understand, not the half of them; seems to me that you have a kind of an
influence, miss. Last night he changed after you were here, and took me for
his mamma, and asked me what I meant, and said something about a Miss
Una that was true, and a false Jessie or something. I wonder if your name is
Miss Una, miss?” This inquiry was made while Waring was writing a
telegram to the parents. Frances, who was not very quick, could only
wonder for a long time who Una was and Jessie. It was not till evening,
nearly twelve hours after, that there suddenly came into her mind the false
Duessa of the poet. And then the question remained, who was Una, and who
Duessa? a question to which she could find no reply.
Frances remained with her father the greater part of the day. When she
found that what she desired was to be done, there fell a strange kind of lull
into her being, which unaccountably took away her strength, so that she
scarcely felt herself able to hold up her head. She began to be aware that
she had neither slept by night nor had any peace by day, and that a fever of
the mind had been stealing upon her, a sort of reflection of the other fever,
in which her patient was enveloped as in a living shroud. She was scarcely
able to stand, and yet she could not rest. Had she not put force upon herself,
she would have been sending to and fro all day, creeping thither on limbs
that would scarcely support her, to know how he was, or if the change had
yet appeared. She had not feared for his life before, having no tradition of
death in her mind; but now an alarm grew upon her that any moment might
see the blow fall, and that the parents might come in vain. It was while she
stood at one of the windows of Mrs Clarendon’s gloomy drawing-room,
watching for the return of one of her messengers, that she saw her mother’s
well-known brougham drive up to the door. She turned round with a little
cry of “Mamma” to where her father was sitting, in one of the seldom used
chairs. Mrs Clarendon, who would not leave him for many minutes, was
hovering by, wearying his fastidious mind with unnecessary solicitude, and
a succession of questions which he neither could nor wished to answer. She
flung up her arms when she heard Frances’ cry. “Your mother! Oh, has she
dared! Edward, go away, and let me meet her. She will not get much out of
me.”
“Do you think I am going to fly from my wife?” Waring said. He rose up
very tremulous, yet with a certain dignity. “In that case, I should not have
come here.”
“But, Edward, you are not prepared. O Edward, be guided by me. If you
once get into that woman’s hands——”
“Hush!” he said; “her daughter is here.” Then, with a smile: “When a
lady comes to see me, I hope I can receive her still as a gentleman should,
whoever she may be.”
The door opened, and Lady Markham came in. She was very pale, yet
flushed from moment to moment. She, who had usually such perfect self-
command, betrayed her agitation by little movements, by the clasping and
unclasping of her hands, by a hurried, slightly audible breathing. She stood
for a moment without advancing, the door closing behind her, facing the
agitated group. Frances, following an instinctive impulse, went hastily
towards her mother as a maid of honour in an emergency might hurry to
take her place behind the Queen. Mrs Clarendon on her side, with a similar
impulse, drew nearer to her brother—the way was cleared between the two,
once lovers, now antagonists. The pause was but for a moment. Lady
Markham, after that hesitation, came forward. She said: “Edward, I should
be wanting in my duty if I did not come to welcome you home.”
“Home!” he said, with a curious smile. Then he, too, came forward a
little. “I accept your advances in the same spirit, Frances.” She was holding
out her hands to him with a little appeal, looking at him with eyes that sank
and rose again—an emotion that was restrained by her age, by her matronly
person, by the dignity of the woman, which could not be quenched by any
flood of feeling. He took her hands in his with a strange timidity, hesitating,
as if there might be something more, then let them drop, and they stood
once again apart.
“I have to thank you, too,” she said, “for bringing Constance back to me
safe and well; and what is more, Edward, for this child.” She put out her
hand to Frances, and drew her close, so that the girl could feel the agitation
in her mother’s whole person, and knew that, weak as she was, she was a
support to the other, who was so much stronger. “I owe you more thanks
still for her—that she never had been taught to think any harm of her
mother, that she came back to me as innocent and true as she went away.”
“If you found her so, Frances, it was to her own praise, rather than
mine.”
“Nay,” she said with a tremulous smile, “I have not to learn now that the
father of my children was fit to be trusted with a girl’s mind—more,
perhaps, than their mother—and the world together.” She shook off this
subject, which was too germane to the whole matter, with a little tremulous
movement of her head and hands. “We must not enter on that,” she said.
“Though I am only a woman of the world, it might be too much for me.
Discussion must be for another time. But we may be friends.”
“So far as I am concerned.”
“And I too, Edward. There are things even we might consult about—
without prejudice, as the lawyers say—for the children’s good.”
“Whatever you wish my advice upon——”
“Yes, that is perhaps the way to put it,” Lady Markham said, after a
pause which looked like disappointment, and with an agitated smile. “Will
you be so friendly, then,” she added, “as to dine at my house with the girls
and me? No one you dislike will be there. Sir Thomas, who is in great
excitement about your arrival; and perhaps Claude Ramsay, whom
Constance has come back to marry.”
“Then she has settled that?”
“I think so; yet no doubt she would like him to be seen by you. I hope
you will come,” she said, looking up at him with a smile.
“It will be very strange,” he said, “to dine as a guest at your table.”
“Yes, Edward; but everything is strange. We are so much older now than
we were. We can afford, perhaps, to disagree, and yet be friends.”
“I will come if it will give you any pleasure,” he said.
“Certainly, it will give me pleasure.” She had been standing all the time,
not having even been offered a seat—an omission which neither he nor she
had discovered. He did it now, placing with great politeness a chair for her;
but she did not sit down.
“For the first time, perhaps it is enough,” she said. “And Caroline thinks
it more than enough. Good-bye, Edward. If you will believe me, I am—
truly glad to see you: and I hope we may be friends.”
She half raised her clasped hands again. This time he took them in both
his, and leaning towards her, kissed her on the forehead. Frances felt the
tremor that ran through her mother’s frame. “Good-bye,” she said, “till this
evening.” Only the girl knew why Lady Markham hurried from the room.
She stopped in the hall below to regain her self-command and arrange her
bonnet. “It is so long since we have met,” she said, “it upsets me. Can you
wonder, Frances? The woman in the end always feels it most. And then
there are so many things to upset me just now. Constance and Markham—
say nothing of Markham; do not mention his name—and even you——”
“There is nothing about me to annoy you, mamma.”
Lady Markham smiled with a face that was near crying. She gave a little
tap with her finger upon Frances’ cheek, and then she hurried away.
CHAPTER XLVII.
The dinner, it need scarcely be said, was a strange one. Except in
Constance, who was perfectly cool, and Claude, who was more concerned
about a possible draught from a window than anything else, there was much
agitation in the rest of the party. Lady Markham was nervously cordial,
anxious to talk and to make everything “go”—which, indeed, she would
have done far more effectually had she been able to retain her usual
cheerful and benign composure. But there are some things which are
scarcely possible even to the most accomplished woman of the world. How
to place the guests, even, had been a trouble to her, almost too great to be
faced. To place her husband by her side was more than she could bear, and
where else could it be appropriate to place him, unless opposite to her,
where the master of the house should sit? The difficulty was solved loosely
by placing Constance there, and her father beside her. He sat between his
daughters; while Ramsay and Sir Thomas were on either side of his wife.
Under such circumstances, it was impossible that the conversation could be
other than formal, with outbursts of somewhat conventional vivacity from
Sir Thomas, supported by anxious responses from Lady Markham. Frances
took refuge in saying nothing at all. And Waring sat like a ghost, with a
smile on his face, in which there was a sort of pathetic humour, dashed with
something that was half derision. To be sitting there at all was wonderful
indeed, and to be listening to the smalltalk of a London dinner-table, with
all its little discussions, its talk of plays and pictures and people, its scraps
of political life behind the scenes, its esoteric revelations on all subjects,
was more wonderful still. He had half forgotten it; and to come thus at a
single step into the midst of it all, and hear this babble floating on the air
which was charged with so many tragic elements, was more wonderful still.
To think that they should all be looking at each other across the flowers and
the crystal, and knowing what questions were to be solved between them,
yet talking and expecting others to talk of the new tenor and the last
scandal! It seemed to the stranger out of the wilds, who had been banished
from society so long, that it was a thing incredible, when he was thus
thrown into it again. There were allusions to many things which he did not
understand. There was something, for instance, about Nelly Winterbourn
which called forth a startling response from Lady Markham. “You must
not,” she said, “say anything about poor Nelly in this house. From my heart,
I am sorry and grieved for her; but in the circumstances, what can any one
do? The least said, the better, especially here.” The pause after this was
minute but marked, and Waring asked Constance, “Who is Nelly
Winterbourn?”
“She is a young widow, papa. It was thought her husband had left her a
large fortune; but he has left it to her on the condition that she should not
marry again.”
“Is that why she is not to be spoken of in this house?” said Waring,
growing red. This explanation had been asked and given in an undertone.
He thought it referred to the circumstances in which his own marriage had
taken place—Lady Markham being a young widow with a large jointure;
and that this was the reason why the other was not to be mentioned; and it
gave him a hot sense of offence, restrained by the politeness which is
exercised in society, but not always when the offenders are one’s wife and
children. It turned the tide of softened thoughts back upon his heart, and
increased to fierceness the derision with which he listened to all the trifles
that floated uppermost. When the ladies left the room, he did not meet the
questioning, almost timid, look that Lady Markham threw upon him. He
saw it, indeed, but he would not respond to it. That allusion had spoiled all
the rest.
In the little interval after dinner, Claude Ramsay did his best to make
himself agreeable. “I am very glad to see you back, sir,” he said. “I told
Lady Markham it was the right thing. When a girl has a father, it’s always
odd that he shouldn’t appear.”
“Oh, you told Lady Markham that it was—the right thing?”
“A coincidence, wasn’t it? when you were on your way,” said Claude,
perceiving the mistake he had made. “You know, sir,” he added with a little
hesitation, “that it has all been made up for a long time between Constance
and me.”
“Yes? What has all been made up? I understand that my daughter came
out to me to——”
“Oh!” said Claude, interrupting hurriedly, “it is that that has all been
made up. Constance has been very nice about it,” he continued. “She has
been making a study of the Riviera, and collecting all sorts of
renseignements; for in most cases, it is necessary for me to winter abroad.”
Welcome to Our Bookstore - The Ultimate Destination for Book Lovers
Are you passionate about books and eager to explore new worlds of
knowledge? At our website, we offer a vast collection of books that
cater to every interest and age group. From classic literature to
specialized publications, self-help books, and children’s stories, we
have it all! Each book is a gateway to new adventures, helping you
expand your knowledge and nourish your soul
Experience Convenient and Enjoyable Book Shopping Our website is more
than just an online bookstore—it’s a bridge connecting readers to the
timeless values of culture and wisdom. With a sleek and user-friendly
interface and a smart search system, you can find your favorite books
quickly and easily. Enjoy special promotions, fast home delivery, and
a seamless shopping experience that saves you time and enhances your
love for reading.
Let us accompany you on the journey of exploring knowledge and
personal growth!

ebookgate.com

You might also like