Python快速入门04


  1. 对象是把数据与功能整合到一起的产物,或者说对象就是一个盛放数据与功能的容器
  2. 类是用来存放多个对象相同的数据与功能的容器,是一种节省空间、减少冗余代码的机制,面向对象编程最终的核心仍然是去使用对象
  3. 类体的代码在类定义阶段就会执行,所以会产生新的名称空间来存放类中定义的名字。
  4. class Student:
        school = '清华大学'
        # __init__方法会在对象产生之后自动执行,专门为对象进行初始化操作,可以有任意代码,但是必须得返回None或者不写也是返回None
        def __init__(self,name,sex,age):
            self.name = name
            self.sex = sex
            self.age = age
            # return '1'
    
        def choose(self):
            print('%s is chooseing a course' %self.name)
    
    print(Student.__dict__)
    
    stu1 = Student('张三','',12)
    stu2 = Student('李四','',24)
    stu3 = Student('王五','',36)
    print(stu1.__dict__)
    print(Student.__dict__['school'])  # 这种访问方式过于繁琐
    print(Student.school)
    stu1.choose()
    print(id(Student.choose))
    print(id(stu1.choose))
    print(id(stu2.choose))
    print(id(stu3.choose))
    
    print(stu1.choose)
    print(stu2.choose)
    print(stu3.choose)
    
    stu1.choose()
    stu2.choose()
    stu3.choose()
    
    print(list)
  5. class Foo:
        __N = 0
    
        def __init__(self):
            self.__x = 10
    
        def __f1(self):
            print('__f1 run')
    
        def __f2(self):
            self.__f1()
    
    
    
    
    # print(Foo.__N)
    print(Foo._Foo__N)
    obj = Foo()
    print(obj._Foo__x)
    
    Foo._Foo__f1(obj)
    
    Foo._Foo__f2(obj)
    
    Foo.__N = 100
    print(Foo.__N)
  6. class Teacher:
    
        def __init__(self, name=None, age=0):
            # 姓名、年龄对外设置隐藏
            self.__name = name
            self.__age = age
    
        # 隐藏并不是目的要对外提供可访问的接口
        def tell_info(self):
            print('我的姓名是%s,我的年龄是%s' %(self.__name,self.__age))
    
        # 允许外部对老师的姓名年龄进行设置
        def set_info(self,name,age):
            if not isinstance(name,str):
                raise TypeError('姓名必须是字符串类型')
            if not isinstance(age,int):
                raise TypeError('年龄必须是整数类型')
    
            self.__name = name
            self.__age = age
    
    
    t = Teacher('张三',23)
    t.tell_info()
    t1 = Teacher()
    t1.set_info('里斯',24)
    # t1.set_info('里斯','24')
    # t1.set_info(23,'24')
    t1.tell_info()
  7. >>> class ATM:
    ...     def __card(self): #插卡
    ...         print('插卡')
    ...     def __auth(self): #身份认证
    ...         print('用户认证')
    ...     def __input(self): #输入金额
    ...         print('输入取款金额')
    ...     def __print_bill(self): #打印小票
    ...         print('打印账单')
    ...     def __take_money(self): #取钱
    ...         print('取款')
    ...     def withdraw(self): #取款功能
    ...         self.__card()
    ...         self.__auth()
    ...         self.__input()
    ...         self.__print_bill()
    ...         self.__take_money()
    ...
    >>> obj=ATM()
    >>> obj.withdraw()
  8. Python提供了一个装饰器property,可以将类中的函数"伪装"成对象的数据属性,对象在访问该特殊属性时会触发功能的执行,然后将返回值作为本次访问的结果
    >>> class People:
    ...     def __init__(self,name,weight,height):
    ...         self.name=name
    ...         self.weight=weight
    ...         self.height=height
    ...     @property
    ...     def bmi(self):
    ...         return self.weight / (self.height**2)
    ...
    >>> obj=People('lili',75,1.85)
    >>> obj.bmi #触发方法bmi的执行,将obj自动传给self,执行后返回值作为本次引用的结果
    21.913805697589478
  9. 查看该类的所有父类
    #!/usr/bin/env python
    #author:lijipeng
    
    class Parent1:
        pass
    
    class Parent2:
        pass
    
    
    class Son1(Parent1,Parent2):
        pass
    
    print(Son1.__bases__)
  10. 经典类:没有显示的继承object类的类,以及该类的子类
  11. 新式类:显示的继承object类的类,以及该类的子类
  12. Python3中没有新式类和经典类之分,因为没有显示继承也会默认继承object类
  13. 总结对象与对象之间的相似关系可以得到类,总结类与类之间的相似关系可以得到父类
  14. 继承可以解决类与类之间代码重用的问题
  15. class Foo:
         def f1(self):
             print('Foo.f1')
         def f2(self):
             print('Foo.f2')
             self.f1()
    
    class Bar(Foo):
        def f1(self):
            print('Bar.f1')
    
    b = Bar()
    b.f2()
  16. 如果父类不想让子类覆盖自己的方法,可以采用双下划线开头的方式将方法设置为私有
    class Foo:
         def f1(self):
             print('Foo.f1')
         def __f2(self):
             print('Foo.f2')
             self.f1()
    
    class Bar(Foo):
        def f1(self):
            print('Bar.f1')
    
    b = Bar()
    b.f2()
  17. 类有一个mro()方法,它是一个合并了所有父类的MRO列表,且在查找属性时,Python会基于MRO列表按照从左到右的顺序依次查找基类,直到找到第一个匹配这个属性的类为止
  18. 经典类多继承深度优先,新式类多继承广度优先。
  19. 重用父类的代码的两种方式:指名道姓、super() 前者跟继承没有关系,后者是依赖于继承的,super()仍然会按照MRO继续往后查找
  20. #!/usr/bin/env python
    #author:lijipeng
    import abc
    
    # 指定metaclass属性将类设置为抽象类,抽象类本身只是用来约束子类的,不能被实例化
    class Animal(metaclass=abc.ABCMeta):
        @abc.abstractmethod # 该装饰器限制子类必须定义有一个名为talk的方法
        def talk(self): # 抽象方法中无需实现具体的功能
            pass
    
    class Cat(Animal): # 但凡继承Animal的子类都必须遵循Animal规定的标准
        # def talk(self):
        #     pass
        pass
    
    cat=Cat() # 若子类中没有一个名为talk的方法则会抛出异常TypeError,无法实例化
  21. 鸭子类型在某种程度上实现了程序的松耦合度
  22. 类中的函数分为两大类:绑定方法,非绑定方法
  23. 绑定方法又分为绑定到类的方法和绑定到对象的方法
  24. 类中的函数默认绑定到对象上,函数上面加@classmethod后,该函数就绑定到了类
  25. 为类中某个函数加上装饰器@staticmethod后,该函数就变成了非绑定方法,也称为静态方法。不与对象和类绑定,都可以来调用它,就是一个普通函数,所以没有自动传值一说。
  26. 功能实现代码需要引用对象将其定义为对象方法,需要引用类定义为类方法,无需引用类或对象定义为静态方法