注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

互联网产品经理的窝

梦想社:一个人为了梦想,始终没有停下自己的脚步

 
 
 

日志

 
 

《Python基础教程》学习笔记之[D4]面向对象  

2012-05-06 22:17:10|  分类: python |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

原文请参考这里

《Python基础教程》学习笔记之[D4]面向对象 - 梦想社 - 梦想社


第七章  更加抽象——面向对象

 

1. 面向对象的特点——多态,封装,继承

 

   对象:包括特性和方法,特性只是作为对象的一部分变量,而方法则是存储在对象内的函数。

 

(1)多态——对不同类的对象,使用同样操作。不知道对象到底是什么类型,但又要对对象做一些操作

   很多内置的函数和运算符都是多态的

   不用关注x到底是什么类型,都可以使用count函数,另外还有repr(),连接符+等

Python代码  收藏代码
  1. >>> x = 'string'  #x是字符串  
  2. >>> x.count('s')  
  3. 1  
  4. >>> x = ['1''2''1']  #x是列表  
  5. >>> x.count('1')  
  6. 2  

 

(2)封装——对外部世界隐藏对象的操作细节

(3)继承——以普通类为基础建立专门的类对象

 

2. 创建类

   对于python来说,方法就分两种一种是绑定的,一种是不绑定。属于类的方法就是绑定的,普通的函数就是不绑定的

   除了静态类,其他类的方法定义时都需要有一个self参数,而调用时不需要,self类似java/c++里的this,不是指类本身,而是指实例本身。

 

   类的方法与普通的函数只有一个特别的区别——它们必须有一个额外的第一个参数名称,但是在调用这个方法的时候你 为这个参数赋值,Python会提供这个值。这个特别的变量指对象本身,按照惯例它的名称是self 。

   self原理:举例说明,有一个类A,A的实例a,a.method(arg1,arg2)这时python自动转A.method(a,arg1,arg2),这也意味着如果你有一个不需要参数的方法,你还是得给这个方法定义一个self 参数。

 

   python没法显式的说哪个属性是自己的,而且属性还可以动态的增加,此时,一个解决方案出来了,增加self,通过self.访问的就可以做为类的属性。

Python代码  收藏代码
  1. >>> _metaclass_ =  type #确定使用新类  
  2. >>> class Person:  
  3.     def setName(self, name):  #相当于this,代表Person对象自身  
  4.         self.name = name  
  5.     def getName(self):  
  6.         return self.name  
  7.     def greet(self):  
  8.         print "Hello, world! I'm %s." %self.name  
  9.   
  10. #运行       
  11. >>> foo = Person()  
  12. >>> bar = Person()  
  13. >>> foo.setName('Luke')  #相当于给实例foo,添加了一个attribute: name  
  14. >>> bar.setName('Anakin')  
  15. >>> foo.greet()  
  16. Hello, world! I'm Luke.  
  17. >>> bar.greet()  
  18. Hello, world! I'm Anakin.  
  19. >>> foo.name  #特性可在外部访问  
  20. 'Luke'  
  21. >>> Person.getName(foo) #效果同上  
  22. 'Luke'  
  23. >>> bar.name = 'Yoda'  #特性也可在外部直接修改,类似bar.setName('Yoda')  
  24. >>> bar.greet()  #等价于Person.greet(bar)  
  25. Hello, world! I'm Yoda.  

 

   将属性绑定到普通函数上

Python代码  收藏代码
  1. >>> class MyClass:  
  2.     def method(self):  
  3.         print "I have a self!"  
  4.   
  5.           
  6. >>> def function():  
  7.     print "I don't..."  
  8.   
  9.       
  10. >>> c = MyClass()  
  11. >>> c.method()  
  12. I have a self!  
  13. >>> c.method = function  #将属性绑定到普通函数  
  14. >>> c.method()  
  15. I don't...  
 

