13.12.1 issubclass()
Theissubclass() Boolean function determines if one class is a subclass or descendant of another class. It has the following syntax:
issubclass(sub, sup)
issubclass() returns True if the given subclass sub is indeed a subclass of the superclass sup (and False otherwise). This function allows for an
“improper” subclass, meaning that a class is viewed as a subclass of itself, so the function returns True if sub is either the same class as sup or derived fromsup. (A “proper” subclass is strictly a derived subclass of a class.)
ptg 13.12 Built-in Functions for Classes, Instances, and Other Objects 559
Beginning with Python 2.3, the second argument of issubclass() can be tuple of possible parent classes for which it will return True if the first argu- ment is a subclass of any of the candidate classes in the given tuple.
13.12.2 isinstance()
Theisinstance() Boolean function is useful for determining if an object is an instance of a given class. It has the following syntax:
isinstance(obj1, obj2)
isinstance() returns True if obj1 is an instance of class obj2 or is an instance of a subclass of obj2 (and False otherwise), as indicated in the fol- lowing examples:
>>> class C1(object): pass ...
>>> class C2(object): pass ...
>>> c1 = C1()
>>> c2 = C2()
>>> isinstance(c1, C1) True
>>> isinstance(c2, C1) False
>>> isinstance(c1, C2) False
>>> isinstance(c2, C2) True
>>> isinstance(C2, c2) Traceback (innermost last):
File "<stdin>", line 1, in ? isinstance(C2, c2)
TypeError: second argument must be a class
Note that the second argument should be a class; otherwise, you get a TypeError. The only exception is if the second argument is a type object.
This is allowed because you can also use isinstance() to check if an object obj1 is of the type obj2, i.e.,
>>> isinstance(4, int) True
>>> isinstance(4, str) False
>>> isinstance('4', str) True
ptg 560 Chapter 13 Object-Oriented Programming
If you are coming from Java, you may be aware of the warning against using its equivalent, instanceof(), due to performance reasons. A call to Python’s isinstance() will not have the same performance hit primarily because it only needs it to perform a quick search up the class hierarchy to determine what classes it is an instance of, and even more importantly, it is written in C!
Likeissubclass(), isinstance() can also take a tuple as its second argument. This feature was added in Python 2.2. It will return True if the first argument is an instance of any of the candidate types and classes in the given tuple. Also be sure to read more about isinstance() in Section 13.16.1 on page 595.
13.12.3 hasattr() , getattr() , setattr() , delattr()
The *attr() functions can work with all kinds of objects, not just classes and instances. However, since they are most often used with those objects, we present them here. One thing that might throw you off is that when using these functions, you pass in the object you are working on as the first argu- ment, but the attribute name, the second argument to these functions, is the string name of the attribute. In other words, when operating with obj.attr, the function call will be like *attr(obj, 'attr'...)—this will be clear in the examples that follow.
Thehasattr() function is Boolean and its only purpose is to determine whether or not an object has a particular attribute, presumably used as a check before actually trying to access that attribute. The getattr() and setattr() functions retrieve and assign values to object attributes, respec- tively. getattr() will raise an AttributeError exception if you attempt to read an object that does not have the requested attribute, unless a third, optional default argument is given. setattr() will either add a new attribute to the object or replace a pre-existing one. The delattr() function removes an attribute from an object.
Here are some examples using all the *attr() BIFs:
>>> class myClass(object):
... def __init__(self):
... self.foo = 100 ...
>>> myInst = myClass()
>>> hasattr(myInst, 'foo') True
ptg 13.12 Built-in Functions for Classes, Instances, and Other Objects 561
>>> getattr(myInst, 'foo') 100
>>> hasattr(myInst, 'bar') False
>>> getattr(myInst, 'bar')
Traceback (most recent call last):
File "<stdin>", line 1, in ? getattr(myInst, 'bar')
AttributeError: myClass instance has no attribute 'bar'
>>> getattr(c, 'bar', 'oops!') 'oops!'
>>> setattr(myInst, 'bar', 'my attr')
>>> dir(myInst)
['__doc__', '__module__', 'bar', 'foo']
>>> getattr(myInst, 'bar') # same as myInst.bar 'my attr'
>>> delattr(myInst, 'foo')
>>> dir(myInst)
['__doc__', '__module__', 'bar']
>>> hasattr(myInst, 'foo') False
13.12.4 dir()
We first experienced dir() in Exercises 2–12, 2–13, and 4–7. In those exer- cises, we used dir() to give us information about all the attributes of a mod- ule. We now know that dir() can be applied to objects as well.
In Python 2.2, dir() received a significant upgrade. Because of these changes, the voluntarily implemented __members__ and __methods__ data attributes have been deprecated. dir() provides more details than the old one. According to the documentation, “In addition to the names of instance variables and regular methods, it also shows the methods that are normally invoked through special notations, like __iadd__ (+=), __len__ (len()), __ne__ (!=).” Here are more specifics from the Python documentation:
• dir() on an instance (classic or new-style) shows the instance variables as well as the methods and class attributes defined by the instance’s class and all its base classes.
• dir() on a class (classic or new-style) shows the contents of the __dict__ of the class and all its base classes. It does not show class attributes that are defined by a metaclass.
• dir() on a module shows the contents of the module’s __dict__. (This is unchanged.)
ptg 562 Chapter 13 Object-Oriented Programming
• dir() without arguments shows the caller’s local variables.
(Again, unchanged.)
• There are more details; in particular, for objects that
override__dict__ or __class__, these are honored, and for backwards compatibility, __members__ and __methods__ are honored if they are defined.
13.12.5 super()
Thesuper() function was added in 2.2 for new-style classes. The purpose of this function is to help the programmer chase down the appropriate super- class with which the proper method can be invoked. In simple cases, the pro- grammer will likely just call the ancestor class method in an unbound fashion.
Usingsuper() simplifies the task of search for a suitable ancestor and passes in the instance or type object on your behalf when you call it.
In Section 13.11.4, we described the method resolution order (MRO) that is used to chase down attributes in ancestor classes. For each class defined, an attribute named __mro__ is created as a tuple that lists the classes that need to be searched, in the order they are searched. Here is its syntax:
super(type[, obj])
Giventype,super() “returns the superclass” of type. You may also pass in obj, which should be of the type type if you want the superclass to be bound, otherwise it will be unbound. The obj argument can also be a type, but it needs to be a subclass of type. In summary, when obj is given:
• If obj is an instance, then isinstance(obj,type) must beTrue
• If obj is a class or type, then issubclass(obj,type) must beTrue
Actually, super() is a factory function that makes a super object that uses the __mro__ attribute for a given class to find the appropriate super- class. Most notably, it searches that MRO starting from the point where the current class is found. For more details, again please see Guido van Rossum’s essay on type and class unification, where he even gives a pure Python imple- mentation of super() so you can get a better idea of how it works!
Final thought… super()’s primary use is in the lookup of a superclass attribute, e.g., super(MyClass, self).__init__(). If you are not per- forming such a lookup, you probably do not need to be using super().
ptg 13.12 Built-in Functions for Classes, Instances, and Other Objects 563
There are various examples how to use super() scattered throughout this chapter. Also be sure to read the important notes about super()in Sec- tion 13.11.2, especially the Core Note in that section.
13.12.6 vars()
Thevars() built-in function is similar to dir() except that any object given as the argument must have a __dict__ attribute. vars() will return a dic- tionary of the attributes (keys) and values of the given object based on the values in its __dict__ attribute. If the object provided does not have such an attribute, an TypeError exception is raised. If no object is provided as an argument to vars(), it will display the dictionary of attributes (keys) and the values of the local namespace, i.e., locals(). We present an example of callingvars() with a class instance:
class C(object):
pass
>>> c = C()
>>> c.foo = 100
>>> c.bar = 'Python'
>>> c.__dict__
{'foo': 100, 'bar': 'Python'}
>>> vars(c)
{'foo': 100, 'bar': 'Python'}
Table 13.3 summarizes the built-in functions for classes and class instances.
Table 13.3 Built-in Functions for Classes, Instances, and Other Objects
Built-in Function Description
issubclass(sub, sup) ReturnsTrue if class sub is a subclass of class sup,False otherwise
isinstance(obj1, obj2) ReturnsTrue if instance obj1 is an instance of class obj2 or is an instance of a subclass of obj2; will also return True if obj1 is of type obj2; otherwise it returns False
hasattr(obj, attr) ReturnsTrue if obj has attribute attr (given as a string), False otherwise
(continued)
ptg 564 Chapter 13 Object-Oriented Programming