面向对象

Posted 早晨我在雨中采花

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了面向对象相关的知识,希望对你有一定的参考价值。

面向对象

前言:java , c# 只支持面向对象,python 即支持函数式编程,也支持面向对象编程。

一,函数式编程,面向对象编程

 1 ###函数式编程
 2 def mail(email,message):
 3     print("去发吧!")
 4     return True
 5     
 6 mail("alex3714@126.com", "好人")
 7 
 8 
 9 
10 
11 ###面向对象:类,对象
12 
13 class FOO:
14     # 方法(函数在面向对象中叫方法)
15     def mail(email,message):
16         print("去发吧!")
17         return True
18 
19 # 调用
20 
21 #1,创建对象,类名()
22 
23 #    obj = FOO()
24 
25 #2, 通过对象去执行方法
26 
27 #    obj.mail("alex3714@126.com", "好人")
例子1:发邮件功能

通过以上对比发现面向对象不如函数式编程好。是不是面向对象一无是处呢,接着看哦!

 

二,类和对象

a, 创建类
  class 类名:
    def 方法名(self,xxxx): # 注意self 不需要我们去传值,Python自动给其传值
      pass

b, 创建对象
  对象 = 类名()

c, 通过对象执行方法
  对象.方法名(123)

 

 1 # 函数式编程:
 2 
 3     def fetch(host, username, password, sql):
 4         pass
 5         
 6     def create(host, username, password, sql):
 7         pass
 8         
 9     def remove(host, username, password, ID):
10         pass
11     
12     def modify(host, username, password, name):
13         pass
14         
15         
16 # 面向对象编程:
17 
18 class SQLHandLer:  #定义类
19 
20     def fetch(self, sql):  # 定义方法
21         print(self.hhost)
22         print(self.uusername)
23         print(self.pwd)
24         pass
25         
26     def create(self, sql):
27         pass
28         
29     def remove(self, ID):
30         pass
31     
32     def modify(self, name):
33         pass
34     
35 obj1 = SQLHandLer()   #类对象指针,保存对象是由哪个类创建的,把对象指向某个类。
36 obj1.hhost = "www.example.com"
37 obj1.uusername = "alex"
38 obj1.pwd = "123"
39 # 相当于主机名,用户名,密码封装到对象obj当中
40 
41 obj1.fetch("select * from A")    
42 # 此时把"select * from A"当作参数传递给fetch中的sql,然后把obj1当作一个整体传
43 #给fetch中的self,因此通过self就可以获取到封装的主机名,用户名,密码
44 
45 #结果如下:
46 
47 www.example.com
48 alex
49 123
50 select * from A
例子2:实现对数据库的操作

# 对象和类的关系:对象是由类创建的

小结:
到底什么时候使用面向对象?
如果有一些的函数有共同的参数,可以使用面向对象,把共同的参数一次性进行封装,以后直接去对象中取值即可!

 

三,self是什么?

self是一个Python会自动给传值的参数。
简单来说,即哪个对象执行方法,self就是谁。

obj1.fetch("select...") self=obj1
obj2.fetch("select...") self=obj2

例子2中self是obj1, 如果要连接另外一个数据库的话,此时就得创建
一个类似的obj2,而此时的self就是obj2

思考:如果上例中有20个数据库,那就需要创建20个对象,将会显得异常的麻烦!怎么办,接着往下看。

 

四,构造方法

 1 class SQLHandLer:
 2     def __init__(self, a1, a2, a3):
 3     # print("自动执行__int__方法!")
 4         self.host = a1
 5         self.username = a2
 6         self.pwd = a3
 7 
 8 def fetch(self, sql):
 9     self.host = "ww.yewu.com"   # 在其他的函数中可以对__int__中封装对象相应的值做调用和重新赋值等操作!
10     print(self.host, self.username, self.pwd, sql)
11     pass
12 
13     def create(self, sql):
14         pass
15 
16     def remove(self, id_number):
17         pass
18 
19     def modify(self, name):
20         pass
21 
22 obj = SQLHandLer("www.example1.com", "alex", "123")
23 obj.fetch("select * from student")
24 
25 
26 # 结果如下:
27 
28 www.example1.com alex 123 select * from student
29                 
例子3:构造方法,构造方法只要指封装之后的__int__方法,可以构造成新的对象。

