168 lines
3.7 KiB
Markdown
168 lines
3.7 KiB
Markdown
|
\[ [Index](index.md) | [Exercise 3.8](ex3_8.md) | [Exercise 4.2](ex4_2.md) \]
|
||
|
|
||
|
# Exercise 4.1
|
||
|
|
||
|
*Objectives:*
|
||
|
|
||
|
- Learn more about how objects are represented.
|
||
|
- Learn how attribute assignment and lookup works.
|
||
|
- Better understand the role of a class definition
|
||
|
|
||
|
*Files Created:* None
|
||
|
|
||
|
*Files Modified:* None
|
||
|
|
||
|
Start this exercise, by going back to a simple version of the `Stock` class you created.
|
||
|
At the interactive prompt, define a
|
||
|
new class called `SimpleStock` that looks like this:
|
||
|
|
||
|
```python
|
||
|
>>> class SimpleStock:
|
||
|
def __init__(self, name, shares, price):
|
||
|
self.name = name
|
||
|
self.shares = shares
|
||
|
self.price = price
|
||
|
def cost(self):
|
||
|
return self.shares * self.price
|
||
|
|
||
|
>>>
|
||
|
```
|
||
|
|
||
|
Once you have defined this class, create a few instances.
|
||
|
|
||
|
```python
|
||
|
>>> goog = SimpleStock('GOOG',100,490.10)
|
||
|
>>> ibm = SimpleStock('IBM',50, 91.23)
|
||
|
>>>
|
||
|
```
|
||
|
|
||
|
## (a) Representation of Instances
|
||
|
|
||
|
At the interactive shell, inspect the underlying dictionaries of the two instances you created:
|
||
|
|
||
|
```python
|
||
|
>>> goog.__dict__
|
||
|
... look at the output ...
|
||
|
>>> ibm.__dict__
|
||
|
... look at the output ...
|
||
|
>>>
|
||
|
```
|
||
|
|
||
|
## (b) Modification of Instance Data
|
||
|
|
||
|
Try setting a new attribute on one of the above instances:
|
||
|
|
||
|
```python
|
||
|
>>> goog.date = "6/11/2007"
|
||
|
>>> goog.__dict__
|
||
|
... look at output ...
|
||
|
>>> ibm.__dict__
|
||
|
... look at output ...
|
||
|
>>>
|
||
|
```
|
||
|
|
||
|
In the above output, you'll notice that the `goog` instance has
|
||
|
a attribute `date` whereas the `ibm` instance does not.
|
||
|
It is important to note that Python really doesn't place any
|
||
|
restrictions on attributes. For example, the attributes of an
|
||
|
instance are not limited to those set up in the `__init__()`
|
||
|
method.
|
||
|
|
||
|
Instead of setting an attribute, try placing a new value directly into
|
||
|
the `__dict__` object:
|
||
|
|
||
|
```python
|
||
|
>>> goog.__dict__['time'] = '9:45am'
|
||
|
>>> goog.time
|
||
|
'9:45am'
|
||
|
>>>
|
||
|
```
|
||
|
|
||
|
Here, you really notice the fact that an instance is a layer on top of a dictionary.
|
||
|
|
||
|
|
||
|
## (c) The role of classes
|
||
|
|
||
|
The definitions that make up a class definition are shared by all
|
||
|
instances of that class. Notice, that all instances have a link back
|
||
|
to their associated class:
|
||
|
|
||
|
```python
|
||
|
>>> goog.__class__
|
||
|
... look at output ...
|
||
|
>>> ibm.__class__
|
||
|
... look at output ...
|
||
|
>>>
|
||
|
```
|
||
|
|
||
|
Try calling a method on the instances:
|
||
|
|
||
|
```python
|
||
|
>>> goog.cost()
|
||
|
49010.0
|
||
|
>>> ibm.cost()
|
||
|
4561.5
|
||
|
>>>
|
||
|
```
|
||
|
|
||
|
Notice that the name 'cost' is not defined in either `goog.__dict__` or `ibm.__dict__`. Instead, it is being supplied by the
|
||
|
class dictionary. Try this:
|
||
|
|
||
|
```python
|
||
|
>>> SimpleStock.__dict__['cost']
|
||
|
... look at output ...
|
||
|
>>>
|
||
|
```
|
||
|
|
||
|
Try calling the `cost()` method directly through the dictionary:
|
||
|
|
||
|
```python
|
||
|
>>> SimpleStock.__dict__['cost'](goog)
|
||
|
49010.00
|
||
|
>>> SimpleStock.__dict__['cost'](ibm)
|
||
|
4561.5
|
||
|
>>>
|
||
|
```
|
||
|
|
||
|
Notice how you are calling the function defined in the class definition and how the `self` argument
|
||
|
gets the instance.
|
||
|
|
||
|
If you add a new value to the class, it becomes a class variable that's visible to all instances. Try it:
|
||
|
|
||
|
```python
|
||
|
>>> SimpleStock.spam = 42
|
||
|
>>> ibm.spam
|
||
|
42
|
||
|
>>> goog.spam
|
||
|
42
|
||
|
>>>
|
||
|
```
|
||
|
|
||
|
Observe that `spam` is not part of the instance dictionary.
|
||
|
|
||
|
```python
|
||
|
>>> ibm.__dict__
|
||
|
... look at the output ...
|
||
|
>>>
|
||
|
```
|
||
|
|
||
|
Instead, it's part of the class dictionary:
|
||
|
|
||
|
```python
|
||
|
>>> SimpleStock.__dict__['spam']
|
||
|
42
|
||
|
>>>
|
||
|
```
|
||
|
|
||
|
Essentially this is all a class really is--it's a collection of values shared by instances.
|
||
|
|
||
|
|
||
|
\[ [Solution](soln4_1.md) | [Index](index.md) | [Exercise 3.8](ex3_8.md) | [Exercise 4.2](ex4_2.md) \]
|
||
|
|
||
|
----
|
||
|
`>>>` Advanced Python Mastery
|
||
|
`...` A course by [dabeaz](https://www.dabeaz.com)
|
||
|
`...` Copyright 2007-2023
|
||
|
|
||
|
. This work is licensed under a [Creative Commons Attribution-ShareAlike 4.0 International License](http://creativecommons.org/licenses/by-sa/4.0/)
|