(首页)开始编程之旅 翻译自Lee Harr的Start Programming

本文是使用pygsear+pygame作为开发环境,以初级用户角度来分步分阶段学习PYTHON基本概念,并以小游戏开发项目为具体案例,介绍的十分详细。编写风格清新朴实,没有象一般教科书那样枯燥,极其适合初级用户来激发兴趣时使用。

1. StartProgramming-2-5 类Classes

classes can also be loaded from modules.

类也能够被从组件中调用。

A class defines a type of object.

一个类定义了一个对象类型。

Penguin, for example, is a class in the penguin module which we have already used extensively. To make a new instance of a Penguin, we first import the class, and then call it:

比如,Penguin就是一个在penguin组件中我们早已经常用过的一个类。要产生一个新实例,我们要首先导入这个类,然后调用它:

   1 from penguin import Penguin
   2 pete = Penguin()

A class is sort of like a function which acts as a factory for creating objects. Each time you call the class, it returns an object of that class.

一个类类似于一个能够生产对象的工厂的函数。当你每次调用这个类,它都能返回一个这个类的对象。

1.1. class Ball球类

Classes define data and methods which describe the different objects you want to use in your programs.

类定义了你想在程序中描述不同对象的数据和方法。

Let's start out with a very basic object, a ball.

让我们以一个非常基本的对象开始,一个ball(球)。

   1 class Ball:
   2     def set_color(self, color):
   3         self.color = color
   4 
   5     def bounce(self):
   6         print 'boing!'

Put that code in to a file. Call it Ball.py

将这些代码放到一个文件中。文件名为Ball.py

To create a ball, simply call your new class:

要创建一个ball,简单的调用你的新类:

   1 import Ball
   2 rb = Ball.Ball()

Keep in mind that this is all very abstract at this point, and this code is not going to show you a picture of a ball. This is just the idea of a ball. It is more beautiful, really, if you think about it.

牢记这些,这个知识点非常的抽象,并且这些代码不会让你看到一个球的画面。这只是一个球的计划。它非常的漂亮,真实,如果你那样想它的话。

If you really need to see a ball right now, here is a red one I made with the GIMP:

如果你现在确实需要看到一个球,这里有一个我用GIMP画的红球。

1.2. reload重载

Notice that we did not import your new class directly. It is import Ball and not from Ball import Ball. This makes it easier to change your module and see the changes.

注意我们没有直接导入你的新类。是导入Ball组件而不是从组件Ball中导入Ball类。这可以让你容易的改变你的组件并且看到改变。

If you want to make a change to your class -- like if you made a typing error -- you can just do this:

如果你希望更改你的类——比如你输入错了——你可以这样做:

   1 reload(Ball)
   2 rb = Ball.Ball()

1.3. color颜色

The Ball class defines two methods: set_color() and bounce()

这个Ball类定义了两个方法:set_color() 和 bounce()

Methods are like functions, but they are bound to particular objects.

方法就像过程一样,但是方法绑定在特定的对象上。

Once you create a ball, you can change its color:

一旦你创建了一个球,你就能够改变它的颜色:

   1 rb.set_color('bright red')

Notice that with methods, unlike with functions, you do not pass in the first parameter (usually called self). The object itself is passed in automatically as the first parameter when the method is called from a class instance.

注意这是用方法,不等同于用函数,你不能使用第一个参数(通常叫做self)。当从类的实例中调用方法时,对象自身会自动被当作第一个参数来调用。

Also notice the difference between color and self.color in the set_color() method.

所以注意在方法set_color()中color和self.color的区别。

When you call rb.set_color('red') the variable self is bound to the same Ball instance that rb is bound to.

当你调用 rb.set_color('read') 时,变量self被绑定在同样是Ball的实例rb上。

At the same time, the variable color is bound to the string 'red'.

同时,变量color被绑定到字符串'red'上。

Then with the code self.color = color the data attribute self.color is bound to that same string.

然后随着代码self.color=color的运行,数据属性self.color绑定到相同的字符串上。

The set_color() method will create the attribute self.color if it does not exist, or if self.color already exists, it will just set it to the new value.

方法set_color()将会创建一个属性self.color如果它不存在的话,或者如果self.color已经存在,那就会为它设置新值。

You can see what color the ball is by examining the attribute:

你可以检查属性看看ball是什么颜色:

   1 rb.color

1.4. get and set获取和设置

It is a good idea to access data attributes through "getter" and "setter" methods, so we should create a get_color() method which just returns self.color

通过方法"getter"和"setter"访问数据属性是一种好方法,所以我们我们需要创建方法get_color()来返回self.color

Using methods to access your object attributes allows you to keep the interfaces to the attributes the same, even if later the underlying implementation changes.

通过方法访问你的对象变量使得你用相同的接口访问变量,即使后面用工具引发变化。

   1 class Ball:
   2     def set_color(self, color):
   3         self.color = color
   4 
   5     def get_color(self):
   6         return self.color
   7 
   8     def bounce(self):
   9         print 'boing!'

In other words, set_color() might have side effects other than just setting self.color -- it might check first to make sure that you do not try to set the color to orange, or you might decide later that the color would actually be better stored in a different way.

换句话说,set_color()能够比直接设置self.color多一些附加效果——它能够先检查确认你不想设置color为orange,或者你能够稍后决定从不同的途径为color设置一个更改好的值。

1.5. bounce弹起