3. 私有属性、方法——Python并没有真正的私有化支持,但可用下划线得到伪私有


   尽量避免定义以下划线开头的变量

   (1)_xxx      "单下划线 " 开始的成员变量叫做保护变量,意思是只有类对象(即类实例)和子类对象自己能访问到这些变量,需通过类提供的接口进行访问;不能用'from module import *'导入


    (2)__xxx    类中的私有变量/方法名 (Python的函数也是对象,所以成员方法称为成员变量也行得通。),"双下划线 " 开始的是私有成员,意思是只有类对象自己能访问,连子类对象也不能访问到这个数据。

 

    (3)__xxx__ 系统定义名字,前后均有一个“双下划线” 代表python里特殊方法专用的标识,如 __init__()代表类的构造函数。

 

   __开头的本来就是表示private,private是不可继承的

 

    python有私有的定义方法就是在变量或者方法的面前加上双下滑线__,但是实际上这是python的伪私有。只是一种程序员约定俗称的规定,加了就表示私有变量,但是如果要在外部调用的话,还是可以调用的,调用方法如下:

   所有以双下划线开始的变量,都被python翻译为前面加上单下划线和类名

如__inaccessible 翻译为 Secretive._Secretive__inaccessible,注意第一个为单下划线,第二个为双下划线

 

Python代码  收藏代码
  1. >>> class Secretive:  
  2.     def __inaccessible(self):  #双下划线表示私有方法  
  3.         print "Bet you can't see me..."  
  4.     def accessible(self):  
  5.         print "The secret message is:"  
  6.         self.__inaccessible()  
  7.   
  8.           
  9. >>> s = Secretive()  
  10. >>> s.__inaccessible() #私有方法从外界是无法访问的  
  11.   
  12. Traceback (most recent call last):  
  13.   File "<pyshell#89>", line 1in <module>  
  14.     s.__inaccessible() #私有方法从外界是无法访问的  
  15. AttributeError: Secretive instance has no attribute '__inaccessible'  
  16. >>> s.accessible()  #私有方法只能在类内部使用  
  17. The secret message is:  
  18. Bet you can't see me...  
  19. >>> s._Secretive__inaccessible()  #虽然私有,仍能调用,伪私有机制  
  20. Bet you can't see me...  

 

4. 类的命名空间——class语句中的代码都在特殊的命名空间中执行

 

   类的定义区并不只限定使用def语句

Python代码  收藏代码
  1. >>> class C:  
  2.     print 'Without def...'  
  3.   
  4. #运行   
  5. Without def...  

 

   计算类的实例数量

Python代码  收藏代码
  1. >>> class MemberCounter:  
  2.     members = 0  
  3.     def init(self):  
  4.         MemberCounter.members += 1 #属于整个类的属性members,计算类的实例数量,而不用self.members,实例的属性  
  5.   
  6.           
  7. >>> m1 = MemberCounter()  
  8. >>> m1.init()  
  9. >>> MemberCounter.members  
  10. 1  
  11. >>> m1.members  
  12. 1  
  13. >>> m2 = MemberCounter()  
  14. >>> m2.init()  
  15. >>> MemberCounter.members  
  16. 2  
  17. >>> m2.members  #类作用于内的变量,可以被所有实例访问  
  18. 2  
  19. >>> m1.members  
  20. 2  
  21. >>> m2.members = 'test' #重绑定members,相当于新添加了与类里的members相同的同名变量,从而屏蔽了类范围内的变量  
  22. >>> m2.members  
  23. 'test'  
  24. >>> m1.members  #不变  
  25. 2  
  26. >>> MemberCounter.members  
  27. 2  

 

5. 继承

   格式:A是父类,B是子类,B继承A

   class A:

   class B(A):

