了解面向对象之前的一些知识
编程范式
是一种典型的编程风格,是一种方法学
编程范式决定了程序员对程序执行的看法
OOP中,程序是一系列对象之间的相互作用
Python中支持多种编程范式:面向过程、面向对象,面向切面(装饰器部分)等
OOP思想
面向对象的基本哲学:世界由具有各自运动规律和内部状态的对象组成,对象之间的相互作用和通讯构成了世界
唯一性,世界上没有两片相同的叶子,同样的,也没有两个完全相同的对象
分类性:分类是对现实世界的抽象
三大特性,继承,多态和封装
类与实例
类 是一类实例的抽象,抽象的属性和操作
实例 是类的具体化
定义类
class Name:这种方式在python3和python2.3之前比较流行,但是在python2.4之后所有类都要继承自object 类。class Name(object): class Name(Parents):
一个例子:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28#!/usr/bin/env Python
#coding=utf-8
class People(object): #object是所有类的基类,它定义了一些基本的操作。继承了object的类称为新式类
def __init__(self,name,sex,age): #__init__(self,...),初始化方法,self,对象自身
self.name = name #将传进来的值定义给对象自身的数据
self.sex = sex
self.age = age
def say(self,words): #一个普通的方法
print 'saying %s .....' % words
def walk(self):
print "walking....."
tom = People('tom','man',17) #实例化一个对象,self参数会自动传入
tom.say('hello') #调用tom的say方法
tom.walk()
print tom.age #打印tom的实例变量age
===============结果=============
root@tonglele /code/Python/oop_base # python code1.py
saying hello .....
walking.....
17
类的封装性
私有成员
以双下划线开始,但不以双下划线结束
Python中没有真正的私有成员,我们可以通过一些方法调用。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28#!/usr/bin/env python
# coding=utf-8
class People(object):
def __init__(self,name,age):
self.name = name
self.__age = age #一个私有属性
def print_info(self):
print self.name
print self.__age
def __test(self): #一个私有方法
print 'calling test.....'
tom = People('tom',60)
print tom.name
print tom.__age
==========运行结果========
root@tonglele /code/Python/oop_base # python code2.py
tom
Traceback (most recent call last):
File "code2.py", line 20, in <module>
print tom.__age
AttributeError: 'People' object has no attribute '__age' #报错。
1 |
|
类变量
定义在实例方法之外的变量
所有实例共享类变量,但某一个实例对类变量的修改不会影响其他的实例和类本身
类变量可以直接访问1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#!/usr/bin/env python
#coding=utf-8
class People(object):
count = 0
def __init__(self,name,sex,age):
self.name = name
self.sex = sex
self.age = age
def print_info(self):
print self.name
print self.sex
print self.age
tom = People('tom','man',19)
marry = People('marry','women',18)
print People.count
print tom.count
print marry.count
People.count = 100
tom.count = 99
marry.count = 98
print '============'
print People.count
print tom.count
print marry.count
==========结果===========
root@tonglele /code/Python/oop_base # python code3.py
0
0
0
============
100
99
98
类方法
使用@classmethod装饰器装饰,第一个参数代表类本身,
类方法可以直接调用,类方法里可以定义类变量。在类方法里不能调用与实例相关的东西,即不能使用self1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31#!/usr/bin/env python
#coding=utf-8
class People(object):
def __init__(self,name,sex,age):
self.name = name
self.sex = sex
self.age = age
def print_info(self):
print self.name
print self.sex
print self.age
@classmethod
def test(cls): #cls代表类本身
cls.count = 10 #定义一个类变量
print 'calling test.....'
People.test() #类方法可以直接调用
print People.count #打印类变量
tom = People('tom','man',19)
tom.test() #用实例调用类方法
==========运行结果========
root@tonglele /code/Python/oop_base # python code3.py
calling test.....
10
calling test.....
静态方法
以@staticmethod装饰器装饰,可以直接调用,没有像类方法那样限定第一个参数1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#!/usr/bin/env python
#coding=utf-8
class People(object):
def __init__(self,name,sex,age):
self.name = name
self.sex = sex
self.age = age
def print_info(self):
print self.name
print self.sex
print self.age
@staticmethod
def test():
print 'calling static--test.....'
People.test() #直接调用静态方法
tom = People('tom','man',19)
tom.test() #通过实例调用静态方法
========结果==========
root@tonglele /code/Python/oop_base # python code3.py
calling static--test.....
calling static--test.....
属性
@property装饰器可以使被装饰的方法称为一个属性,类似与其他语言中的get方法
属性的setter方法
其他的具体解释见代码片1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
#!/usr/bin/env python
import time
import datetime
class Dog(object):
def __init__(self,n):
self.n = n
self.__a = None
def test(self):
print 'calling test.....'
@property #open_f方法被@property装饰器装饰了之后成为一个属性
def open_f(self):
return self.__a == None
@open_f.setter #当open_f方法被装饰之后它自己也变成了一个另一个装饰器,用来装饰这个open_f方法之后此时的这个open_f就相当于其他语言的set方法
def open_f(self,value):
self.__a = value
class Timef(object):
def __init__(self):
self.__time = datetime.datetime.now()
@property
def time(self):
return self.__time.strftime('%Y-%m-%d %H:%M:%S')
@time.setter
def time(self,value):
self.__time = datetime.datetime.strptime(value,'%Y-%m-%d %H:%M:%S')
t = Dog(1212)
print t.open_f
t.open_f = 7878 #给该属性赋值,相当于调用了set方法
print t.open_f #调用该属性,相当于调用了get方法
tt = Timef()
print tt.time
tt.time = '2016-03-20 21:34:21'
print tt.time
#time例子:
#默认以字符串的形式返回当前的时间,也可以以字符串的形式设置时间,整体来说是封装了私有属性__time。
==========运行结果=============
root@tonglele /code/Python/oop_base # python code4.py
True
False
2016-06-29 22:10:20
2016-03-20 21:34:21
另一个常用的运用:
在工作中,有些需求需要对IP地址进行处理,因为在计算机中IP都是以整数的形式做运算的,
但是展现出来的时候都是以字符串形式(点分十进制),便于人类查看,就可以用上述方法实现对IP操作的封装
魔术方法
魔术方法总是以双下划线开头,并以双下划线结尾的,这些方法都是由特殊用途的
下面简单介绍一些:
init
init初始化方法,对实例对象的一些数据进行初始化1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#!/usr/bin/env python
# coding=utf-8
class People(object):
def __init__(self,name,age): #初始化函数
self.name = name #将类=实例对象的一些数据初始化。。
self.age = age
print "init....."
tom = People('tom',19) #实例化一个对象
==========运行结果=====
root@tonglele /code/Python/oop_base # python code5.py
init.....
1 | __new__,__del__ |
1 |
|
以上魔术方法的一些应用1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52#!/usr/bin/env python
#coding=utf-8
class Man(object):
def __init__(self,name,sex,age):
self.name = name
self.sex = sex
self.age = age
def __eq__(self,other):
return self.age == other.age and self.sex == other.sex and self.age == other.age
def __gt__(self,other):
return self.age > other.age
def __ne__(self,other):
return self.age != other.age or self.name != other.name or self.sex != other.sex
def __add__(self,other):
return Man(self.name+other.name,self.sex+other.sex,self.age+other.age)
def __str__(self):
return 'name: %s sex: %s age: %s \n' % (self.name,self.sex,self.age)
def __del__(self):
print 'del......' #做一些清理工作
man1 = Man('tom','man',19)
man2 = Man('harry','man',17)
print man1 == man2
print man1 > man2
print man1 != man2
print man1
print man1 + man2
===========结果==========
False
True
True
name: tom sex: man age: 19
name: tomharry sex: manman age: 36
del......
del......
del......
继承
子类与父类:子类是对父类的扩展,在父类的属性和方法的基础上做一些扩展
一个继承的例子
1 | #!/usr/bin/env python |
多继承
我们大多数情况下只会使用单继承,但python也提供多继承class ClassName(c1,c2…)1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#!/usr/bin/env python
class A(object):
def __init__(self):
pass
def m(self):
print 'A -- m....'
class B(object):
def n(self):
print 'B -- n....'
class C(A,B):
pass
c = C()
c.m()
c.n()
===========运行结果========
A -- m....
B -- n....
但是多继承中也会出现一些问题:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23#!/usr/bin/env python
class A(object):
def __init__(self):
pass
def m(self):
print 'A -- m....'
class B(object):
def m(self):
print 'B -- m....'
class C(A,B):
pass
c = C()
c.m()
=========结果===========
A -- m.... #当多个父类中拥有同一个名称的方法时,子类采用继承顺序靠前的那个
1 | #!/usr/bin/env python |
MRO:一种算法,在python中存在多继承,当继承列表中有同名方法的时候,python就是根据这个MRO来选择子类该执行哪个方法的。
感谢阅读,欢迎指正。