|ePolyglot: Examination and development of multilanguage programming using Eiffel, Python, and Haskell|
|Prev||Chapter 7. Shadow Classes||Next|
The basic PYTHON_OBJECT class hierarchy consists of thirteen classes comprising the basic primitives of Python, and two additional classes for user-defined Python classes and modules (which will be discussed more fully in a later section of the documentation). The Eiffel "short forms" of the classes can be found in the documentation reference part of this document; what follows is a brief description of each of the classes and what they are good for:
The PYTHON_OBJECT class represents the root of the Python object shadow class hierarchy. It provides features for
Object creation, including reference count examination and incrementing/decrementing.
Object destruction, including automatic decrement of the Python object's reference count on garbage collection.
Attribute getting, setting, and deleting using Eiffel strings and PYTHON_OBJECTs as keys.
Standard attributes as features, either returning the desired object or the constant None object, for the standard Python attributes __dict__, __methods__, __class__, __bases__, and __name__.
Comparison operations, such as is_equal, cmp, compare, and the infix "<" operator
String representations of the object, for both the Python str and repr functions, available as Eiffel STRINGs or Python string objects
Primitive identification of the object in the form of a series of checks (is_file, is_integer, etc.)
Features for calling "callable" objects such as Python function objects
Features for getting the type of a Python object
Features for various attributes of the Python object, such as hash codes, length, etc.
Contracts for many of the features, such as requiring that "get attribute" methods are only executed on objects that "have" the attributes, ensuring that return codes are valid, or the invariant that the reference count is valid. Descendants of PYTHON_OBJECT generally also include the invariant that the object pointed to by the python_object_pointer pointer are of the desired class (so that the developer cannot assign a Python tuple pointer to a PYTHON_NUMBER object, for example).
The PYTHON_NUMBER class provides the base for manipulating number primitives under Eiffel. The class includes features such as:
Inheritance of the Eiffel NUMERIC class, enabling Python numbers to be treated in the same way as Eiffel numbers
Support for basic numeric operations such as infix operators "+", "-", "*", "/", "^" and prefix operators "+" and "-"
Modulo arithmetic including remainder and (result, remainder) tuples
Power function for raising a number to a variable power (the infix "^" operator only allows integer powers)
Bitwise manipulation of numbers, such as inversion, left/right shifts, and and/or/xor modifications
Type conversions to the child classes PYTHON_INTEGER and PYTHON_LONG, as well as conversion to Eiffel DOUBLEs
Child classes for PYTHON_INTEGER and PYTHON_LONG, wihch support conversion to and from the appropriate Eiffel classes
The PYTHON_SEQUENCE class contains the base functions for manipulating sequences (see the child class descriptions for further information on specific classes such as strings and tuples). Included are features for:
Attributes such as length
Concatenation of sequences to produce new sequences (distinct from appending, this creates a new sequence--useful since Python strings and tuples are immutable)
Repeats of a sequence
Features for getting and setting items and slices of a list, and removing items
Turning a list into a tuple
Determining whether a sequence includes a value, or the count of those included, and the index of a particular element
The PYTHON_LIST class represents the Python list abstraction, which is a flexible array of Python objects. Lists are unrestricted in their contents and can contain any sort of PYTHON_OBJECTs; they provide all the features of a PYTHON_SEQUENCE, with the additional features of:
Insertion of items into the list
Sorting or reversing the list
Tuples in Python are essentially immutable lists; while the class contains features for setting items or slices, this is meant to be done primarily for construction and is probably hazardous to do once the object is constructed
Another immutable sequence, the PYTHON_STRING class also includes added functions for creating the Python string from an Eiffel STRING object, for getting the C representation of the Python string, and for formatting the string as with the C printf function (although this takes a tuple of Python arguments as its primary orgument, which may not be worth the effort).
It's important to note that, since Python strings are immutable, the Python interpreter caches them--so developers can't judge much based on the reference count of a Python string, and if the C representation of the Python string is changed, all Python objects referencing it will reflect the change--which could be surprising. Far better to leave immutable objects actually immutable.
Mappings represent mappings from a set of inputs to a single output-- in the case of Python mappings, this basically means from a single input to an output, meaning a dictionary. Even so, this vertical class hierarchy (consisting of PYTHON_MAPPING and its single descendant PYTHON_DICTIONARY) remains separated into two layers. The base class contains features for:
The number of items in the mapping
The ability to add, delete, replace, or get items using either an Eiffel STRING or Python object as the key
The ability to query for the presence of a key
Features for getting the list of keys, items, or (key, item) tuples present in the dictionary
While the PYTHON_MAPPING class contains the same features specifically targeted toward dictionaries.
Python file objects can be easily created and manipulated. The PYTHON_FILE class allows this to be done from within Eiffel, including features to:
Create the file from a filename
Read a line from the file
Query for the file's filename
Write an object or string to the file
Manipulation of Python code modules is possible using the PYTHON_MODULE class, which allows functions for creating the module (either a new blank module or an imported one) and querying for names, filenames, and dictionaries.
Not really part of the PYTHON_OBJECT hierarchy, the PYTHON_OBJECT_FACTORY class is an invaluable helper class designed to simplify the creation of new PYTHON_OBJECT primitives and conversion of Eiffel values into PYTHON_OBJECTs. Included are features for:
Creating specific new objects via the features new_python_string, new_python_integer, and new_python_float, which take arguments of the corresponding Eiffel types
Conversion of Eiffel values into PYTHON_OBJECT equivalents via the functions new_python_tuple and python_equivalent. This is done rather sneakily via the Eiffel conforms_to feature, which tests conformance of an Eiffel type to another type interface. As such, it is something of a hack--a statically typed language, Eiffel is not suited for reflection, but this works tolerably and considerably simplifies the process of passing arguments to Python functions, an area which will be explored more fully in the section on using user-defined Python classes from within Eiffel.