虽说将函数放到字典里是很有趣的一件事情,你应该也会想到“如果 Python 能自动为你做这件事情该多好”。事实上也的确有,那就是 class 这个关键字。你可以使用 class 创建更棒的“函数字典”,比你在上节练习中做的强大多了。Class(类)有着各种各样强大的功能和用法,但本书不会深入讲这些内容,在这里,你只要你学会把它们当作高级的“函数字典”使用就可以了。
用到“class”的编程语言被称作“Object Oriented Programming(面向对象编程)”语言。这是一种传统的编程方式,你需要做出“东西”来,然后你“告诉”这些东西去完成它们的工作。类似的事情你其实已经做过不少了,只不过还没有意识到而已。记得你做过的这个吧:
stuff = ['Test', 'This', 'Out']
print ' '.join(stuff)
其实你这里已经使用了 class。``stuff`` 这个变量其实是一个 list class (列表类)。而 ' '.join(stuff) 里调用函数 join 的字符串 ' ' (就是一个空格)也是一个 class —— 它是一个 string class (字符串类)。到处都是 class!
还有一个概念是 object(物件),不过我们暂且不提。当你创建过几个 class 后就会学到了。你怎样创建 class 呢?和你创建 ROOMS 的方法差不多,但其实更简单:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | class TheThing(object):
def __init__(self):
self.number = 0
def some_function(self):
print "I got called."
def add_me_up(self, more):
self.number += more
return self.number
# two different things
a = TheThing()
b = TheThing()
a.some_function()
b.some_function()
print a.add_me_up(20)
print b.add_me_up(30)
print a.number
print b.number
# Study this. This is how you pass a variable
# from one class to another. You will need this.
class TheMultiplier(object):
def __init__(self, base):
self.base = base
def do_it(self, m):
return m * self.base
x = TheMultiplier(a.number)
print x.do_it(b.number)
|
Warning
嗯,你开始看到 Python 的“疣子”了。Python 是一门比较旧的语言,其中包含很多丑陋的设计决定。为了将这些丑陋设计掩盖过去,他们就做了一些新的丑陋设计,然后告诉人们让他们习惯这些新的坏设计。``class TheThing(object)`` 就是其中一个例子。这里我就不展开讲了,不过你也不必操心为什么你的 class 要在后面添一个(object) ,只要跟着这样做就可以了,否则将来总有一天别的 Python 程序员会吼你让你这样做。后面我们再讲为什么。
你看到参数里的 self 了吧?你知道它是什么东西吗?对了,它就是 Python 创建的额外的一个参数,有了它你才能实现 a.some_function()` 这种用法,这时它就会把\ 前者翻译成 ``some_function(a) 执行下去。为什么用 self 呢?因为你的函数并不知道你的这个“实例”是来自叫 TheThing 或者别的名字的 class。所以你只要使用一个通用的名字 self 。这样你写出来的函数就会在任何情况下都能正常工作。
其实你可以使用 self 以外的别的字眼,不过如果你这样做的话,你就会成为所有Python 程序员的众之矢的,所以还是随大流的好。只有变态才会在这里乱改,我教你的没错。对以后会读到你的代码的人好点儿,因为你现在的代码10年以后所有的代码都会是一团糟。
接下来,看到 __init__ 函数了吗?这就是你为 Python class 设置内部变量的方式。你可以使用 . 将它们设置到 self 上面。另外看到我们使用了 add_me_up() 为你创建的 self.number 加值。后面你可以看到我们怎样可以使用这种方法为数字加值,然后打印出来。
接着我创建了另一个叫 TheMutiplier 的 class,它的功能是做乘法。这样的 class 其实是非常没必要的,不过它向你展示了如何将变量和状态从一个 class 传递到另一个 class。在这里我使用了 TheMultiplier.__init__ 来从 a.number 来获取基本数值,我还将 b.number 传递到 TheMultiplier.do_it 以供调用。好好研究一下,你需要相关的知识来完成后面的加分习题。
Class 是很强大的东西,你应该好好读读相关的东西。尽可能多找些东西读并且多多实验。你其实知道它们该怎么用,只要试试就知道了。其实我马上就要去练吉他了,所以我不会让你写练习了。你将使用 class 写一个练习。
接下来我们将把习题41的内容重写,不过这回我们将使用 class:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 | ## Animal is-a object (yes, sort of confusing) look at the extra credit
class Animal(object):
pass
## ??
class Dog(Animal):
def __init__(self, name):
## ??
self.name = name
## ??
class Cat(Animal):
def __init__(self, name):
## ??
self.name = name
## ??
class Person(object):
def __init__(self, name):
## ??
self.name = name
## Person has-a pet of some kind
self.pet = None
## ??
class Employee(Person):
def __init__(self, name, salary):
## ?? hmm what is this strange magic?
super(Employee, self).__init__(name)
## ??
self.salary = salary
## ??
class Fish(object):
pass
## ??
class Salmon(Fish):
pass
## ??
class Halibut(Fish):
pass
## rover is-a Dog
rover = Dog("Rover")
## ??
satan = Cat("Satan")
## ??
mary = Person("Mary")
## ??
mary.pet = satan
## ??
frank = Employee("Frank", 120000)
## ??
frank.pet = rover
## ??
flipper = Fish()
## ??
crouse = Salmon()
## ??
harry = Halibut()
|
这个版本的游戏和你的上一版效果应该是一样的,其实有些代码都几乎一样。比较一下两版代码,弄懂其中不同的地方,重点需要理解这些东西:
result = sentence[:] 是做什么的?
这是 Python 中复制 list 的方法。你用了列表切片(list slice)的语法 [:] ,其效果是将列表从头到尾每个元素切片出来并创建了一个新列表。
这脚本好难跑起来啊!
到现在为止你应该有能力写脚本并让脚本运行起来了。偶尔你会碰到点小困难,但其实也没什么复杂的。用你学过的各种技巧去克服困难吧。