42的练习
本办法在这章开始给我们普及概念了。
面向对象的编程,一定绕不开这几个概念:抽象、封装、类、实例、对象。
一句话可以概括下:对事物进行【抽象】,从而【封装】为【类】,由【类】可以生成【实例】或【对象】。
写成代码是什么 样 子
这个概念有点绕人,不过实话说,你只要在创建和使用 class 的时候操心一下就可以了。我来给你两个区分 Class 和 Object 的小技巧。
首先针对类和对象,你需要学会两个说法,“ is-a( 是啥 )” 和“ has-a( 有啥 )” 。“是啥”要用在谈论“两者以类的关系互相关联”的时候,而“有啥”要用在“两者无共同点,仅是互为参照”的时候。接下来,通读这段代码,将每一个注解为 ##?? 的位置标明他是“ is-a” 还是“ has-a” 的关系,并讲明白这个关系是什么。在代码的开始我还举了几个例子,所以你只要写剩下的就可以了。
记住,“是啥”指的是鱼和泥鳅的关系,而“有啥”指的是泥鳅和鳃的关系。
(译注:为了解释方便,译文使用了中文鱼名。原文使用的是“三文鱼 (salmon)” 和“大比目鱼(halibut)” ,名字也是英文常用人名。)
加分习题
研究一下为什么 Python 添加了这个奇怪的叫做 object 的 class ,它究竟有什么含义呢?
**这个是python独有的,开始设计语言时,没有考虑周全。有没有办法把 Class 当作 Object 使用呢?
**这个还真不清楚, 没完全理解在习题中为 animals 、 fish 、还有 people 添加一些函数,让它们做一些事情。看看当函数在Animal 这样的“基类 (base class)” 里和在 Dog 里有什么区别。
**找些别人的代码,理清里边的“是啥”和“有啥”的关系。
**是啥”指的是鱼和泥鳅的关系(从属),而“有啥”指的是泥鳅和鳃的关系(含有)使用列表和字典创建一些新的一对应多的“ has-many” 的关系。
你认为会有一种“ has-many” 的关系吗?阅读一下关于“多重继承 (multiple inheritance)” 的资料,然后尽量避免这种用法。
常见 问题回答
这些 ## ?? 注解是干嘛用的?
这些注解是供你填空的。你应该在对应的位置填入“ is-a” 、“ has-a” 的概念。重读这节习题,看看其它的注解,仔细理解一下我的意思。
这句 self.pet = None 有什么用?
确保类的 self.pet 属性被设置为 None 。
super(Employee, self).init(name) 是做什么用的?
这样你可以可靠地将父类的 init 方法运行起来。搜索“ python super” ,看看它的优缺点。
43的练习
代码
import random#引入随机
from urllib.request import urlopen #从urllib进口urlopen
import sys
WORD_URL = "http://learncodethehardway.org/words.txt"
WORDS = []
PHRASES = {
"class ###(###):":
"Make a class named ### that is-a ###.",
"class ###(object):\n\tdef __init__(self,***)":
"class ###has-a __init__ that takes self and *** paramaters.",#类# # # has-a __init__以自我和***参数。”,
"class ###(object):\n\tdef ***(self,@@@)":
"class ### has-a function named *** that takes self and @@@ paramaters.",#类# # # has-a函数命名为***,以自我和@ @ @参数。
"*** = ###()":
"Set *** to an instance of class ###.",#设置***一类的实例# # #
"***.###(@@@)":
"From *** get the *** function, and call it with paramaters self, @@@.",#从***的***功能,并调用它的参数自,@ @ @
"***.*** = '***'":
"From *** get the *** attribute and set it to '***'."#从***获取***属性并将其设置为**
}
# do they want to drill phrases first #他们想操练短语第一
PHRASES_FIRST = False
if len(sys.argv) == 2 and sys.argv[1] == "english":
PHRASES_FIRST = True
# load up the words from the website #把词从网站载入
for word in urlopen(WORD_URL).readlines():
WORDS.append(word.strip())
def convert(snippet, phrase):
class_names = [w.capitalize() for w in
random.sample(WORDS, snippet.count("###"))]
other_names = random.sample(WORDS, snippet.count('***'))
rssults = []
param_names = []
for i in range(0, snippet.count('@@@')):
param_count = random.randint(1,3)
param_names.append(', '.join(random.sample(WORDS, param_count)))
for sentence in snippet, phrase:#对于片段中的句子,短语
result = sentence[:]
# fake class names #假类名称
for word in class_names:
result = result.replace('###', word, 1)
# fake other names
for word in other_names:
result = result.replace('***', word, 1)
# fake parameter lists #伪造参数列表
for word in param_names:
result = result.replace('@@@', word, 1)
results.append(result)
return results
# keep going until they hit CTRL-D
try:
while True:
snippets = PHRASES.keys()
random.shuffle(snippets)
for snippet in snippets:
phrase = PHRASES[snippet]
question, answer = convert(snippet, phrase)
if PHRASE_FIRST:
question, answer = answer, question
print(question)
input("> ")
print("ANSWER: %s\n\n" % answer)
except EOFError:
print("\nBye")
没有运行出来,这个很模糊
ex44
隐 式继承(Implicit Inheritance )
首先我将向你展示当你在父类里定义了一个函数,但没有在子类中定义的例子,这时候会发生隐式继承。
class Parent(object):
def implicit(self):
print "PARENT implicit()"
class Child(Parent):
pass
dad = Parent()
son = Child()
dad.implicit()
son.implicit()
class Child: 中的 pass 是在 Python 中创建空的代码区块的方法。这样就创建了一个叫 Child 的
类,但没有在里边定义任何细节。在这里它将会从它的父类中继承所有的行为。运行起来就是这样:
PARENT implicit()
PARENT implicit()
就算我在第 16 行调用了 son.implicit() 而且就算 Child 中没有定义过 implicit 这个函数,这
个函数依然可以工作,而且和在父类 Parent 中定义的行为一样。这就说明,如果你将函数放到基类中
(也就是这里的 Parent ),那么所有的子类(也就是 Child 这样的类)将会自动获得这些函数功能。
如果你需要很多类的时候,这样可以让你避免重复写很多代码。
显 式 覆 写(Explicit Override )
有时候你需要让子类里的函数有一个不同的行为,这种情况下隐式继承是做不到的,而你需要覆写子类
中的函数,从而实现它的新功能。你只要在子类 Child 中定义一个相同名称的函数就可以了,如下所示:
class Parent(object):
def override(self):
print "PARENT override()"
class Child(Parent):
def override(self):
print "CHILD override()"
dad = Parent()
son = Child()
dad.override()
son.override()
这里我在两个类中都定义了一个叫 override 的函数,我们看看运行时会出现什么情况。
PARENT override()
CHILD override()
如你所见,运行到第 14 行时,这里执行的是 Parent.override ,因为 dad 这个变量是定义在 Parent
里的。不过到了第 15 行打印出来的却是 Child.override 里的信息,因为 son 是 Child 的一个实例,
而子类中新定义的函数在这里取代了父类里的函数。
现在来休息一下并巩固一下这两个概念,然后我们接着进行。
super() 和 init 搭 配 使用
最常见的 super() 的用法是在基类的 init 函数中使用。通常这也是唯一可以进行这种操作的地方,
在这里你在子类里做了一些事情,然后完成对父类的初始化。这里是一个在 Child 中完成上述行为的例
子:
class Child(Parent):
def init(self, stuff):
self.stuff = stuff
super(Child, self).init()
这和上面的 Child.altered 差别不大,只不过我在 init 里边先设了个变量,然后才用
Parent.init 初始化了 Parent
45
这个,无从下手,捉急!
7月30日听课
split函数
昨晚听,其实没太明白,今天百度补充。
Python split()方法
Python 字符串
描述
Python split()通过指定分隔符对字符串进行切片,如果参数num 有指定值,则仅分隔 num 个子字符串
语法
split()方法语法:
str.split(str="", num=string.count(str)).
参数
str -- 分隔符,默认为所有的空字符,包括空格、换行(\n)、制表符(\t)等。
num -- 分割次数。
返回值
返回分割后的字符串列表。
实例
以下实例展示了split()函数的使用方法:
!/usr/bin/pythonstr = "Line1-abcdef \nLine2-abc \nLine4-abcd";print str.split( );print str.split(' ', 1 );
以上实例输出结果如下:
['Line1-abcdef', 'Line2-abc', 'Line4-abcd']['Line1-abcdef', '\nLine2-abc \nLine4-abcd']