Movatterモバイル変換


[0]ホーム

URL:


Jump to content
WikibooksThe Free Textbook Project
Search

Think Python/Classes and objects

From Wikibooks, open books for an open world
<Think Python
Think Python
A Wikibookian has nominated this page for cleanup because:
Copy editing needed
You canhelp make it better. Please review anyrelevant discussion.

User-defined types

[edit |edit source]

We have used many of Python’s built-in types; now we are goingto define a new type. As an example, we will create a typecalledPoint that represents a point in two-dimensionalspace.

In mathematical notation, points are often written inparentheses with a comma separating the coordinates. For example,(0, 0) represents the origin, and (x,y) represents thepointx units to the right andy units up from the origin.

There are several ways we might represent points in Python:

  • We could store the coordinates separately in two variables,x andy.
  • We could store the coordinates as elements in a list or tuple.
  • We could create a new type to represent points as objects.

Creating a new typeis (a little) more complicated than the other options, butit has advantages that will be apparent soon.

A user-defined type is also called aclass.A class definition looks like this:

classPoint(object):"""represents a point in 2-D space"""

This header indicates that the new class is aPoint,which is a kind ofobject, which is a built-intype.

The body is a docstring that explains what the class is for.You can define variables and functions inside a class definition,but we will get back to that later.

Defining a class namedPoint creates a class object.

>>>printPoint&lt;class'__main__.Point'>

BecausePoint is defined at the top level, its “fullname” is__main__.Point.

The class object is like a factory for creating objects. To create aPoint, you callPoint as if it were a function.

>>>blank=Point()>>>printblank&lt;__main__.Pointinstanceat0xb7e9d3ac>

The return value is a reference to a Point object, which weassign toblank. Creating a new object is calledinstantiation, and the object is aninstance ofthe class.

When you print an instance, Python tells you what class itbelongs to and where it is stored in memory (the prefix0x means that the following number is in hexadecimal).

Attributes

[edit |edit source]

You can assign values to an instance using dot notation:

>>>blank.x=3.0>>>blank.y=4.0

This syntax is similar to the syntax for selecting a variable from amodule, such asmath.pi orstring.whitespace. In this case,though, we are assigning values to named elements of an object.These elements are calledattributes.

As a noun, “AT-trib-ute” is pronounced with emphasis on the firstsyllable, as opposed to “a-TRIB-ute,” which is a verb.

The following diagram shows the result of these assignments.A state diagram that shows an object and its attributes iscalled anobject diagram:

File:Book022.png

The variableblank refers to a Point object, whichcontains two attributes. Each attribute refers to afloating-point number.

You can read the value of an attribute using the same syntax:

>>>printblank.y4.0>>>x=blank.x>>>printx3.0

The expressionblank.x means, “Go to the objectblankrefers to and get the value ofx.” In this case, we assign thatvalue to a variable namedx. There is no conflict betweenthe variablex and the attributex.

You can use dot notation as part of any expression. For example:

>>>print'(%g,%g)'%(blank.x,blank.y)(3.0,4.0)>>>distance=math.sqrt(blank.x**2+blank.y**2)>>>printdistance5.0

You can pass an instance as an argument in the usual way.For example:

defprint_point(p):print'(%g,%g)'%(p.x,p.y)

print_point takes a point as an argument and displays it inmathematical notation. To invoke it, you can passblank asan argument:

>>>print_point(blank)(3.0,4.0)

Inside the function,p is an alias forblank, so ifthe function modifiesp,blank changes.

Exercise 1

[edit |edit source]

Write a function called 'distance' that it takes two Pointsas arguments and returns the distance between them.

Rectangles

[edit |edit source]

Sometimes it is obvious what the attributes of an object should be,but other times you have to make decisions. For example, imagine youare designing a class to represent rectangles. What attributes wouldyou use to specify the location and size of a rectangle? You canignore angle; to keep things simple, assume that the rectangle iseither vertical or horizontal.

