诚意
诚意如你,当一诚的态度对待

导航

 

1     面向对象的介绍

1.1   函数式编程和面向对象的对比

1.1.1 第一轮对比

1.1.1.1  函数式编程

 1 def email(em,text):
 2     """
 3     发送邮件
 4     :return:
 5     """
 6     print(em,text)
 7 
 8 def msg(tel,text):
 9     """
10     发送短信
11     :return:
12     """
13     print(tel,text)
14 
15 def wechat(num,text):
16     """
17     发送微信
18     :return:
19     """
20     print(num,text)
21 
22 
23 # 编写功能:假设用户购买课程,然后给alex发送提醒;
24 if 1==1:
25     msg('188888888','张进购买了一个学位课')
26     email('alex@sb.com','张进购买了一个学位课')
27     wechat('xxxx','张进购买了一个学位课')
View Code

1.1.1.2  面向对象编程

 1 class Message:
 2     def email(self, em, text):
 3         """
 4         发送邮件
 5         :return:
 6         """
 7         print(em,text)
 8 
 9     def msg(self, tel, text):
10         """
11         发送短信
12         :return:
13         """
14         print(tel,text)
15 
16     def wechat(self, num, text):
17         """
18         发送微信
19         :return:
20         """
21         print(num,text)
22 
23 
24 # 编写功能:假设用户购买课程,然后给alex发送提醒;
25 if 1==1:
26     obj = Message()
27     obj.email('alex@sb.com', '张进购买了一个学位课')
28     obj.msg('188888888','张进购买了一个学位课')
29     obj.wechat('xxxx','张进购买了一个学位课')
View Code

 

1.1.1.3  第一轮对比:

函数: 定义简单/调用简单

面向对象: 定义复杂/调用复杂   好处:归类,将某些类似的函数写在一起

 

 

1.1.1.4  第一轮的总结:

1. 函数式编程可能会比面向对象好.

2. Python中支持两种编程方式.

3. 面向对象方式格式:

定义:

       class 类名:                                  - 定义了一个类

              def 函数名(self):            - 在类中编写了一个"方法"

                     pass

调用:

       x1 = 类名()                                 - 创建了一个对象/实例化一个对象

       x1.函数名()                                 - 通过对象调用其中一个方法.

注意:这里的self参数是把实例化后的对象名传过去,因此self是xx类的xx对象

 

4. 示例:

 1 class Account:
 2     def login(self):
 3         user = input('请输入用户名:')
 4         pwd = input('请输入密码:')
 5         if user == 'alex' and pwd == 'sb':
 6             print('登录成功')
 7         else:
 8             print('登录失败')
 9 
10 obj = Account()
11 obj.login()
View Code

1.1.2 第二轮对比

"""

完成以下功能:

老狗/20岁/男/上山去砍柴

老狗/20岁/男/开车去东北

老狗/20岁/男/喜欢大宝剑

"""

1.1.2.1  函数式编程:

 1 def kc(name,age,gender):
 2 
 3        data = "%s,性别%s,今年%s岁,喜欢上山砍柴" %(name,gender,age)
 4 
 5        print(data)
 6 
 7  
 8 
 9 def db(name,age,gender):
10 
11        data = "%s,性别%s,今年%s岁,喜欢开车去东北" %(name,gender,age)
12 
13        print(data)
14 
15  
16 
17 def bj(name,age,gender):
18 
19        data = "%s,性别%s,今年%s岁,喜欢大宝剑" %(name,gender,age)
20 
21        print(data)
22 
23  
24 
25 kc('老狗',20,'')
26 
27 kc('老狗',20,'')
28 
29 db('老狗',20,'')
30 
31 bj('老狗',20,'')
View Code

 

1.1.2.2  面向对象编程:

 1 class LaoGou:
 2 
 3        def __init__(self,name,age,gender): # 特殊的方法,如果 类名() ,则该方法会被自动执行 (构造方法)
 4 
 5               self.n1 = name
 6 
 7               self.n2 = age
 8 
 9               self.n3 = gender