小结:类中有一个特殊的方法__init__ ,当出现 "类()" 时,__init__ 将会被自动执行。此时无论
出现多少数据库,只需要往SQLHandler中传参数即可!


注意:这里面有一个需要注意的点,就是在类里面,进行函数调用时,不分先后顺序都可以调用得到。
比如,可以在__init__,方法中调用下面的其他如create()等函数。

 

五,面向对象的三大特性:

  • 封装 (面向对象中最最重要的一点!)
  • 继承 (比较有用)
  • 多态 (这点特性在python中没有太多的意义,这点特性在c#,java这种强类型的语言中比较有用)

 

六,面向对象之对象中封装对象

常见的类:str,list,dict,tuple,set 这六个python常见的类,我们也可以自定义类。

 1 class c1:
 2 def __init__(self, name, obj):
 3     self.name = name
 4     self.obj = obj
 5 
 6 
 7 class c2:
 8     def __init__(self, name, age):
 9         self.name = name
10         self.age = age
11 
12     def show(self):
13         print(self.name)
14         print("show")
15 
16 
17 class c3:
18     def __init__(self, a1):
19         self.money = 123
20         self.aaa = a1
21 
22 c2_obj = c2("aa", 11)
23 # c2_obj 是c2类型,包含 name = "aa", age = 11
24 
25 c1_obj = c1("alex", c2_obj)   # ------>把对象当参数传递
26 # c1_obj 是c1类型,,包含 name = "alex", obj = c2_obj
27 
28 c3_obj = c3(c1_obj)
29 # c3_obj 是c3类型,包含 money = 123, aaa = c1_obj
30 
31 
32 # 如何用c3_obj调用 show(),方法 ??? 
33 
34 c3_obj.aaa.obj.show()   # 一定注意去理解哈
35 
36 
37 # 结果如下:
38 aa
39 show
对象中封装对象

 

七,继承性

(python可以多继承,可以单继承,java和C#只能单继承)

 

  • 单继承

1.

 1 class F1:  # 父类,也叫基类
 2     def show(self):
 3         print("show")
 4 
 5 def foo(self):
 6     print(self.name)
 7 
 8 
 9 class F2(F1):  # 子类,也叫派生类
10     def __init__(self, name):
11         self.name = name
12 
13     def bar(self):
14         print("bar")
15 
16     def show(self):
17         print("F2.show")
18 
19 obj = F2("alex")
20 obj.foo()    # 请问这个执行结果会是"alex"吗?
21     
例子4,单继承

答案是肯定的。见下面注意的第二点。


小结:需要注意以下几点?
1,子类只能继承父类,下面的类只能继承上面的类,同样子类也可能变成父类,相对的。
2,子类在继承之后之所以能调用父类的方法,本质上就是相当于把父类中的方法在子类中重写一遍。
3,子类在继承父类之后,如果父类中也有同样的方法,在执行时优先执行自己的方法

 

2.

 1 class S1:
 2     def f1(self):
 3         self.f2()
 4 
 5     def f2(self):
 6         print("S1.f2")
 7 
 8 
 9 class S2(S1):
10     def f3(self):
11         self.f1()
12 
13     def f2(self):
14         print("S2.f2")
15 
16 # 判断执行结果,到底会执行哪个f2()?????
17 
18 obj1 = S2()   # 一定要从根入手,obj1是根据S2创建的
19 obj1.f3()
20 
21 obj2 = S1()  # 一定要从根入手,obj2是从s1创建的
22 obj2.f1()
例子5,单继承

结果如下:

S2.f2
S1.f2

分析:可以通过上面注意事项中的第二点来看,也看以通过根来看,观察对象是根据那个类来创建的。这是继承易混淆的点,以后在看源码时会经常碰到类似的问题,其实并不难。

 

 

  • 多继承

  1.   没有共同父类的多继承

 1 class C0:
 2     def f2(self):
 3         print("C0.f2")
 4 
 5 class C1:
 6     def f2(self):
 7         print("C1.f2")
 8         pass
 9 
10 
11 class C2(C0):
12     def f1(self):
13         print("C2.f1")
14         pass
15 
16 
17 class C3(C2, C1):  # 谁在前面就就先继承谁(如果C1和C2当中有相同的方法就可以体现出来)
18     def f3(self):
19         pass
20 
21 obj = C3()
22 obj.f2()
例子6,没有共同父类的多继承 

# 当没有共同的父类的时,谁在前面,会一直向上找,一直找到没有继承。(像C3在继承时,会一直向上找 C3-->C2-->C0 ,实在找不到才会去找C1(一条道路走到黑)

 

 

   2,  有共同父类的多继承

 1 class C_2:
 2     def f2(self):
 3         print("C_2.f2")
 4         pass
 5 
 6 class C_1(C_2):
 7     def f5(self):
 8         print("C_2.f2")
 9         pass
10 
11 class C0(C_2):
12     def f6(self):
13         print("C0.f2")
14 
15 class C1(C0):
16     def f2(self):
17         print("C1.f2")
18         pass
19 
20 class C2(C_1):
21     def f4(self):
22         print("C2.f2")
23         pass
24 
25 class C3(C2, C1):  # 谁在前面就就先继承谁(如果C1和C2当中有相同的方法就可以体现出来)
26     def f3(self):
27         pass
28 
29 obj = C3()
30 obj.f2()
例子7,有共同父类的多继承

小结:当有共同的父类时,会从前面类顺着继承找到顶端,但不会找到最后的父类,如果还找不到,则会从另一路继承开始找,父类最后执行!

如图所示:C2是他们共同的父类,C3 -->C2--> C_1(不找最后的父类),如果还找不到,则从C1-->C0-->C_2

   

注意:
在python3+上有共同的父类继承都如上,因为在python3+,所有的类默认继承ojbect类。
但是在python2.7中:
1, 当没有共同的父类时和python3+是一样的,
2, 当有共同的父类时,python2.7默认会前面类顺着继承找到顶端,而且会找到最后的父类。
但是如果让最后的父类继承object类之后,执行顺序和python3+一样。因为在python3+默认
所有的类都继承object类

3, python2.7类分为:经典类和新式类,经典类会一条道走到黑,找到最顶端。而新式类(即继承object)
类之后,和python3+一样

 

  3,  多继承问题的实例

 1 class C1:
 2     def forever(self):
 3         self.run()
 4 
 5 class C2(C1):
 6     def __init__(self):
 7         pass
 8 
 9     def run(self):
10         self.process()
11 
12     def process(self):
13         print("C2.process")
14 
15 class C3(C2):
16     def __init__(self):
17         pass
18 
19 class C4:
20     def process(self):
21         print("C4_process")
22 
23 class C5(C4, C3):
24     pass
25 
26 obj = C5()
27 obj.forever()
28 
29 
30 结果如下:
31 
32 C4_process
例子8,多继承的实例,以后在看源码时经常碰到!!!一定要理解!

对执行过程进行分析:

1,首先obj = C5(),这一步就决定:第一步先找执行C5下面的__init__方法,C5下面没有__init__方法,紧接着去找C4下面的__init__方法(也没有),再找C3下面的__init__方法,有并执行。

2,执行obj.forever(), C5(没有forever方法)--> C4(也没有) --> C3(也没有) --> C2(也没有) --> C1(有并执行forever方法,forever下有run()方法,此时的run.self中的self仍为obj,因此从根开始找)--> C5(没有)--> C4(没有) --> C3(没有) --> C2(有并执行,但是此时run()中还有process方法,同上从根开始找) --> C5(没有)--> C4(有,并执行)--> 结束!

以上是关于面向对象的主要内容,如果未能解决你的问题,请参考以下文章

面向面试编程代码片段之GC

PHP面向对象之选择工厂和更新工厂

Java中面向对象的三大特性之封装

python之路之前没搞明白4面向对象(封装)

Scala的面向对象与函数编程

Python面向对象学习之八,装饰器