您的位置:首页 > 编程语言 > Python开发

《Python基础教程》学习笔记 Chp7 更加抽象

2016-06-01 17:40 417 查看
多态

多态意味着不知道变量所引用的对象类型是什么,还是能对它进行操作,而它也会根据对象(或类)类型的不同而表现出不同的行为。

封装

封装是指向程序中的其他部分隐藏对象的具体实现细节的原则。

创建自己的类

>>> _metaclass_ = type
>>> 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('Alice')
>>> bar.setName('Bobby')
>>> foo.greet()
Hello , world ! I'm Alice.
>>> bar.greet()
Hello , world ! I'm Bobby.


注: metaclass = type,在新式类的语法中才需要加。这里self参数是对于对象自身的引用。其中setName等叫做类的方法。

特性、函数和方法

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参数并不依赖于调用方法的方式,前面我们使用的是instance.method(实例.方法)的形式,可以随意使用其他变量引用同一个方法:

>>> class Class:
...     def method(self):
...         print 'I have a self'
...
>>> cls = Class()
>>> cls.method()
I have a self
>>> method = cls.method
>>> method()
I have a self


注:尽管最后一个方法调用看起来于函数调用十分相似,但是变量method引用绑定方法cls.method上,也就意味着这还是会对self参数进行访问(也就是说,它仍旧绑定到类的相同实例上)。

私有化

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

>>> class Secretive:
...     def __inaccessible(self):
...         print "Bet you can't see me ..."
...     def accessible(self):
...         print "The secret message is : "
...         self.__inaccessible()
...
>>> s = Secretive()
>>> s.accessible()
The secret message is :
Bet you can't see me ...
>>> s.__inaccessible()
Traceback (most recent call last):
File "<interactive input>", line 1, in <module>
AttributeError: Secretive instance has no attribute '__inaccessible'


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

>>> Secretive._Secretive__inaccessible
<unbound method Secretive.__inaccessible>


因此上例中的私有化方法可以如下所示进行访问:

>>> s._Secretive__inaccessible()
Bet you can't see me ...


如果不需要使用这种方法但是又想让其他对象不要访问内部数据,那么可以使用单下划线。例:

>>> class Secretive:
...     def _inaccessible(self):
...         print "Bet you can't see me ..."
...
>>> s = Secretive()
>>> s._Secretive__inaccessible()
Traceback (most recent call last):
File "<interactive input>", line 1, in <module>
AttributeError: Secretive instance has no attribute '_Secretive__inaccessible'
>>> s._Secretive_inaccessible()
Traceback (most recent call last):
File "<interactive input>", line 1, in <module>
AttributeError: Secretive instance has no attribute '_Secretive_inaccessible'


类的命名空间

例:

>>> class MemberCounter:
...     members = 0
...     def init(self):
...         MemberCounter.members+=1
...
>>> m1 =  MemberCounter()
>>> m1.init()
>>> MemberCounter.members
1
>>> m2 = MemberCounter()
>>> m2.init()
>>> MemberCo
4000
unter.members
2
>>> m2.members
2
>>> m1.members = 'two'
>>> m1.members
'two'
>>> m2.members
2


分析说明:类中定义了一个可供所有成员(实例)访问的变量members,用来计算类的成员数量(我们可以把它理解为全局变量),然后又在实例m1中重新绑定了members的值(此时相当于是局部变量,所以屏蔽了类范围内的变量)。

指定超类

例:

>>> class Filter:
...     def init(self):
...         self.blocked = []
...     def filter(self, sequence):
...         return [x for x in sequence if x not in self.blocked]
...
>>> class SPAMFilter(Filter):   #SPAMFilter是Filter的子类
...     def init(self):     #重写Filter超类中的init方法
...         self.blocked = ['SPAM']
...
>>> f = Filter()
>>> f.init()
>>> f.filter([1,2,3])
[1, 2, 3]
>>> s = SPAMFilter()
>>> s.init()
>>> s.filter(['SPAM', 'SPAM', 'SPAM', 'SPAM', 'eggs', 'bacon', 'SPAM'])
['eggs', 'bacon']


检查继承

如果要查看一个类是否是另一个类的子类,可以使用内建函数的issubclass函数。例:

>>> issubclass(SPAMFilter, Filter)
True
>>> issubclass(Filter, SPAMFilter)
False


如果想要知道已知类的基类(们),可以直接使用它的特殊特性_bases_。例:

>>> SPAMFilter.__bases__
(<class __main__.Filter at 0x02324D18>,)
>>> Filter.__bases__
()


使用isinstance方法检查一个对象是否是一个类的实例。例:

>>> isinstance(s, SPAMFilter)
True
>>> isinstance(s, Filter)
True
>>> isinstance(f, SPAMFilter)
False


可以使用_class_特性知道一个对象属于哪个类。例:

>>> s.__class__
<class __main__.SPAMFilter at 0x02324C38>
>>> f.__class__
<class __main__.Filter at 0x02324D18>


多个超类

Python中支持多重继承,即一个类可以有多个超类。当使用多重继承时,如果一个方法从多个超类继承(也就是说有两个具有相同名字的不同方法),那么必须要注意一下超类的顺序(在class语句中):先继承的类中的方法会重写后继承的类中的方法,这种访问超类的顺序为MRO(Method Resolution Order,方法判定顺序)。例:

>>> class Calculator:
...     def calculator(self, expression):
...         self.value = eval(expression)
...     def talk(self):
...         print 'Hi, my value is : ', self.value
...
>>> class Talker:
...     def talk(self):
...         print 'Hi, now you can get my value is : ', self.value
...
>>> class TalkingCalculator(Calculator, Talker):
...     pass
...
>>> tc = TalkingCalculator()
>>> tc.calculator('1+2*3')
>>> tc.talk()
Hi, my value is :  7
>>> class TalkingCalculator(Talker, Calculator):
...     pass
...
>>> tc1 = TalkingCalculator()
>>> tc1.calculator('1+2*3')
>>> tc1.talk()
Hi, now you can get my value is :  7


接口和内省

可以使用hasattr方法检查所需方法是否已经存在。例:

>>> hasattr(tc, 'talk')
True
>>> hasattr(tc, 'finder')
False


可以使用callable方法检查所需的方法是否可调用。例:

>>> callable(getattr(tc, 'tall', None))
False
>>> callable(getattr(tc, 'talk', None))
True


本章新函数

callable(object): 确定对象是否可调用(比如函数或者方法)

getattr(object,name[, default]): 确定特性的值,可选择提供默认值

hasattr(object,name):确定对象是否有给定的特性

isinstance(object,class):确定对象是否是类的实例

issubclass(A,B):确定A是否为B的子类

random.choice(sequence):从非空徐磊中随机选择元素

setattr(object,name,value):设定对象的给定特性为value

type(object):返回对象的类型
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  python