专栏首页机器学习与统计学《Python基础教程》 读书笔记 第七章 更加抽象(上)

《Python基础教程》 读书笔记 第七章 更加抽象(上)

7.1对象的魔力

面向对象程序设计中的术语对象(object)基本上可以看做数据(特性)以及由一系列可以存取、操作这些数据的方法所组成的集合。使用对象替代全局变量和函数的原因可能有很多。其中对象最重要的优点包括以下几方面。

多态(Polymorphism):意味着可以对不同类的对象使用同样的操作,它们会像被“施了魔法一般”工作。

封装(Encapsulation ):对外部世界隐藏对象的工作细节。

继承(Inheritance ):以普通的类为基础建立专门的类对象。

7.1.1多态

1.多态和方法

绑定到对象特性上面的函数称为方法(method ).

>>> [1,2,"a"].count('a') 1

对于变量x来说,不需要知道它是字符串还是列表,就可以调用它的count方法--不用管它是什么类型(只要你提供了一个字符作为参数即可)。

>>> from random import choice >>>x=choice(['hello,world!',[1,2,'e','e',4]]) >>> x.count('e') 2

关键点在于不需要检测类型:只需要知道x有个叫做count的方法,带有一个字符作为参数,并且返回整数值就够了。如果其他人创建了的对象类也有count方法,那也无所谓—你只需要像用字符串和列表一样使用该对象就行了。

2.多态的多种形式

>>> def add(x,y): return x+y >>> add('fish','license') 'fishlicense'

参数可以是任何支持加法的对象。如果需要编写打印对象长度消息的函数,则只需对象具有长度(len函数可用)即可:

>>> add('fish','license') 'fishlicense' >>> def length_message(x): ... print "the length of",repr(x),"is",len(x)

函数中使用了repr函数,repr函数是多态特性的代表之一,可以对任何东西使用:

>>>length_message("fnord") the length of 'fnord' is 5 >>> length_message([1,2,3]) the length of [1, 2, 3] is 3

要使用多态函数和运算符,多态就“消除”了。事实上,唯一能够毁掉多态的就是使用函数显示地检查类型,比如type, isinstance以及issubclass函数等。如果可能的话,应该尽力避免使用这些毁掉多态的方式。真正重要的是如何让对象按照你所希望的方式工作,不管它是否是正确的类型(或者类)。

7.1.2封装

封装是对全局作用域中其他区域隐藏多余信息的原则。听起来有些像多态一一使用对象而不用知道其内部细节,两者概念类似,因为它们都是抽象的原则一一它们都会帮助处理程序组件而不用过多关心多余细节,就像函数做的一样。

但是封装并不等同于多态。多态可以让用户对于不知道是什么类(或对象类型)的对象进行方法调用,而封装是可以不用关心对象是如何构建的而直接进行使用。听起来还是有些相似?让我们用多态而不用封装写个例子,假设有个叫做OpenObject的类:

>>> o=OpenObject() >>> o.setName('sir lancelot') >>> o.getName() ‘sir lancelot’

假设变量0将它的名字存储在全局变量globalName中:

>>>globeName ‘sir lancelot’

这就意味着在使用OpenObject类的实例时候,不得不关心globalName的内容。实际上要确保不会对它进行任何更改:

>>>globaName=’sir gumby’ >>>o.getName() ‘sir gumby’

如果创建多个openobject实例就会出问题

7.2类和类型

7.2.1类到底是什么

所有的对象都属于某一个类,称为类的实例(instance)

7.2.2创建自己的类

>>> class Person: def setName(self,name): self.name=name def getName(self): return self.name def greet(self): print "hello world,i'm %s,"% self.name >>> foo=Person() >>> bar=Person() >>> foo.setName('luke skywalker') >>> bar.setName('anakinskywalker') >>> foo.greet() hello world,i'm luke skywalker, >>> bar.greet() hello world,i'm anakin skywalker,

在调用foo的setName和greet函数时,foo自动将自己作为第一个参数传入函数中—因此形象地命名为self。对于这个变量,每个人可能都会有自己的叫法,但是因为它总是对象自身,所以习惯上总是叫做self

特性是可以在外部访问的:

>>> foo.name 'luke skywalker' >>> bar.name='Yoda' >>> bar.greet() hello world,i'm Yoda,