Python代码  收藏代码
  1. >>> class Filter:  
  2.     def init(self):  
  3.         self.blocked = []  
  4.     def filter(self, sequence):  
  5.         return [x for x in sequence if x not in self.blocked]  
  6.   
  7.       
  8. >>> class SPAMFilter(Filter): #继承Filter  
  9.     def init(self): #重写Filter父类中的init方法  
  10.         self.blocked = ['SPAM']  
  11.   
  12.           
  13. >>> f = Filter()  
  14. >>> f.init()  
  15. >>> f.filter([123])  
  16. [123]  
  17. >>>   
  18. >>> s = SPAMFilter()  
  19. >>> s.init()  #调用子类重写的方法  
  20. >>> s.filter(['SPAM''TEST''SPAM''test']) #调用从父类继承来的方法  
  21. ['TEST''test']  

 

   调查继承

   issubclass(A,B):查看类A是否是类B的子类

Python代码  收藏代码
  1. >>> issubclass(SPAMFilter, Filter)  
  2. True  
  3. >>> issubclass(Filter, SPAMFilter)  
  4. False  

 

   若想知道某个类的基类,使用特殊属性__bases__,注意为“双下划线”

Python代码  收藏代码
  1. >>> SPAMFilter.__bases__  
  2. (<class __main__.Filter at 0x011A62D0>,)  
  3. >>> Filter.__bases__  
  4. ()  
 

   isinstance(A,B):对象A是否是类B的实例

Python代码  收藏代码
  1. >>> s = SPAMFilter() #既是子类的实例又是父类的实例  
  2. >>> isinstance(s, SPAMFilter)  #s是子类的直接实例(成员)  
  3. True  
  4. >>> isinstance(s, Filter)  #s是父类的间接实例  
  5. True  
  6. >>> isinstance(s, str) #isinstance对类型也起作用,如str是字符串类型  
  7. False  

 

   若想知道对象属于哪个类的实例,使用特殊属性__class__,注意为“双下划线”

Python代码  收藏代码
  1. >>> s.__class__  
  2. <class __main__.SPAMFilter at 0x011A6480>  

 

6. 多重继承

   子类TalkingCalculator不作任何事,它从父类中继承所有的行为,从Calculator中继承calculate方法,从Talk中继承talk方法。

Python代码  收藏代码
  1. >>> class Calculator:  
  2.     def calculate(self, expression):  
  3.         self.value = eval(expression)  
  4.   
  5.           
  6. >>> class Talker:  
  7.     def talk(self):  
  8.         print "Hi, my value is"self.value  
  9.   
  10.           
  11. >>> class TalkingCalculator(Calculator, Talker):  
  12.     pass  
  13.   
  14. >>> tc = TalkingCalculator()  
  15. >>> tc.calculate('1 + 2 * 3')  
  16. >>> tc.talk()  
  17. Hi, my value is 7  

 

    注意超类顺序,先继承的类中的方法会重写后继承的类中的方法

    假设C继承A和B,而A和B中有同名方法,如method

   class C(A, B):,A中的method重写B中的method

   class C(B, A):,B中的method重写A中的method,所以如果想使用B中的method方法,则将B放在前面

 

7. 接口和内省——公开的方法和属性

 

   检查所需方法(特性)是否存在

Python代码  收藏代码
  1. >>> hasattr(tc, 'talk')  
  2. True  
  3. >>> hasattr(tc, 'test')  
  4. False  

 

   检查方法是否可调用

Python代码  收藏代码
  1. >>> hasattr(getattr(tc, 'talk'None), '__call__')  
  2. True  
  3. >>> hasattr(getattr(tc, 'test'None), '__call__')  
  4. False  

    getattr()允许提供默认值,以便当方法不存在时使用。

    与getattr()相对的是setattr()用来设置对象特性

Python代码  收藏代码
  1. >>> setattr(tc, 'name''Mr. Gumby')  
  2. >>> tc.name  
  3. 'Mr. Gumby'  
 

总结:

   random.choice(seq) : 从非空序列中随机选择元素

Python代码  收藏代码
  1. >>> from random import choice  
  2. >>> choice([123])  
  3. 1  

 

   type(object):返回对象类型

Python代码  收藏代码
  1. >>> type('test')  
  2. <type 'str'>  
  3. >>> type(1)  
  4. <type 'int'>  
  评论这张
 
阅读(160)| 评论(0)
推荐 转载

历史上的今天

在LOFTER的更多文章

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017