There are at least two possibilities:

  • You could specify one corner of the rectangle (or the center), the width, and the height.
  • You could specify two opposing corners.

At this point it is hard to say whether either is better thanthe other, so we’ll implement the first one, just as an example.

Here is the class definition:

classRectangle(object):"""represent a rectangle.       attributes: width, height, corner.    """

The docstring lists the attributes:width andheight are numbers;corner is a Point object thatspecifies the lower-left corner.

To represent a rectangle, you have to instantiate a Rectangleobject and assign values to the attributes:

box=Rectangle()box.width=100.0box.height=200.0box.corner=Point()box.corner.x=0.0box.corner.y=0.0

The expressionbox.corner.x means,“Go to the objectbox refers to and select the attribute namedcorner; then go to that object and select the attribute namedx.”

The figure shows the state of this object:

File:Book023.pngAn object that is an attribute of another object isembedded.

Instances as return values

[edit |edit source]

Functions can return instances. For example,find_centertakes aRectangle as an argument and returns aPointthat contains the coordinates of the center of theRectangle:

deffind_center(box):p=Point()p.x=box.corner.x+box.width/2.0p.y=box.corner.y+box.height/2.0returnp

Here is an example that passesbox as an argument and assignsthe resulting Point tocenter:

>>>center=find_center(box)>>>print_point(center)(50.0,100.0)

Objects are mutable

[edit |edit source]

You can change the state of an object by making an assignment to one ofits attributes. For example, to change the size of a rectanglewithout changing its position, you can modify the values ofwidth andheight:

box.width=box.width+50box.height=box.height+100

You can also write functions that modify objects. For example,grow_rectangle takes a Rectangle object and two numbers,dwidth anddheight, and adds the numbers to thewidth and height of the rectangle:

defgrow_rectangle(rect,dwidth,dheight):rect.width+=dwidthrect.height+=dheight

Here is an example that demonstrates the effect:

>>>printbox.width100.0>>>printbox.height200.0>>>grow_rectangle(box,50,100)>>>printbox.width150.0>>>printbox.height300.0

Inside the function,rect is analias forbox, so if the function modifiesrect,box changes.

Exercise 2

[edit |edit source]

Write a function namedmove_rectangle that takes a Rectangle and two numbers nameddx anddy. It should change the location of the rectangle by addingdx to thex coordinate ofcorner and addingdy to they coordinate ofcorner.

Copying

[edit |edit source]

Aliasing can make a program difficult to read because changesin one place might have unexpected effects in another place.It is hard to keep track of all the variables that might referto a given object.

Copying an object is often an alternative to aliasing.Thecopy module contains a function calledcopy thatcan duplicate any object:

>>>p1=Point()>>>p1.x=3.0>>>p1.y=4.0>>>importcopy>>>p2=copy.copy(p1)

p1 andp2 contain the same data, but they arenot the same Point.

>>>print_point(p1)(3.0,4.0)>>>print_point(p2)(3.0,4.0)>>>p1isp2False>>>p1==p2False

Theis operator indicates thatp1 andp2 are not thesame object, which is what we expected. But you might have expected== to yieldTrue because these points contain the samedata. In that case, you will be disappointed to learn that forinstances, the default behavior of the== operator is the sameas theis operator; it checks object identity, not objectequivalence. This behavior can be changed—we’ll see how later.

If you usecopy.copy to duplicate a Rectangle, you will findthat it copies the Rectangle object but not the embedded Point.

>>>box2=copy.copy(box)>>>box2isboxFalse>>>box2.cornerisbox.cornerTrue

Here is what the object diagram looks like:

<IMG SRC="book024.png">

This operation is called ashallow copy because it copies theobject and any references it contains, but not the embedded objects.

For most applications, this is not what you want. In this example,invokinggrow_rectangle on one of the Rectangles would notaffect the other, but invokingmove_rectangle on either wouldaffect both! This behavior is confusing and error-prone.

