Python语言的面相对象编程方式初步学习


Posted in Python onMarch 12, 2016

词语练习

  • class:告诉python创造一个新的东西
  • object:两个意思:最基本的东西和任何实例化的东西。
  • instance:创建一个类得到的东西。
  • def:在类中创建一个函数。
  • self:在类里面的函数中使用,是实例和object能访问的变量。
  • inheritance:继承,一个类可以继承另一个类,像你和你的父母。
  • composition:一个类可以包含另外一个类,就像汽车包含轮胎。
  • attribute:一个属性类,通常包括变量。
  • is-a:表示继承关系
  • has-a:包含关系

通过卡片记忆这些词语,单独的词语通常没什么意义,不过我还是要先知道它们的存在。

短语练习

  • class x(y):创建一个类x,它继承了y类。
  • class x(object):def __init__(self,j):x类包含__init__函数,函数中有self和j参数。
  • class x(object):def m(self,j):类x包含m函数,m函数有self和j两个参数。
  • foo = x():设置foo为类x的实例化。
  • foo.m(j):通过foo调用m函数,参数是self和j。
  • foo.k = q:通过foo给k属性赋值为q。

上面那些x,y,m,q等等都是可以变的。

一个阅读测试
这是一个简单的脚本可以让你用来做练习,它只做一件事,就是使用一个urllib的库去下载一个单词列表。我们把下面的代码写到opp_test.py文件中。

import random 
from urllib import 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 *** parameters.", 
  "class ###(object):\n\tdef ***(self, @@@)": "class ### has-a function named *** that takes self and @@@ parameters.", 
  "*** = ###()" : "Set *** to an instance of class ###.", 
  "***.***(@@@)" : "From *** get the *** function, and call it with parameters self, @@@.", 
  "***.*** = '***'": "From *** get the *** attribute and set it to '***'." 
} 
 
 
PHRASE_FIRST = False 
if len(sys.argv) == 2 and sys.argv[1] == "english": 
  PHRASE_FIRST = True 
 
 
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("***")) 
  results = [] 
  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 
 
 
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 
 
 
      raw_input("> ") 
      print "ANSWER: %s\n\n" % answer 
except EOFError: 
  print "\nBye"

运行这个例子,它会尽可能准确的回答问题。

root@he-desktop:~/mystuff# python oop_test.py
class Deer(object):
def __init__(self, connection)
> 
ANSWER: class Deer has-a __init__ that takes self and connection parameters.


class Cause(Agreement):
> 
ANSWER: Make a class named Cause that is-a Agreement.


animal.driving(arch)
> 
ANSWER: From animal get the driving function, and call it with parameters self, arch.


cat = Aftermath()
> 
ANSWER: Set cat to an instance of class Aftermath.


cork.card = 'attempt'
>

类和对象
类就像模块
你可以认为模块就是一个特殊的字典,它可以保存python代码,通过 . 号调用。python还有一个类似实现这种目的的结构,叫做类。一个类包含了很多函数和数据,可以通过 . 去访问它们。

如果我要写一个类似mystuff的类,就像这样:

class mystuff(object):
  def __int__(self):
    self.tangerine = "Hello"

  def apple(self):
    print "apple"

和模块比有点复杂,不过你可以认为它就是一个迷你模块。让人疑惑的是__init__()函数和self.tangerine设置tangerine变量的值。

这里是用类替代模块的原因:你可以在一个程序中使用同一个类很多次,它们不相互影响,但是一个程序中只能导入一个模块。

理解这些之前,你必须理解什么是对象。

对象就像迷你的导入
如果类像模块,那么类也会有类型模块的导入功能。就是实例化,如果你实例化一个类,得到的就是一个对象。

使用类的方法类似调用函数,像这样:

thing = mystuff()
thing.apple()
print thing.tangerine

第一步是实例化,然后调用它的函数,我们通过上面的代码分析一下python是怎么按照顺序执行的:

  • python寻找Myclass,看看你是不是定义了这个类。
  • python为你在类里面定义的函数创建一个空对象。
  • 如果类中有魔术方法__init__,那么就会使用这个函数初始化你的空对象。
  • 在__init__方法中有一个额外的变量self,这就是python为我们创建的空对象,你可以给这个变量赋值。
  • 这样的话,我给 thing.tangerine赋了句歌词,并且初始化了这个对象。
  • 那么现在python就可以把这个刚完成的对象赋给一个变量thing了。

这就是我们为什么像调用函数一样导入一个类。

记住,我给出的不是一个非常准确类的工作方法,仅仅是为了你能通过模块而更好的理解类。事实是,类和对象和模块不是一个东西,老实说的话,就像下面这样:

  • 类就像一个蓝图,定义用来创建一个迷你模块。
  • 实例化就是导入的同时使用这个迷你模块。
  • 创建出来的迷你模块就是对象,赋给一个变量,然后通过这个变量工作。
  • 虽然从模块过渡到类和对象比较难,不过也只有这个方法比较好理解。

