标签:
第六天:
面向对象
1. 面向对象的特点——多态,封装,继承
对象:包括特性和方法,特性只是作为对象的一部分变量,而方法则是存储在对象内的函数。
(1)多态——对不同类的对象,使用同样操作。不知道对象到底是什么类型,但又要对对象做一些操作
很多内置的函数和运算符都是多态的
不用关注x到底是什么类型,都可以使用count函数,另外还有repr(),连接符+等
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.访问的就可以做为类的属性。
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.
将特性(方法)绑定到普通函数上
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,注意第一个为单下划线,第二个为双下划线
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 1, in <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语句
1. >>> class C:
2. print ‘Without def...‘
3.
4. #运行
5. Without def...
计算类的实例数量
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
classA:
class B(A):
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([1, 2, 3])
16.[1, 2, 3]
17.>>>
18.>>> s = SPAMFilter()
19.>>> s.init() #调用子类重写的方法
20.>>> s.filter([‘SPAM‘, ‘TEST‘, ‘SPAM‘, ‘test‘]) #调用从父类继承来的方法
21.[‘TEST‘, ‘test‘]
调查继承
issubclass(A,B):查看类A是否是类B的子类
1. >>> issubclass(SPAMFilter, Filter)
2. True
3. >>> issubclass(Filter, SPAMFilter)
4. False
若想知道某个类的基类,使用特殊属性__bases__,注意为“双下划线”
1. >>> SPAMFilter.__bases__
2. (<class __main__.Filter at 0x011A62D0>,)
3. >>> Filter.__bases__
4. ()
isinstance(A,B):对象A是否是类B的实例
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__,注意为“双下划线”
1. >>> s.__class__
2. <class __main__.SPAMFilter at 0x011A6480>
6. 多重继承
子类TalkingCalculator不作任何事,它从父类中继承所有的行为,从Calculator中继承calculate方法,从Talk中继承talk方法。
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. 接口和内省——公开的方法和属性
检查所需方法(特性)是否存在
1. >>> hasattr(tc, ‘talk‘)
2. True
3. >>> hasattr(tc, ‘test‘)
4. False
检查方法是否可调用
1. >>> hasattr(getattr(tc, ‘talk‘, None), ‘__call__‘)
2. True
3. >>> hasattr(getattr(tc, ‘test‘, None), ‘__call__‘)
4. False
getattr()允许提供默认值,以便当方法不存在时使用。
与getattr()相对的是setattr()用来设置对象特性
1. >>> setattr(tc, ‘name‘, ‘Mr. Gumby‘)
2. >>> tc.name
3. ‘Mr. Gumby‘
总结:
random.choice(seq) : 从非空序列中随机选择元素
1. >>> from random import choice
2. >>> choice([1, 2, 3])
3. 1
type(object):返回对象类型
1. >>> type(‘test‘)
2. <type ‘str‘>
3. >>> type(1)
4. <type ‘int‘>
标签:
原文地址:http://blog.csdn.net/tanggao1314/article/details/52210867