一,初始面向对象

面向过程的程序设计的核心是过程(流水线式思维),过程即解决问题的步骤,面向过程的设计就好比精心设计好一条流水线,考虑周全什么时候处理什么东西。

优点是:极大的降低了写程序的复杂度,只需要顺着要执行的步骤,堆叠代码即可。

缺点是:一套流水线或者流程就是用来解决一个问题,代码牵一发而动全身。

应用场景:一旦完成基本很少改变的场景,著名的例子有Linux內核,git,以及Apache HTTP Server等

 

类:(定义)

具有相同属性或技能的一类事物

而类有两种属性:静态属性和动态属性

  静态属性就是直接在类中定义的变量

  动态属性就是定义在类中的方法

对象: 具体类的表现

类体: 有两部分组成  

1, 静态变量(静态属性)

普通属性和静态属性,他们在定义和使用中有所区别,而最本质的区别是内存中保存的位置不同

   普通属性属于对象

   静态属性属于

2,方法(动态属性)

方法包括:普通方法、静态方法和类方法,三种方法在内存中都归属于类,区别在于调用方式不同。

   普通方法:由对象调用;至少一个self参数;执行普通方法时,自动将调用该方法的对象赋值给self

   类方法:由调用; 至少一个cls参数;执行类方法时,自动将调用该方法的复制给cls

  •   静态方法:由调用;无默认参数;

 

类名.__dict__查询类中所有内容(不能增,删,改)

类名.新变量=内容  增

类名.变量=新内容 改

del 类名.变量  删

类名+() 这个过程: 是实例化的一个过程(创建了一个对象)

类名() 实例化对象

实行了三步

  1,产生了一个实例 (对象,对象空间)

  2,把对象空间传给self ,执行__init__方法

  3,把这个对象的空间返回给调用者

对象的角度:

  对象.__dict__ 查询对象中的所有内容

  万能的点,可以修改对象中的所有内容

  对象操作类中的静态变量:只能查询和引用

对象调用类中的方法[工作中通过对象执行类中的方法,而不是通过类名]

 

对象空间和对象空间是相互独立的

1,静态属性(静态变量,静态字段)

2,动态属性(方法) self

3,类方法  @classmethod  默认参数:cls 

4,静态方法  @staticmethod 没有默认参数

5,特性  @property 引入它是为了让方法伪装成一个属性,在代码上没有本质的提升 其实就是普通方法的变种    (详细讲解在属性那篇博客中)

调用 

   对象名.动态属性()/类名.动态属性() 需要传参

  类名.静态变量(静态属性)/对象名.静态变量(静态属性)

  类名.类方法()/对象名.类方法()   不需要传入参数

  类名.静态方法()/对象名.静态方法()  

操作类中的方法(除了类方法,静态方法 需要类名调用之外,剩下的方法都要对象调用)

以上调用优先前面的一种

 

对象的命名空间中能存:

  对象属性

对象能调用的:

  对象属性

  类中的普通方法

组合 (让对象和对象之间发生关系)

  给一个类的对象封装一个属性,这个属性是另一个类的对象

对象.属性 : 先从对象空间中查找,找到到去本类空间查找,然后是父类查找...

类名.属性: 先从本类中查找,找不到再从父类中查找....  它无法查找对象空间的属性

面向对象的三大属性 : 继承,多态,封装

object 

类: 分为新式类和经典类

凡是继承object类型的类都是新式类,否则都是经典类

python 2X:(既有经典类,又有新式类,所有的类都默认不继承object类,都默认为经典类,但是可以叫他继承object)

python 3X (所有的类都为新式类,因为python 3X 默认都继承object)

class Person(Animal):     括号里的是父类(基类,超类) 括号外的是派生类(子类)

  pass

子类类名和子类实例化的对象可以访问父类的所有内容

  只执行父类的方法: 子类就不要定义与父类同名的方法

  只执行子类的方法: 在子类创建这个方法

  既要执行子类方法,又要执行父类方法(两种解决方案)

  1,父类名.__init__(self,name,sex,age)

  2,super().__init__(name,sex,age)   [其中super(子类名,self) 一般默认 ,不用打出来]

 

class Animal:
    def __init__(self,name,sex,age):
        self.name=name
        self.sex=sex
        self.age=age
    def eat(self):
        print('%s都需要进食'% self.name)
    def drink(self):
        print('%s都需要饮水'% self.name)


class Brid(Animal):
    def __init__(self,name,sex,age,wing):
        # Animal.__init__(self,name,sex,age)
        super().__init__(name,sex,age)
        self.wing=wing
    def laying_eggs(self):
        print('可以产蛋')
    def eat(self):
        # Animal.eat(self)
        super().eat()
        print('%s都需要吃虫子'% self.name)

class Cat(Animal):
    def mousetrap(self):
        print('可以抓老鼠')
class Dog(Animal):
    def housekeeping(self):
        print('可以看家')
b1=Brid('鹦鹉','',16,'绿翅膀')
b1.eat()
两种解决方法

 继承:

 

单继承: 新式类和经典类查询顺序一样

多继承:新式类:广度优先 

   经典类:深度优先 