7.2.3特性、函数和方法

self参数事实上正是方法和函数的区别。方法(更专业一点可以称为绑定方法)将它们的第一个参数绑定到所属的实例上,因此这个参数可以不必提供。所以可以将特性绑定到一个普通函数上,这样就不会有特殊的self参数了:

>>> class Class: ... def method(self): ... print 'i have a self!' ... >>> def function(): ... print "i don't..." ... >>> instance=Class() >>> instance.method() i have a self! >>> instance.method=function >>> instance.method() i don't...

self参数并不取决于调用方法的方式,目前使用的是实例调用方法,可以随意使用引用同一个方法的其他变量:

>>> class Bird: ... song='squaawk!' ... def sing(self): ... print self.song ... >>> bird=Bird() >>> bird.sing() squaawk! >>> birdsong=bird.sing >>> birdsong() squaawk!

最后一个方法调用看起来与函数调用十分相似,但是变量birdsong引用绑定方法bird.sing上,也就意味着这还是对self参数的访问。

默认情况下,程序可以从外部访问一个对象的特性。再次使用前面讨论过的有关封装的例子:

>>>c .name ‘sir lancelot’ >>>c .name=’sir gumby’ >>>c.getName() ‘sir gumby'

为了让方法或者特性变为私有(从外部无法访问),只要在它的名字前面加上双下划线即可:

>>> class Secretive: ... def __inaccessible(self): ... print "bet you can't see me" ... def accessible(self): ... print "the secret message is:" ... self.__inaccessible()

现在__inaccessible从外界是无法访问的,而在类内部还能使用(比如从accessible)访问:

>>> s=Secretive() >>> s._Secretive() Traceback (most recent call last): File "<input>", line 1, in <module> AttributeError: 'Secretive' object has noattribute '_Secretive' >>> s.accessible() the secret message is: bet you can't see me

类的内部定义中,所有以双下划线开始的名字都被“翻译”成前面加上单下划线和类名的形式。

本文分享自微信公众号 - 机器学习与统计学(tjxj666)

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2015-05-26

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 100天搞定机器学习|Day16 通过内核技巧实现SVM

    再简单回顾一下svm算法的思路,详细推导请看前情回顾相关内容,或在文末下载之前推荐的《理解SVM 的三层境界》PDF版。

    统计学家
  • 《Python基础教程》 读书笔记 第九章 魔法方法、属性和迭代器 9.5属性

    class Rectangle: def __init__(self): self.width=0 self.height=0 def setSize(...

    统计学家
  • 利用Python让你的命令行像坤坤一样会打篮球

    承接上文,作为一个经常逛b站的肥宅,近期b站上除了流行"品如”素材的视频,更多的莫过于蔡xx打球视频的了,有模仿的,有对比的,有手绘的,更过分的是竟然有人在命令...

    统计学家
  • Python学习(七)---- 面向对象学习(类)

    原文地址: https://blog.csdn.net/fgf00/article/details/52449707 编辑:智能算法,欢迎关注!

    智能算法
  • python面向对象编程小结

    在类的内部使用def关键字可以为类定义一个方法。与函数定义不同的是,类的方法必须包含参数 'self ’ ,

    py3study
  • python3 组合的个人理解

    python的组合在我看来和函数的嵌套差不多,比如一个人,一把枪,一个类调用人的类,和抢的类把他们组合起来,这就叫组合!

    py3study
  • 将特性与Mixin类混合

    python中多重继承的用途之一是通过mixins扩展类功能。mixin是提供其他类方法的类,但不被视为基类

    公众号---志学Python
  • python笔记:线程

    2 锁 #创建锁 mutex = threading.Lock() #锁定 mutex.acquire([timeout]) #释放 mutex.release...

    超级大猪
  • iOS·长按保存图片到相册:系统原生UIActionSheet与UIAlertView,UIAlertController等方案

    陈满iOS
  • python服务端多进程压测工具

    本文描述一个python实现的多进程压测工具,这个压测工具的特点如下: 多进程 在大多数情况下,压测一般适用于IO密集型场景(如访问接口并等待返回),在这种场景...

    用户1225216

扫码关注云+社区

领取腾讯云代金券