Fortunately, thecopy module contains a method nameddeepcopy that copies not only the object but also the objects it refers to, and the objectsthey refer to,and so on.You will not be surprised to learn that this operation iscalled adeep copy.

>>>box3=copy.deepcopy(box)>>>box3isboxFalse>>>box3.cornerisbox.cornerFalse

box3 andbox are completely separate objects.

Exercise 3

[edit |edit source]

Write a version ofmove_rectangle that creates and returns a new Rectangle instead of modifying the old one.

Debugging

[edit |edit source]

When you start working with objects, you are likely to encountersome new exceptions. If you try to access an attributethat doesn’t exist, you get anAttributeError:

>>>p=Point()>>>printp.zAttributeError:Pointinstancehasnoattribute'z'

If you are not sure what type an object is, you can ask:

>>>type(p)&lt;type'__main__.Point'>

If you are not sure whether an object has a particular attribute,you can use the built-in functionhasattr:

>>>hasattr(p,'x')True>>>hasattr(p,'z')False

The first argument can be any object; the second argument is astring that contains the name of the attribute.

Glossary

[edit |edit source]
class:
A user-defined type. A class definition creates a newclass object.
class object:
An object that contains information about auser-defined type. The class object can be used to create instancesof the type.
instance:
An object that belongs to a class.
attribute:
One of the named values associated with an object.
embedded (object):
An object that is stored as an attributeof another object.
shallow copy:
To copy the contents of an object, includingany references to embedded objects;implemented by thecopy function in thecopy module.
deep copy:
To copy the contents of an object as well as anyembedded objects, and any objects embedded in them, and so on;implemented by thedeepcopy function in thecopy module.
object diagram:
A diagram that shows objects, theirattributes, and the values of the attributes.

Exercises

[edit |edit source]

Exercise 4

[edit |edit source]

World.py, which is part of Swampy (see Chapter '4'), contains a class definition for a user-defined type calledWorld. If you run this code:fromWorldimport*world=World()wait_for_user()A window should appear with a title bar and an empty square. In this exercise we will use this window to draw Points, Rectangles and other shapes. Add the following lines beforewait_for_user and run the program again

''canvas=world.ca(width=500,height=500,background='white')bbox=[[-150,-100],[150,100]]canvas.rectangle(bbox,outline='black',width=2,fill='green4')

You should see a green rectangle with a black outline. The first line creates a Canvas, which appears in the window as a white square. The Canvas object provides methods likerectangle for drawing various shapes.

bbox is a list of lists that represents the “bounding box” of the rectangle. The first pair of coordinates is the lower-left corner of the rectangle; the second pair is the upper-right corner.

You can draw a circle like this:

canvas.circle([-25,0],70,outline=None,fill='red')

The first parameter is the coordinate pair for the center of the circle; the second parameter is the radius.

If you add this line to the program, the result should resemble the national flag of Bangladesh (seewikipedia.org/wiki/Gallery_of_sovereign-state_flags).

  • Write a function calleddraw_rectangle that takes a Canvas and a Rectangle as arguments and draws a representation of the Rectangle on the Canvas.
  • Add an attribute namedcolor to your Rectangle objects and modifydraw_rectangle so that it uses the color attribute as the fill color.
  • Write a function calleddraw_point that takes a Canvas and a Point as arguments and draws a representation of the Point on the Canvas.
  • Define a new class called Circle with appropriate attributes and instantiate a few Circle objects. Write a function calleddraw_circle that draws circles on the canvas.
points=[[-150,-100],[150,100],[150,-100]]canvas.polygon(points,fill='blue')

I have written a small program that lists the available colors; you can download it fromthinkpython.com/code/color_list.py.

Retrieved from "https://en.wikibooks.org/w/index.php?title=Think_Python/Classes_and_objects&oldid=4410089"
Category:
Hidden categories:

[8]ページ先頭

©2009-2025 Movatter.jp