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生成随机验证码(中文验证码)示例
Apr 03 Python
Python使用multiprocessing实现一个最简单的分布式作业调度系统
Mar 14 Python
python解决Fedora解压zip时中文乱码的方法
Sep 18 Python
Python中shape计算矩阵的方法示例
Apr 21 Python
Python学习入门之区块链详解
Jul 25 Python
python将控制台输出保存至文件的方法
Jan 07 Python
django富文本编辑器的实现示例
Apr 10 Python
python版百度语音识别功能
Jul 09 Python
详解python 破解网站反爬虫的两种简单方法
Feb 09 Python
终于搞懂了Keras中multiloss的对应关系介绍
Jun 22 Python
python中upper是做什么用的
Jul 20 Python
python实现每天自动签到领积分的示例代码
Aug 18 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脚本数据库功能详解(中)
2006/10/09 PHP
mysql 字段类型说明
2007/04/27 PHP
php 无限级分类学习参考之对ecshop无限级分类的解析 带详细注释
2010/03/23 PHP
php新浪微博登录接口用法实例
2014/12/23 PHP
PHP并发查询MySQL的实例代码
2017/08/09 PHP
javascript语句中的CDATA标签的意义
2007/05/09 Javascript
javascript 自动填写表单的实现方法
2010/04/09 Javascript
基于jQuery实现表单提交验证
2014/11/24 Javascript
推荐9款炫酷的基于jquery的页面特效
2014/12/07 Javascript
jquery读取xml文件实现省市县三级联动的方法
2015/05/29 Javascript
简介JavaScript中的setTime()方法的使用
2015/06/11 Javascript
javascript中return,return true,return false三者的用法及区别
2015/11/17 Javascript
JavaScript 网页中实现一个计算当年还剩多少时间的倒数计时程序
2017/01/25 Javascript
jQuery插件MovingBoxes实现左右滑动中间放大图片效果
2017/02/28 Javascript
JS简单数组排序操作示例【sort方法】
2019/05/17 Javascript
Vue 中可以定义组件模版的几种方式
2019/08/06 Javascript
[04:31]2016国际邀请赛中国区预选赛妖精采访
2016/06/27 DOTA
python 实现在Excel末尾增加新行
2018/05/02 Python
python爬取哈尔滨天气信息
2018/07/14 Python
对python:print打印时加u的含义详解
2018/12/15 Python
django数据关系一对多、多对多模型、自关联的建立
2019/07/24 Python
使用python 计算百分位数实现数据分箱代码
2020/03/03 Python
如何用python处理excel表格
2020/06/09 Python
html5指南-1.html5全局属性(html5 global attributes)深入理解
2013/01/07 HTML / CSS
使用layui框架实现点击左侧导航切换右侧内容且右侧选项卡跟随变化的效果
2020/11/10 HTML / CSS
卡西欧G-SHOCK英国官网: 防水防震手表
2018/01/08 全球购物
高中生校园生活自我评价
2013/09/19 职场文书
函授本科毕业自我鉴定
2013/10/09 职场文书
一名女生的自荐信
2013/12/08 职场文书
英语故事演讲稿
2014/04/29 职场文书
2014年母亲节寄语
2014/05/07 职场文书
小升初自荐信范文
2015/03/05 职场文书
国家助学金受助感言
2015/08/01 职场文书
超级实用的公文标题大全!
2019/07/19 职场文书
手写Spirit防抖函数underscore和节流函数lodash
2022/03/22 Javascript
python中pd.cut()与pd.qcut()的对比及示例
2022/06/16 Python