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的id()函数介绍
Feb 10 Python
Python的Tornado框架实现异步非阻塞访问数据库的示例
Jun 30 Python
python中验证码连通域分割的方法详解
Jun 04 Python
Python 实现异步调用函数的示例讲解
Oct 14 Python
Django REST framework视图的用法
Jan 16 Python
解决python3 requests headers参数不能有中文的问题
Aug 21 Python
pycharm运行scrapy过程图解
Nov 22 Python
pygame库实现移动底座弹球小游戏
Apr 14 Python
Python常用模块sys,os,time,random功能与用法实例分析
Jan 07 Python
python字符串,元组,列表,字典互转代码实例详解
Feb 14 Python
使用jupyter notebook将文件保存为Markdown,HTML等文件格式
Apr 14 Python
flask框架中的cookie和session使用
Jan 31 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/02/14 PHP
Excel数据导入Mysql数据库的实现代码
2008/06/05 PHP
hessian 在PHP中的使用介绍
2010/12/13 PHP
PHP 第二节 数据类型之转换
2012/04/28 PHP
PHP实现上传文件并存进数据库的方法
2015/07/16 PHP
Referer原理与图片防盗链实现方法详解
2019/07/03 PHP
Yii框架页面渲染操作实例详解
2019/07/19 PHP
浅析PHP中的 inet_pton 网络函数
2019/12/16 PHP
JavaScript入门教程(10) 认识其他对象
2009/01/31 Javascript
jquery固定底网站底部菜单效果
2013/08/13 Javascript
toggle()隐藏问题的解决方法
2014/02/17 Javascript
js绘制圆形和矩形的方法
2015/08/05 Javascript
easyui Draggable组件实现拖动效果
2015/08/19 Javascript
JS实现来回出现文字的状态栏特效代码
2015/10/31 Javascript
Angular.js回顾ng-app和ng-model使用技巧
2016/04/26 Javascript
jQuery制作图片旋转效果
2017/02/02 Javascript
Nodejs 发送Post请求功能(发短信验证码例子)
2017/02/09 NodeJs
JavaScript事件处理程序详解
2017/09/19 Javascript
vue实现倒计时获取验证码效果
2020/04/17 Javascript
Vue路由权限控制解析
2020/11/09 Javascript
[00:56]2014DOTA2国际邀请赛 DK、iG 赛前探访
2014/07/10 DOTA
python使用点操作符访问字典(dict)数据的方法
2015/03/16 Python
python的numpy模块安装不成功简单解决方法总结
2017/12/23 Python
详解python单元测试框架unittest
2018/07/02 Python
Python读取YUV文件,并显示的方法
2018/12/04 Python
深入解析Python小白学习【操作列表】
2019/03/23 Python
浅析Python数字类型和字符串类型的内置方法
2019/12/22 Python
Python字典深浅拷贝与循环方式方法详解
2020/02/09 Python
Python爬虫爬取杭州24时温度并展示操作示例
2020/03/27 Python
Zooplus罗马尼亚:宠物食品和配件
2019/11/02 全球购物
公益活动策划方案
2014/01/09 职场文书
2015年党员创先争优承诺书
2015/01/22 职场文书
新生开学寄语大全
2015/05/28 职场文书
公开致歉信
2019/06/24 职场文书
golang中实现给gif、png、jpeg图片添加文字水印
2021/04/26 Golang
docker compose 部署 golang 的 Athens 私有代理问题
2022/04/28 Servers