The other method in this class so far is bounce(). You can make the ball bounce by calling that method:

到目前为止类的另外一个方法是bounce()。你可以调用那个方法让球跳起来:

   1 rb.bounce()
   2 rb.bounce()
   3 rb.bounce()

All bounce() does is print a message to the console.

所有的bounce()会打印一条信息到控制台上。

Using print statements like this can be a simple way to debug your class methods. You can print out various values at different times and see if they match up to what you think they should be.

像这样利用print(打印)语句能够简单的调试你的类组件。你可以在不同的时间打印出不同的变量值,并且观察他们是否符合你当初的设想。

Often you will get an error message or a weird value from the print, and you can start your investigation there.

在你得到一个错误的消息或是打印出一个怪异的变量时,你就可以从这开始你的调查了。

1.6. __init__

One problem with the Ball class the way we have the code now is that if you try to check the color before you set it, you will get an error:

用我们现在的Ball类代码时有一个问题,如果你尝试在设置color前察看它的值,这将发生错误:

   1 gb = Ball.Ball()
   2 gb.get_color()

To make sure that the Ball always has a color, we should include the special method init() to initialize the objects to a known state when they are created.

为保证Ball总是拥有一个color,我们需要包含一个特殊的方法 init() 当对象创建时能够预置对象到已知状态。

Adding init(), the class will now look like this:

添加 init(),这个类现在看起来像这样:

   1 class Ball:
   2     def __init__(self, color='white'):
   3         self.set_color(color)
   4 
   5     def set_color(self, color):
   6         self.color = color
   7 
   8     def get_color(self):
   9         return self.color
  10 
  11     def bounce(self):
  12         print 'boing!'

The init() method is called automatically when you instantiate your class, and it can take parameters like any other function.

当你实例化你的类时,方法 init() 被自动的调用,并且它能够像其他函数一样附带参数。

Remember that any time you make changes to your module you will need to either re-start the interpreter or else reload() the module.

记得任何时候,你改动了你的组件,只需要重新开始交互解释器或者reload()这个组件。

   1 reload(Ball)
   2 wb = Ball.Ball()

will create a ball with its color set to the default 'white', and

将会创建一个ball并且带有缺省值'white'(白)的color,并且

   1 yb = Ball.Ball('yellow')

will make a 'yellow' ball.

将会产生一个'yellow'(黄)球。

1.7. Inheritance继承

The real power of classes emerges when you understand inheritance.

当你明白继承时,类的真正能量才会浮现出来。

Inheritance means that a class can define a new object which is a type of another object.

继承的意思是一个类能够定义一个类似于其他对象的新对象。

For example, we might create a new object SuperBall which is a type of Ball:

例如,我们能够创建一个新对象SuperBall类似于Ball:

   1 class SuperBall(Ball):
   2     def __init__(self):
   3         Ball.__init__(self, 'swirled')
   4         print 'SuperBall created!'
   5 
   6     def bounce(self):
   7         print 'boing, boing, boing'
   8         self.superbounce()
   9 
  10     def superbounce(self):
  11         print 'BOING!'

1.8. Add, Override, Extend加入,替换,扩展

If SuperBall defined no methods at all, it would be just like Ball. What we want, though, is something that is like a Ball, but with some changes.

如果SuperBall没有定义任何方法,它就像一个Ball一样。可是我们想做什么,虽然,这有几分像一个Ball,但是也有一些改变。

One thing we can do is add completely new methods.

一件事是我们完整地添加了一个新方法。

The superbounce() method adds a capability which a normal Ball just does not have.

这个superbounce()方法添加了一种能力,这是普通的Ball类所没有的。

If your class defines a method which is also in its parent class, the new method will be called instead of the parent class method -- the new method overrides the parent method. In this case, The bounce() method is one which both Ball and SuperBall have.

如果你的类定义了一个在父类中已经存在的方法,新的方法将会代替父类的方法被调用——新的方法覆盖了父类的方法。这种情况下,bounce()是唯一一个Ball和SuperBall同时拥有的方法。

Calling bounce() on a SuperBall overrides the normal Ball.bounce(). In this case, it prints out a message, and then calls the superbounce() method too.

调用在SuperBall上调用bounce(),不理会普通的Ball.bounce()。在这种情况下,它打印出消息,然后再调用superbounce()。

Sometimes what you want is the parent class's behavior, plus something more.

有时你想父类有什么的表现,加上一些更多的。

The SuperBall.init() method starts out by calling Ball.init() to get the normal Ball initialization.

方法SuperBall.init()开始于调用Ball.init()的Ball的初始化。

This is a common idiom in subclasses, and you should probably do it just like this until you have a better understanding of how classes and inheritance work.

在子类中这是一种通用的方言,并且直到你更好的理解类和继承的工作方式之后也许你才会像这样来用。

Notice that since Ball.init() is called against the class Ball and not against an instance of class Ball you need to explicitly pass in the Ball instance (self) as the first parameter.

注意,自从Ball.init()再次被调用,类Ball便不再是一个类的实例,你需要清楚地通过Ball实例的第一个参数。(self)。

After that, SuperBall.init() also prints out an informative message. At this point, it could also set up any additional attributes which a SuperBall has, but which a Ball does not.

在那之后,SuperBall.init()也打印出一个消息信息。在这个时候,它同样能够设置任何SuperBall拥有的附加属性而在Ball中没有的。