多继承广度优先 根据mro-c3算法   可以用mro方法查看继承顺序

 

为什么会有继承:

  1,提高代码的复用性

  2,提高代码的维护性

  3,让类与类发生关系

 

 

A(B,C,D)

#首先找到A继承的三个类的深度继承顺序,放到一个列表中
L[B] = [B,D,F,H] #B往上面的继承顺序
L[C] = [C,E,G,H] #C往上面的继承顺序
L[D] = [D,F,H]   #D往上面的继承顺序

#第二步:A自己的广度,第一层
L[A] = [B,C,D]

list = [A,B,C,D,F,E,G,H,O]

#每个列表的第一个元素为头部,从第一个列表的头部开始找,找其他列表中尾部是否含有
这个类名,如果没有,提取出来放到一个列表中,如果有,找下一个列表的头部,循环下去
只要提取来一个,我们就从第一个列表的头部接着重复上面的操作.
1   [B,D,F,H]  [C,E,G,H]  [D,F,H]  [B,C,D]
2   [D,F,H]    [C,E,G,H]  [D,F,H]  [C,D]  #提取了头部的B,然后将其他列表头部的B删除,并将B放到list中
3   [D,F,H]    [E,G,H]  [D,F,H]  [D]      #因为第一个列表的D在其他列表的尾部存在,所以跳过D,然后找第二个列表的头部C,提取了头部的C,然后将其他列表头部的B删除,并将B放到list中

4   [H]    [H]  [H]  []  

第二题
#最高树杈的mro继承顺序

B 1   [B] [E] [D] [E,D]
  2   [] [E] [D] [E,D]
  3      [] [] [D] [D]
  
list_B = [B,E,D]

c 1   [C] [D] [F] [D,F]
  2   [] [D] [F] [D,F]
  3   [] [] [F] [F]
list_C = [C,D,F]

A 1 [A] [B,E,D] [C,D,F] [B,C]
  2 [] [B,E,D] [C,D,F] [B,C]
  3 [] [E,D] [C,D,F] [C]
  4 [] [D] [C,D,F] [C]
  5 [] [D] [D,F] []
  6 [] [] [F] []
  6 [] [] [] []
list_A [A,B,E,C,D,F]
mro-c3算法

多态:

 

python 没有多态,因为他处处都是多态(但是他有鸭子类型)

鸭子类型: 他看着像鸭子,他就是鸭子 (类中都有相同的方法,那么这些类就互称为鸭子

 

lass F1:
    pass


class S1(F1):

    def show(self):
        print 'S1.show'


class S2(F1):

    def show(self):
        print 'S2.show'

def Func(obj):
    print obj.show()

s1_obj = S1()
Func(s1_obj) 

s2_obj = S2()
Func(s2_obj) 

Python “鸭子类型”
鸭子类型

 抽象类与接口类

与java一样,python也有抽象类的概念但是同样需要借助模块实现,抽象类是一个特殊的类,它的特殊之处在于只能被继承,不能被实例化

为什么要有抽象类

    如果说是从一堆对象中抽取相同的内容而来的,那么抽象类就是从一堆类中抽取相同的内容而来的,内容包括数据属性和函数属性。

   比如我们有香蕉的类,有苹果的类,有桃子的类,但从这些类抽取相同的内容就是水果的类,吃水果时,要么吃一个具体的香蕉,要么吃一个具体的桃子, 但你永远吃不到一个叫水果的东西.

  从设计角度来看,如果类是从现实对象抽象而来,那么抽象类就是基于类抽象而来.

  从实现角度来看,抽象类与普通类的不同之处在于:抽象类中有抽象方法,该类不能被实例化,只能被继承,且子类必须实现抽象方法,这一点和接口有点相似,但其实不同

 

  

from abc import ABCMeta ,abstractmethod 
class Payment (metaclass=ABCMeta):
    @abstractmethod  #制定一个,就需要引用一次
    def pay(self):         #制定规范
        pass
class Alipay(Payment):
    def __init__(self,money):
        self.money=money
    def pay(self):
        print('用支付宝支付了%d元' % self.money)
class Jdpay(Payment):
    def __init__(self,money):
        self.money=money
    def pay(self):
        print('用京东支付了%d元' % self.money)
def pay(abc):            # 归一化设计
    abc.pay()
a1=Alipay(100)   
j1=Jdpay(1000)
pay(a1)
pay(j1)
抽象类实现方法和归一化设计

封装

广义的封装 : 把方法和属性都封装在一个类里,定义一个规范来描述一类事物.
 狭义的封装 : 私有化 只能在类的内部访问
 __静态变量,私有方法,私有的对象属性,私有的类方法,私有的静态方法
 在内存中存储 _类名__名字
为什么在类的内部可以使用双下划线访问 : 在类的内部使用,你就知道你在哪个类中
在子类中可以访问访问父类的私有变量么?不行
私有 : 不能在类的外部使用也不能被继承

  

 

 

 

 

 

  

 

  

 

posted on 2018-07-30 21:26  玫瑰制造丶  阅读(66)  评论(0)    收藏  举报