从东西中取出东西
现在有三种方法:

# 字典
mystuff['apple']

# 模块
mystuff.apple()
print mystuff.tangerine

# 类
thing = mystuff()
thing.apple()
print thing.tangerine

第一个类
你可能还有很多疑问,不要着急,暂时先放放这些疑问,下一个练习我们学校面向对象的知识,下面我们先了解一下类的写法,为下一练习做准备。

class Song(object): 
 
 
  def __init__(self, lyrics): 
    self.lyrics = lyrics 
 
 
  def sing_me_a_song(self): 
    for line in self.lyrics: 
      print line 
 
 
happy_bday = Song(["Happy birthday to you", 
  "I don't want to get sued", 
  "So I'll stop right there"]) 
 
 
bulls_on_parade = Song(["they relly around the family", 
  "With pockets full of shells"]) 
 
 
happy_bday.sing_me_a_song() 
bulls_on_parade.sing_me_a_song()

运行结果

Happy birthday to you
I don't want to get sued
So I'll stop right there
they relly around the family
With pockets full of shells

继承

你必须明白一个重要的概念,就是类和对象的不同。问题是,类和对象没有真正的区别,他们在不同的时间是相同的东西,我将用禅语解释他们:

鱼和鲑鱼的区别是什么呢?

这个问题是不是很晕?坐下来想想,我的意思是,鱼和鲑鱼是不同的,但是又是相同的,对吗?鲑鱼是鱼的一种,所以没有什么不同。但是,鲑鱼是鱼的一个分类,并且和其他鱼的分类不同。所以鲑鱼和鱼既相同又不同。

我们不需要真的知道鲑鱼和鱼的区别,只要知道鲑鱼是鱼的一种,而鱼还有其他很多种类就可以了。

现在让我们更近一步,假设你有三条鲑鱼,并且给他们取名为Frank,Joe,Mary,那么思考这个问题:

Mary和鲑鱼有什么区别?

这也是一个奇怪的问题,但是比上个问题简单一点。你知道Mary是一条鲑鱼,她是鲑鱼的一个实例。Joe和Frank也是一个鲑鱼的实例。但是我们说的实例是什么意思呢?意思就是他们创建于鲑鱼,然后现在是一个真实东西,鲑鱼就像他们的属性。

现在记住了:鱼是一个类,鲑鱼也是一个类,Mary是一个对象。好好想想,你能明白过来的。

鱼是一个类,就是说鱼不是一个真正存在的东西,但是我们通过它的相似的特点去实例化一些东西,比如,有鳞片,有鳃,生活在水里等,那么这个东西就是一条鱼。

然后一个专家过来说:”这些鱼是鲑鱼。“ 这个专家给这些鱼定义一个新类”鲑鱼“,这个类有一些特别的属性,长鼻子,红色的肉,生活在海里,味道美味,好吧,它就是鲑鱼。

最后,一个厨师过来对专家说:不,你看到的鲑鱼在这里,我叫它Mary,我要把她做成一道美味。”现在,你就有了一个鲑鱼的实例(也是鱼的实例)叫做Mary,我们叫这个实例是一个对象。

现在我们得出:Mary是一种鲑鱼,鲑鱼是一种鱼。对象是一个类,而类又是另外一个类。

写成代码是这样的
这个概念有些奇怪,不过你只要在创建和使用类的时候注意一下就可以了,我来告诉你两个区别类和对象的方法。

第一,你要学习两个短语“is-a”和“has-a”。is-a就是对象和类之间通过类的关系想关联,has-a是对象和类相关联是因为他们彼此参考。

下面用这两个关系标注下面的程序,记住,鱼和鲑鱼是is-a的关系,鲑鱼和鳃是has-a的关系。

## Animal is-a object (yes, sort of confusing) look at the extra credit 
class Animal(object): 
  pass 
 
## ?? is-a 
class Dog(Animal): 
 
  def __init__(self, name): 
    ## ?? has-a 
    self.name = name 
 
## ?? is-a  
class Cat(Animal): 
 
  def __init__(self, name): 
    ## ?? has-a 
    self.name = name 
 
## ?? is-a 
class Person(object): 
 
  def __init__(self, name): 
    ## ?? has-a 
    self.name = name 
 
    ## Person has-a pet of some kind 
    self.pet = None 
 
## ?? has-a 
class Employee(Person): 
 
  def __init__(self, name, salary): 
    ## ?? hmm what is this strange magic? 
    super(Employee, self).__init__(name) 
    ## ?? has-a 
    self.salary = salary 
 
## ?? is-a 
class Fish(object): 
  pass 
 
## ?? is-a 
class Salmon(Fish): 
  pass 
 
## ?? is-a 
class Halibut(Fish): 
  pass 
 
 
## rover is-a Dog 
rover = Dog("Rover") 
 
## ?? is-a 
satan = Cat("Satan") 
 
## ?? is-a 
mary = Person("Mary") 
 
## ?? is-a 
mary.pet = satan 
 
