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多线程学习资料
Dec 19 Python
python中查看变量内存地址的方法
May 05 Python
浅谈Python中copy()方法的使用
May 21 Python
Python numpy 点数组去重的实例
Apr 18 Python
python和mysql交互操作实例详解【基于pymysql库】
Jun 04 Python
python 列表推导式使用详解
Aug 29 Python
使用python获取邮箱邮件的设置方法
Sep 20 Python
Python实现企业微信机器人每天定时发消息实例
Feb 25 Python
Python爬虫实例——scrapy框架爬取拉勾网招聘信息
Jul 14 Python
python在协程中增加任务实例操作
Feb 28 Python
Python多线程 Queue 模块常见用法
Jul 04 Python
Python获取江苏疫情实时数据及爬虫分析
Aug 02 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多用户计数器代码
2007/03/11 PHP
PHP Google的translate API代码
2008/12/10 PHP
php实现博客,论坛图片防盗链的方法
2016/10/15 PHP
Yii2实现增删改查后留在当前页的方法详解
2017/01/13 PHP
TP5(thinkPHP5)框架基于ajax与后台数据交互操作简单示例
2018/09/03 PHP
jquery 分页控件实现代码
2009/11/30 Javascript
JavaScript window.document的属性、方法和事件小结
2012/10/24 Javascript
JavaScript中的运算符种类及其规则介绍
2013/09/26 Javascript
基于javascript实现泡泡大冒险网页版小游戏
2016/03/23 Javascript
值得分享的轻量级Bootstrap Table表格插件
2016/05/30 Javascript
javascript实现任务栏消息提示的简单实例
2016/05/31 Javascript
vue router-link传参以及参数的使用实例
2017/11/10 Javascript
Angular实现点击按钮控制隐藏和显示功能示例
2017/12/29 Javascript
vue中v-cloak解决刷新或者加载出现闪烁问题(显示变量)
2018/04/20 Javascript
JavaScript执行环境及作用域链实例分析
2018/08/01 Javascript
Vue-router 报错NavigationDuplicated的解决方法
2020/03/31 Javascript
微信小程序自定义弹出层效果
2020/05/26 Javascript
[52:36]VGJ.S vs Serenity 2018国际邀请赛小组赛BO2 第一场 8.19
2018/08/21 DOTA
Python实例之wxpython中Frame使用方法
2014/06/09 Python
解决python 自动安装缺少模块的问题
2018/10/22 Python
django使用haystack调用Elasticsearch实现索引搜索
2019/07/24 Python
Django Rest framework频率原理与限制
2019/07/26 Python
基于python实现对文件进行切分行
2020/04/26 Python
解决在keras中使用model.save()函数保存模型失败的问题
2020/05/21 Python
html5 学习简单的拾色器
2010/09/03 HTML / CSS
浅析border-radius如何兼容IE
2016/04/19 HTML / CSS
加拿大当代时尚服饰、配饰和鞋类专业零售商和制造商:LE CHÂTEAU
2017/10/06 全球购物
工作疏忽检讨书
2014/01/25 职场文书
学生请假条
2014/04/11 职场文书
争先创优个人总结
2015/03/04 职场文书
端午节寄语2015
2015/03/23 职场文书
聘任通知书
2015/09/21 职场文书
最美劳动诗,致敬所有的劳动者!
2019/07/12 职场文书
MySQL索引篇之千万级数据实战测试
2021/04/05 MySQL
python爬虫请求库httpx和parsel解析库的使用测评
2021/05/10 Python
Python实现数据的序列化操作详解
2022/07/07 Python