程式扎記: [Quick Python] 19. Data types as objects

標籤

2012年3月15日 星期四

[Quick Python] 19. Data types as objects

Preface : 
By now, you’ve learned the basic Python types and also how to create your own data types using classes. For many languages, that would be pretty much it, as far as data types are concerned. But Python is dynamically typed, meaning that types of things are determined at runtime, not at compile time. This is one of the reasons Python is so easy to use. It also makes it possible, and sometimes necessary, to compute with the types of objects (and not just the objects themselves). 

This chapter covers : 
* Treating types as objects
* Using types
* Creating user-defined classes
* Understanding duck typing

Types are objects, too : 
Fire up a Python session, and try out the following : 
>>> type(5)

>>> type(['hello', 'goodbye'])

This is the first time you’ve seen the built-in type() function in Python. It can be applied to any Python object and returns the type of that object. In this example, it tells us that 5 is an int (integer) and that ['hello', 'goodbye'] is a list, something you probably already knew. 

Of greater interest is that Python returns objects in response to the calls to type; and are the screen representations of the returned objects. What sort of object is returned by a call of type(5)? We have any easy way of finding out—just use type on that result : 
>>> type_result = type(5)
>>> type(type_result)

The object returned by type is an object whose type happens to be —we can call it a type object. A type object is another kind of Python object whose only outstanding feature is the confusion its name sometime causes. Saying a type object is of type has about the same degree of clarity as the old Abbot and Costello “Who’s on First?” comedy routine. 

Using types : 
Now that you know that data types can be represented as Python type objects, what can you do with them? You can compare them, because any two Python objects can be compared : 
>>> type("Hello") == type("Goodbye")
True
>>> type("Hello") == type(5)
False
>>> type("Hello") is type("Goodbye") # They are both "str" type. And the returned object from type() are the same
True

The types of "Hello" and "Goodbye" are the same (they’re both strings), but the types of "Hello" and 5 are different. Among other things, you can use this to provide type checking in your function and method definitions. 

Types and user-defined classes : 
The most common reason to be interested in the types of objects, particularly instances of user-defined classes, is to find out whether a particular object is an instance of a class. After determining that an object is of a particular type, the code can treat it appropriately. An example makes things much clearer. To start, let’s define a couple of empty classes, so as to set up a simple inheritance hierarchy : 
  1. class A:  
  2.     pass  
  3. class B(A):  
  4.     pass  
Now, create an instance of class B : 
>>> b = B()

As expected, applying the type function to b tells us that b is an instance of the class B that’s defined in our current __main__ namespace : 
>>> type(b)
__main__.B'>

We can also obtain exactly the same information by accessing the instance’s special __class__ attribute : 
>>> b.__class__

We’ll be working with that class quite a bit to extract further information, so let’s store it somewhere : 
>>> b_class = b.__class__

Now, to emphasize that everything in Python is an object, let’s prove that the class we obtained from b is the class we defined under the name B : 
>>> b_class == B
True

In this example, we didn’t need to store the class of b—we already had it—but I want to make clear that a class is just another Python object and can be stored or passed around like any Python object. Given the class of b, we can find the name of that class using its __name__ attribute : 
>>> b_class.__name__
'B'

And we can find out what classes it inherits from by accessing its __bases__ attribute, which contains a tuple of all of its base classes : 
>>> b_class.__bases__
(,)

Used together, __class____bases__, and __name__ allow a full analysis of the class inheritance structure associated with any instance. 

But two built-in functions provide a more user-friendly way of obtaining most of the information we usually need: isinstance() and issubclass(). The isinstance function is what you should use to determine whether, for example, a class passed into a function or method is of the expected type : 
- Exam02.py :
  1. class C:  
  2.     pass  
  3. class D:  
  4.     pass  
  5. class E(D):  
  6.     pass  

Then enter interactive session and key in : 
 

For class instances, check against the class (1). e is an instance of class D because E inherits from D (2). But d isn’t an instance of class E (3). For other types, you can use an example (4). A class is considered a subclass of itself (5). 

Duck typing : 
Using type()isinstance(), and issubclass() makes it fairly easy to make code correctly determine an object’s or class’s inheritance hierarchy. Although this is easy, Python also has a feature that makes using objects even easier: duck typingDuck typing, as in “if it walks like a duck and quacks like a duck, it probably is a duck,” refers to Python’s way of determining whether an object is the required type for an operation, focusing on an object’s interface rather than its type. If an operation needs an iterator, for example, the object used doesn’t need to be a subclass of any particular iterator or of any iterator at all. All that matters is that the object used as an iterator is able to yield a series of objects in the expected way. 

This is in contrast to a language like Java, where stricter rules of inheritance are enforced. In short, duck typing means that in Python, you don’t need to (and probably shouldn’t) worry about type-checking function or method arguments and the like. Instead, you should rely on readable and documented code combined with thorough testing to make sure an object “quacks like a duck” as needed. 

Duck typing can increase the flexibility of well-written code and, combined with the more advanced OO features discussed in chapter 20, gives you the ability to create classes and objects to cover almost any situation. 

Supplement : 
The Python Standard Library > 5. Built-in Types

沒有留言:

張貼留言

網誌存檔

關於我自己

我的相片
Where there is a will, there is a way!