## ?? is-a 
frank = Employee("Frank", 120000) 
 
## ?? is-a 
frank.pet = rover 
 
## ?? is-a 
flipper = Fish() 
 
## ?? is-a 
crouse = Salmon() 
 
## ?? is-a 
harry = Halibut()

关于 class Name(object)
我让你使用class Name(object)但是没有告诉你为什么。因为怕你混淆,并且不知道怎么学习。

最初python设计类的时候有很多问题,等发现的时候已经太晚了,它们必须要支持这种错误的类。为了修正这个问题,他们必须设计一个新类方便旧的类能继续使用,而且新的类也能正确使用。

这就是为什么类要继承object类,是不是有点混乱,这里的object指的是类,而不是字面上的解释为对象。

你就记住,一个新的顶级类必须继承object就好了。不要太多纠结于字面上的理解,我们要留着思考更加重要的事情。

Python 相关文章推荐
python sqlobject(mysql)中文乱码解决方法
Nov 14 Python
Python内置的字符串处理函数整理
Jan 29 Python
Python用zip函数同时遍历多个迭代器示例详解
Nov 14 Python
基于Python3 逗号代码 和 字符图网格(详谈)
Jun 22 Python
详解python使用Nginx和uWSGI来运行Python应用
Jan 09 Python
简单了解django orm中介模型
Jul 30 Python
python 实现将小图片放到另一个较大的白色或黑色背景图片中
Dec 12 Python
Python使用Tkinter实现滚动抽奖器效果
Jan 06 Python
python3 实现口罩抽签的功能
Mar 11 Python
pytorch实现查看当前学习率
Jun 24 Python
python获取整个网页源码的方法
Aug 03 Python
详解Python中的进程和线程
Jun 23 Python
举例讲解Python中的list列表数据结构用法
Mar 12 #Python
Python中的if、else、elif语句用法简明讲解
Mar 11 #Python
使用Python读写文本文件及编写简单的文本编辑器
Mar 11 #Python
简单讲解Python中的数字类型及基本的数学计算
Mar 11 #Python
详解Python中的变量及其命名和打印
Mar 11 #Python
Python基本语法经典教程
Mar 11 #Python
Python使用PIL库实现验证码图片的方法
Mar 11 #Python
You might like
在PHP中使用XML
2006/10/09 PHP
分享一则PHP定义函数代码
2015/02/26 PHP
PHP书写格式详解(必看)
2016/05/23 PHP
PHP使用两个栈实现队列功能的方法
2018/01/15 PHP
用javascript来实现动画导航效果的代码
2007/12/16 Javascript
js正则表达式中exec用法实例
2015/07/23 Javascript
JavaScript 拖拽实例代码
2016/09/21 Javascript
JavaScript自动点击链接 防止绕过浏览器访问的方法
2017/01/19 Javascript
jQuery实现用户输入自动完成功能
2017/02/13 Javascript
基于Nodejs利用socket.io实现多人聊天室
2017/02/22 NodeJs
jQuery使用正则验证15/18身份证的方法示例
2017/04/27 jQuery
利用Ionic2 + angular4实现一个地区选择组件
2017/07/27 Javascript
浅谈箭头函数写法在ReactJs中的使用
2017/08/22 Javascript
JS实现简易换图时钟功能分析
2018/01/04 Javascript
JS实现的RC4加密算法示例
2018/08/16 Javascript
layui监听工具栏的实例(操作列表按钮)
2019/09/10 Javascript
[03:28]2014DOTA2国际邀请赛 走近EG战队天才中单Arteezy
2014/07/12 DOTA
[15:20]DOTA2亚洲邀请赛总决赛开幕式表演:羽泉献唱
2017/04/05 DOTA
[55:48]VGJ.S vs TNC Supermajor 败者组 BO3 第二场 6.6
2018/06/07 DOTA
Django实现分页功能
2018/07/02 Python
django项目搭建与Session使用详解
2018/10/10 Python
Python对象中__del__方法起作用的条件详解
2018/11/01 Python
python退出命令是什么?详解python退出方法
2018/12/10 Python
强悍的Python读取大文件的解决方案
2019/02/16 Python
详解Python3 中的字符串格式化语法
2020/01/15 Python
实例讲解Python 迭代器与生成器
2020/07/08 Python
Python 实现键盘鼠标按键模拟
2020/11/18 Python
澳大利亚波西米亚风情网上商店:Czarina
2019/03/18 全球购物
保加利亚服装和鞋类购物网站:Bibloo.bg
2020/11/08 全球购物
Python里面如何实现tuple和list的转换
2012/06/13 面试题
大四学生思想汇报
2014/01/13 职场文书
会计顶岗实习心得
2014/01/25 职场文书
在校大学生的职业生涯规划书
2014/03/14 职场文书
英语专业毕业生求职信
2014/05/24 职场文书
深入理解java.lang.String类的不可变性
2021/06/27 Java/Android
Java 超详细讲解十大排序算法面试无忧
2022/04/08 Java/Android