面向对象初始

面向对象

 

 

 

      • 概念:具有相同属性和技能的一个事物。

      • 面向对象的好处:

          1. 使得代码之间的角色关系更加清晰
          2. 增强了代码的可拓展性。
          3. 约束了对象的属性和功能。 

   

      • 面向对象的特点:
          1. 结局的不确定性。
          2. 不关注程序过程的执行。只关注程序中的对象以及对象之间的关系
      • 类名  
        • 引用静态变量
          • 查看静态变量的方式:
            1. A.__dict__["静态变量”]:只能查看,不能修改、删除。
            2. A.静态变量:可以查看、修改、删除。      
        • 引用动态变量(方法、动态属性:默认带一个self的参数,)
            • 类名+方法名 查看这个方法的内存地址。
            • 类名+方法名(实参),调用了这个方法,必须传一个参数给self。
      • 类名+():相当于创建了一个实例,等同于创建了一个对象。即对象or实例 = 类名+()
      • 实例化过程:
          1. 创建了一个实例,将会作为一个实参。
          2. 自动触发了__init__函数,并将实例作为一个实参传给了self。
          3. 执行完__init__函数后,将self自动返回给调用者。
      • __init__: 是一个初始化方法,是给一个对象添加基础属性的方法,一般用于self赋值。 

 

 

    • 对象 

      • 概念:对一个类的具体描述

        • 在类的内部,self就是类的对象

        • 在类的外部,每个对象都对应着一个名称,这个对象指向对象的内存空间。 

 

      • 属性的调用
        • 对象名.属性    (点调用法)
        • 对象名.__dict__[属性名]          
      • 方法的调用
        • 类名+方法名+(对象名):方法中的self指向对象本身
        • 对象名.方法名+():方法中的self直接指向这个对象。    

 

 

    • 类命名空间与对象的命名空间

      • 创建一个类就会创建一个类的命名空间,用来储存类的属性以及所含有的方法。属性包括静态属性以及动态属性(方法)。

          • 其中类的属性是可以共享给所有对象的。

          • 方法是绑定到具体的对象的。对象通过自己内存空间的类对象指针找到类的方法。

      • 对象的内存空间只存储对象的特有属性,不存储类的静态属性以及方法。
      • 方法和静态属性存储在类的内存空间中,为了节省内存,让多个对象共享类的属性以及方法
      • 对象使用名字调用属性,先从自己的内存空间查找,然后再从所属类的内存空间查找。
      • 对于静态属性的修改,使用类名类调用属性来修改。    

 

 

    • 组合 

      • 定义:一个类的对象作为一个类对象的属性。大白话就是什么有什么。

      • 作用:有些对象没发独立发挥它的作用,所以必须依赖其他对象,所以用到了组合。

    • 交互

      • 定义:将一个对象作为一个参数传递给类的方法。

 

面向对象的三大特性

    • 继承

      • 父类:基类、超类;   子类:派生类  

      • 类型

        • 单继承

          • __bases__为内置属性,可以查看一个类的父类
          • python中所以类的父类默认继承object,继承了object类的都叫新式类。
          • 如果一个类中没有继承f父类,就默认继承了object类。  
        • 多继承                  

 

  

 

    • 封装

      • 定义:函数和属性装到了一个非非全局的命名空间称为封装。

      • 作用:隐藏对象的属性和实现细节,仅对外提供公共访问方式。

      • 原则:
          1. 将不需要对外提供的内容都隐藏起来;
          2. 把属性都隐藏,提供公共方法对其访问。
      • 私有属性以及私有方法
        • 私有属性  
          • 定义一个私有名字就是在私有名字前面加两天下划线“__”,所谓私有,就是不能在类的外面去引用他。 
          • 一个私有名字在存储过程中,仍然会出现在A.__dict__中。
          • python对名字进行了修改:_类名__名字。在类的外部调用,必须得用_类名__方法名调用。而在内部可以正常调用:类名.__名字。
          • 这种变形其实正是针对外部的变形,在外部是无法通过__x这个名字访问到的。  

 

1 class A:
2     __N = 'aaa'  # 静态变量
3     def func(self):
4         print(A.__N)  # 在类的内部使用正常
5         print(A._A__N)  ##类中所有的双下划线都会自动变形为:_类名__x的形式

6 7 a = A() 8 a.func() 9 print(A.__N) # 在类的外部直接使用 报错

 

        • 私有方法
1 class C:
2     def __wahaha(self):     ##方法也可以私有化,只需要给方面名前面加上两下划线就ok
3         print('wahaha')
4     def ADCa(self):
5         self.__wahaha()
6 c = C()
7 c.ADCa()
      • 在子类定义的__x不会覆盖在父类定义的__x,因为子类中变形成了:_子类名__x,而父类中变形成了:_父类名__x,即双下滑线开头的属性在继承给子类时,子类是无法覆盖的。          
1 class D:
2     def __func(self):      # '_D__func'
3         print('in func')
4 
5 class E(D):
6     def __init__(self):
7         self.__func()      # '_E__func'
8 e = E()
报错
 1 class D:
 2     def __init__(self):
 3         self.__func()       ###在D中调用_D__func() ,所以输出 'in D'
 4     def __func(self):
 5         print('in D')
 6 
 7 class E(D):
 8     def __func(self):
 9         print('in E')
10 e = E()                 ##实例化E,子类没有__init__方法,自动触发父类的__init__方法
1 class F:
2     pass
3 F.__name = 'alex'  # 不是在创建私有属性,变形只在类的内部发生
4 print(F.__name)  
5 print(F.__dict__)


输出结果:
alex

{'__module__': '__main__', '__dict__': <attribute '__dict__' of 'F' objects>, '__weakref__': <attribute '__weakref__' of 'F' objects>, '__doc__': None, '__name': 'alex'}

          • 与java的对比 
            • 公有的public:在类的内部可以使用,子类可以使用,外部可以使用。python中所有正常的名字;
            • 保护的protect:在类的内部可以使用,子类可以使用,外部可以使用,python中没有
            • 私有的private:只有在类的内部可以使用,外部以及子类不可使用。python中的双下划线“__”名字。
      • 私有的用法
          • 当一个方法不想被子类继承的时候;
          • 有些属性或者方法不希望外部调用,只想提供给内部方法调用的时候。

 

 

 

    • property

      • property是一种特殊的属性,访问它时会执行一段功能(函数)然后返回值。用来将一个方法伪装成一个属性。  

      • 作用:

        1. @property 可以将一个方法伪装成为一个属性。

        2. 从原来的的对象名+'.'+方法名+()变为 对象名+'.'+方法。   

 1 class Person:
 2     def __init__(self,name,weight,height):
 3         self.name = name
 4         self.__height = height
 5         self.__weight = weight
 6     @property
 7     def bmi(self):
 8         return self.__weight / self.__height ** 2
 9 print(Person.__dict__)
10 p = Person('大表哥',92,1.85)
11 print(p.__dict__)
12 print(p.bmi)   # 对这个属性 只能看了
        • 被property装饰的方法仍然是个方法,存在类的dict中;
        • 对象的__dict__不会储存这个伪属性。
        • 在一个类的加载过程中,会先加载这个类中的名字,包括被property装饰的名字,在实例化对象的时候,python解释器会到类的空间里看看有没有被这装饰的属性,如果有的话,实例化的时候就不能在自己的对象空间里创建这个属性了。
      • 修改被@property修饰的属性
 1 class Person:
 2     def __init__(self,n):
 3         self.__name = n  # 私有的属性了
 4     @property
 5     def name(self):
 6         return self.__name
 7 
 8     @name.setter        # 重要程度 ***
 9     def name(self,new_name):
10         if type(new_name) is str:
11             self.__name = new_name
12         else:
13             print('您提供的姓名数据类型不合法')
14 
15 p = Person('alex')
16 print(p.name)       #def name(self):
17 p.name = 'sb' #def name(self,new_name):        #调用了被time.setter装饰的函数,然后将sb赋值给new_name,对私有属性 name 进行修改。
18 print(p.name)       #def name(self):
19 p.name = 123 #def name(self,new_name):
20 print(p.name)       #def name(self):

      • 删除被@property装饰的属性

  

 1 class Person:
 2     def __init__(self,n):
 3         self.__name = n  # 私有的属性
 4     @property           
 5     def name(self):
 6         return self.__name
 7     # @name.deleter
 8     # def name(self):
 9     #     print('name 被删除了')
10     @name.deleter         # 重要程度*
11     def name(self):
12         del self.__name
13 
14 p = Person('alex')
15 print(p.name)
16 del p.name  # 只是执行了被@name.deleter装饰的函数 ####del p.name  会执行被@name.deleter修饰的函数
17 print(p.name)

 

      • 总结:
        @property --> func     将方法伪装成属性,只管看的事儿;
        @func.setter --> func 对伪装的属性进行赋值的时候调用这个方法 一般情况下用来做修改
        @func.deleter --> func 在执行del 对象.func的时候调用这个方法 一般情况下用来做删除 基本不用;

 

          将一些需要随着一部分属性的变化而变化的值的计算过程 从方法 伪装成属性
          将私有的属性保护起来,让修改的部分增加一些约束,来提高程序的稳定性和数据的安全性



    • classmethod

      • 类方法,可以直接被类调用,不需要默认传参数,只需要传一个类参数就行了。不依赖对象的方法,就应该定义为类方法,可以任意操作类中的静态变量。

      • 由于不是用对象内存空间中的属性,所以不会将对象和方法绑在一起,而是将类和方法绑定到一起。对象依然可以通过类对象指针找到与类绑定的类方法。

 

 1 class Goods:
 2     __discount = 0.8
 3     def __init__(self,name,ori_price,):
 4         self.name = name
 5         self.__ori_price = ori_price
 6     @property
 7     def price(self):
 8         return self.__ori_price*Goods.__discount
 9     @classmethod
10     def change_discount(cls,new_discount):
11         cls.__discount = new_discount
12 
13 
14 Goods.change_dicount(0.5)   ###不依赖对象的方法,直接用类方法对类的静态属性进行修改。
15 apple = Goods("Apple",10)
16 mango = Goods("Mango",20)
17 print(apple.price)
18 print(mango.price)
    • staticmethod

      • 定义:静态方法没有默认参数,当成普通的函数使用即可。

      •  

        
        

        不是绑定方法,没有和任何对象或者类发生任何的绑定。 

         

     

    •  
      使用什么样的方法要看具体用到了哪些名称空间中的变量
      当一个方法要使用对象的属性时 就是用普通的方法
      当一个方法要使用类中的静态属性时 就是用类方法
      当一个方法要既不使用对象的属性也不使用类中的静态属性时,就可以使用staticmethod静态方法
        

 

              

 

            

            

      

                      

 

posted on 2018-04-10 16:20  弃疾  阅读(136)  评论(0)    收藏  举报

导航