10 
11 def kc(self):
12 
13               data = "%s,性别%s,今年%s岁,喜欢上山砍柴" %(self.n1,self.n3,self.n2)
14 
15               print(data)
16 
17        def db(self):
18 
19               data = "%s,性别%s,今年%s岁,喜欢开车去东北" %(self.n1,self.n3,self.n2)
20 
21               print(data)
22 
23        def bj(self):
24 
25               data = "%s,性别%s,今年%s岁,喜欢大宝剑" %(self.n1,self.n3,self.n2)
26 
27               print(data)
28 
29 obj = LaoGou('老狗',20,'')
30 
31 obj.kc()
32 
33 obj.db()
34 
35 obj.bj()
View Code

 

1.1.2.3  第二轮对比(构造方法,在实例化的时候就已经自动运行类里的__init__()了

构造方法

示例一:

       class Foo:

              def __init__(self,name):     构造方法,目的进行数据初始化.

                 self.name = name

                 self.age = 18

                 obj = Foo('侯明魏')

通过构造方法,可以将数据进行打包,以后使用时,去其中获取即可.

示例二:   

       class Bar:

              pass

       obj = Bar()

 

1.1.2.4  构造方法的应用

1.1.2.4.1     将数据封装到对象中,以供自己在方法中调用
 1 class FileHandler:
 2 
 3        def __init__(self,file_path):
 4 
 5               self.file_path = file_path
 6 
 7               self.f = open(self.file_path, 'rb')
 8 
 9        def read_first(self):
10 
11               pass
12 
13        def read_last(self):
14 
15               pass
16 
17 def read_second(self):
18 
19               pass
20 
21                                                 
22 
23 obj = FileHandler('C:/xx/xx.log')
24 
25 obj.read_first()
26 
27 obj.read_last()
28 
29 obj.read_second()
30 
31 obj.f.close()

 

把数据封装在self也就是obj对象中,调用方法就会用到self

 

1.1.2.4.2     将数据封装到对象中,以供其他函数调用
 1 def new_func(arg):
 2 
 3        arg.k1
 4 
 5        arg.k2
 6 
 7        arg.k6
 8 
 9  
10 
11 class Foo:
12 
13        def __init__(self,k1,k2,k6):
14 
15               self.k1 = k1
16 
17               self.k2 = k2
18 
19               self.k6 = k6
20 
21 obj = Foo(111,22,333)
22 
23 new_func(obj)

数据封装在对象obj里,然后可以参数形式传给其他函数,这样函数使用参数时就会带哦用参数。

 

练习: 信息管理系统

1. 用户登录

2. 显示当前用户信息

3. 查看当前用户所有的账单

4. 购买姑娘形状的抱枕

 1 class UserInfo:
 2 
 3        def __init__(self):
 4 
 5               self.name = None
 6 
 7        def info(self):
 8 
 9               print('当前用户名称:%s' %(self.name,))
10 
11        def account(self):
12 
13               print('当前用户%s的账单是:....' %(self.name,))
14 
15        def shopping(self):
16 
17               print('%s购买了一个人形抱枕' %(self.name,))
18 
19        def login(self):
20 
21               user = input('请输入用户名:')
22 
23               pwd = input('请输入密码:')
24 
25               if pwd == 'sb':
26 
27                      self.name = user        #此时对象的name有东西了
28 
29                      while True:
30 
31                             print("""
32 
33                                    1. 查看用户信息
34 
35                                    2. 查看用户账单
36 
37                                    3. 购买抱枕
38 
39                                    """)
40 
41                             num = int(input('请输入选择的序号:'))
42 
43                             if num == 1:
44 
45                                    self.info()
46 
47                             elif num ==2:
48 
49                                    self.account()
50 
51                             elif num == 3:
52 
53                                    self.shopping()
54 
55                             else:
56 
57                                    print('序号不存在,请重新输入')
58 
59                             else:
60 
61                                    print('登录失败')
62 
63 obj = UserInfo()
64 
65 obj.login()
View Code

 

1.1.1 第三轮

 1 users = ['梁慧','朱奎峰','刘炳旭'...]  # list()
 2  # 完全可以实现
 3 
 4  users = [
 5 
 6                  {'name':'梁慧','age':18}, # 全栈15期%s,年龄:%s
 7 
 8                  {'name':'朱奎峰','age':18},
 9 
10                  {'name':'刘炳旭','age':18},
11 
12                    ] # list()
13 
14                            
15   for item in users:
16 
17           temp = "全栈15期%s,年龄:%s " (item['name'],item['age'])
18 
19            print(temp)
20 
21                            
22 
23                            
24 # 代码拆分,使得业务逻辑代码更加简洁
25 
26                            
27 class Person(object):
28 
29          def __init__(self,name,age):
30 
31                  self.name = name
32 
33                   self.age = age
34 
35                                          
36 
37         def message(self):
38 
39                    return "全栈15期%s,年龄:%s " (self.name,self.age)
40 
41                            
42 
43 users = [ Person('梁慧',18), Person('朱奎峰',18), Person('刘炳旭',18)  ]
44 
45                            
46 
47            for obj in users:
48 
49                  print(obj.message())
View Code

2     面向对象代码如何编写

2.1   规则:

       class Foo:           定义类

              def __init__(self,name):   构造方法

                     self.name = name

              def detail(self,msg):

                     print(self.name,msg)

      obj = Foo()    类的实例化----》对象

      obj.detail()     对象调用类里的方法

 

2.2   什么时候写?如何写?

2.2.1 方式一:归类+提取公共值

2.2.1.1  归类

 1 class File:
 2 
 3        def file_read(self,file_path):
 4 
 5               pass
 6 
 7        def file_update(self,file_path):
 8 
 9               pass
10 
11 def file_delete(self,file_path):
12 
13               pass
14 
15        def file_add(self,file_path):
16 
17               pass
18 
19 class Excel:
20 
21        def excel_read(self,file_path):
22 
23               pass
24 
25        def excel_update(self,file_path):
26 
27               pass
28 
29        def excel_delete(self,file_path):
30 
31               pass
32 
33        def excel_add(self,file_path):
34 
35               pass
View Code

 

2.2.1.2  提取公共值

 1 class File:
 2 
 3        def __init__(self,file_path):
 4 
 5               self.file_path = file_path
 6 
 7        def file_read(self):
 8 
 9               pass
10 
11        def file_update(self):
12 
13               pass
14 
15        def file_delete(self):
16 
17               pass
18 
19        def file_add(self):
20 
21               pass
22 
23 class Excel:
24 
25        def __init__(self,file_path):
26 
27               self.file_path = file_path
28 
29        def excel_read(self):
30 
31               pass
32 
33        def excel_update(self):
34 
35               pass
36 
37        def excel_delete(self):
38 
39               pass
40 
41        def excel_add(self):
42 
43               pass
View Code

 

2.2.2 方式二:在指定类中编写和当前类相关的所有代码 + 提取公共值

 1 class Message:
 2 
 3        def email(self):      
 4 
 5               pass
 6 
 7 class Person:
 8 
 9        def __init__(self,na, gen, age, fig)
10 
11               self.name = na
12 
13               self.gender = gen
14 
15               self.age = age
16 
17               self.fight =fig
18 
19        def grassland(self):
20 
21               self.fight = self.fight - 10 
22 
23        def practice(self):
24 
25               self.fight = self.fight + 90  
26 
27        def incest(self):
28 
29               self.fight = self.fight - 666
30 
31 cang = Person('苍井井', '', 18, 1000)    # 创建苍井井角色
32 
33 dong = Person('东尼木木', '', 20, 1800)  # 创建东尼木木角色
34 
35 bo = Person('波多多', '', 19, 2500)      # 创建波多多角色
36 
37 dong.grassland()
View Code

 

3     面向对象的三大特性

3.1   封装

3.1.1 将相关功能封装到一个类中:

class Message:

       def email(self):pass

       def msg(self):pass

       def wechat(self):pass

 

3.1.2 将数据封装到一个对象中:

class Person:

       def __init__(self,name,age,gender):

              self.name = name

              self.age = age

              self.gender = gender

obj = Person('孙福来',18,'女')

 

class Person:

       def __init__(self,name,age,gender):

              self.name = name

              self.age = age

              self.gender = gender

obj = Person('孙福来',18,'')


-------------

obj.xxxx=123   #在类的外面用对象的方式封装了一个变量放到类里

 

3.2   继承->复用

类自动继承object类

3.2.1 为何会有继承?

提高代码的重用性

3.2.2 单继承(基本使用)

 1 class Base:  #父类,基类
 2 
 3        def f2(self):
 4 
 5               print('f2')
 6 
 7 class Foo(Base):        # 子类,派生类
 8 
 9        def f1(self):
10 
11               print('f1')
12 
13 obj = Foo()
14 
15 obj.f2()

注意:obj 是 Foo的对象,调用时,首先到Foo类里,obj把自己作为参数传给self,self就是obj.此时如果Foo类里找不到,在去Foo类的父类里面找,记住此时self依旧是Foo类

原则:现在自己类中找,么有就去父类

 

3.2.3 多继承

Java/c#/php等语言没有,子类可以继承多个父类.

原则:(先找左父类/再找右父类)

 1 class Base1:
 2 
 3     def show(self):
 4 
 5         print('Base1.show')
 6 
 7 class Base2:
 8 
 9     def show(self):
10 
11         print('Base2.show')
12 
13 class Foo(Base1,Base2):
14 
15     pass
16 
17 obj = Foo()
18 
19 obj.show()

练习:

1. 多继承先找左边

2. self到底是谁,self是那个类的对象,那么就从该类开始找(自己没有就找父类)

 1 class Base1:
 2 
 3     def f1(self):
 4 
 5         print('base1.1')
 6 
 7     def f2(self):
 8 
 9         print('base1.f2')
10 
11 class Base2:
12 
13     def f1(self):
14 
15         print('base2.f1')
16 
17     def f2(self):
18 
19         print('base2.f2')
20 
21     def f3(self):
22 
23         print('base2.f3')
24 
25         self.f1()
26 
27 class Foo(Base1,Base2):
28 
29     def f0(self):
30 
31         print('foo.f0')
32 
33         self.f3()
34 
35 obj = Foo()
36 
37 obj.f0()
38 
39  
View Code

分析:1:obj为Foo类的对象,首先必须明确这一点。
2:当obj.f0()时,先去Foo类里面寻找f0(),找到后执行f0(),
3:执行过程中self.f3(),此self是obj对象,先去Foo类里面寻找f3(),找不到就去父类中寻找
4:先从左边的父类中寻找,此时self也是obj,没有找到再去右边父类中寻找,在右边的父类中找到后执行遇到self.f1(),

5:先去Foo类里面寻找f1()----》按前面的顺序来

 

 

3.2.4 多继承方法顺序

3.2.4.1  先找左后找右

3.2.4.2  经典类&&新式类

Py2:(python2.3之后出现c3算法)

  经典类

  新式类:如果自己或者自己的前辈只要有人继承object,那么此类就是新式类

Py3:新式类

 

3.2.4.3  经典类查找继承顺序的方法

一条道走到黑(深度优先)(提到深度优先,想到广度优先,所谓广度优先,就是一层一层)

 

 

如上图,黑色是继承关系;绿色是查找顺序

 

3.2.4.4  新式类查找继承顺序的方法

新式类,C3算法实现(python2.3更新时c3算法)

3.2.4.4.1     先设定几个定义:
  • 表头: 
    列表的第一个元素
  • 表尾: 
    列表中表头以外的元素集合(可以为空)
  • 示例 
    列表:[A, B, C] 
    表头是A,表尾是B和C
3.2.4.4.2     c3算法的规则和案例

规则

获取第一个表头 和 其他表尾进行比较

       不存在则拿走。

       如果存在,则放弃,然后获取第二个表的表头再次和其他表的表尾进行比较。

 

 

 

案例:

以下图为例,利用c3算法计算继承顺序

 

 

Foo +Merg [E] + Merg [H]

 

Merg [E]=[D,object]+[C,B,A,object]

(1)左边的表头D拿出来,与各个列表的表尾比较发现不在表尾,拿出此时顺序是E,D

       (2)[object]+[C,B,A,object],拿出左边列表的表头与各个列表的表尾比较发现在其他表。然后左边的列表并不是最后一个,跳过这个左边的列表,下次比较的是下一个列表的表头

       (3)[C,B,A,object]拿出表头C,与各个列表的表尾比较,发现不再所有列表表尾,拿出来,此时继承顺序是E,D,C;继续跳到第一个列表,第一个列表object在其他列表中表尾中有,在跳到下一个表的

       (4)[B,A,object] 拿出表头B,与各个列表的表尾比较,发现不再所有列表表尾,拿出来,此时继承顺序是E,D,C,B;继续跳到第一个列表,第一个列表object在其他列表中表尾中有,在跳到下一个表的

       (5) [A,object] 拿出表头A,与各个列表的表尾比较,发现不再所有列表表尾,拿出来,此时继承顺序是E,D,C,B,A;继续跳到第一个列表,第一个列表object在其他列表中表尾中有,在跳到下一个表的;此时就只剩下[object]+ [object]

       (6)[object]+ [object],----》object,最后继承顺序是E,D,C,B,A,object

注意:每次在第一个列表与其他列表表尾比较时,,这个数据不动,发现有的话,跳到下一个列表的表头在比较,直到能比较拿出来为止,注意,比较完成后要再次跳到第一个列表

 

Merg [H]= [C,B,A,object]+ [G,F,object]

       [H,C,B,A,G,F,object]

 

Foo +Merg [E] + Merg [H]

= Foo  +  [E,D,C,B,A,object]+ [H,C,B,A,G,F,object]

=[ Foo,E,D,H,C,B,A,G,F,object]

 

检验方法:

 1 class A:
 2     pass
 3 class B(A):
 4     pass
 5 class C(B):
 6     pass
 7 class D:
 8     pass
 9 class E(D,C):
10     pass
11 class F:
12     pass
13 class G(F):
14     pass
15 class H(C,G):
16     pass
17 class Foo(E,H):
18     pass
19 
20 print(E.__mro__)
21 print(H.__mro__)
22 print(Foo.__mro__)
23 
24 答案:
25 
26 (<class '__main__.E'>, <class '__main__.D'>, <class '__main__.C'>, <class '__main__.B'>,   <class '__main__.A'>, <class 'object'>)
27 
28 (<class '__main__.H'>, <class '__main__.C'>, <class '__main__.B'>, <class '__main__.A'>, <class '__main__.G'>, <class '__main__.F'>, <class 'object'>)
29 
30 (<class '__main__.Foo'>, <class '__main__.E'>, <class '__main__.D'>, <class '__main__.H'>, <class '__main__.C'>, <class '__main__.B'>, <class '__main__.A'>, <class '__main__.G'>, <class '__main__.F'>, <class 'object'>)
View Code

 

 

 

3.3   多态

多种形态或多种状态

def func(arg):

       arg.f1()

 

如上面的参数的类型并不能确定。所以python本身就具备多态的能力

 

 

鸭子类型:

参考鸭子类型,鸭子类型(英语:duck typing)是动态类型的一种风格。在这种风格中,一个对象有效的语义,不是由继承自特定的类或实现特定的接口,而是由"当前方法和属性的集合"决定。这个概念的名字来源于由James Whitcomb Riley提出的鸭子测试,“鸭子测试”可以这样表述:

“当看到一只鸟走起来像鸭子、游泳起来像鸭子、叫起来也像鸭子,那么这只鸟就可以被称为鸭子。”

在鸭子类型中,关注的不是对象的类型本身,而是它是如何使用的。例如,在不使用鸭子类型的语言中,我们可以编写一个函数,它接受一个类型为"鸭子"的对象,并调用它的"走"和"叫"方法。在使用鸭子类型的语言中,这样的一个函数可以接受一个任意类型的对象,并调用它的"走"和"叫"方法。如果这些需要被调用的方法不存在,那么将引发一个运行时错误。任何拥有这样的正确的"走"和"叫"方法的对象都可被函数接受的这种行为引出了以上表述,这种决定类型的方式因此得名。

鸭子类型通常得益于"不"测试方法和函数中参数的类型,而是依赖文档、清晰的代码和测试来确保正确使用。

 

posted on 2018-08-27 17:28  诚意  阅读(154)  评论(0)    收藏  举报