• 💡 面向对象的抽象程度比函数要高,因为一个Class既包含数据,又包含操作数据的方法。数据封装、继承和多态是面向对象的三大特点

    类和实例

  • 如果没有合适的继承类,就使用object类,这是所有类最终都会继承的类

  • 注意到__init__方法的第一个参数永远是self,表示创建的实例本身,在__init__方法内部,可以把各种属性绑定到self,因为self就指向创建的实例本身
  • 类是创建实例的模板,而实例则是一个一个具体的对象,各个实例拥有的数据都互相独立、互不影响
  • 和静态语言不同,Python允许对实例变量绑定任何数据。对于两个实例变量,虽然它们都是同一个类的不同实例,但拥有的变量名称都可能不同

    访问限制

  • 如果要让内部属性不被外部访问,可以把属性的名称前加上两个下划线__变成私有变量,只有内部可访问

  • 在Python中,变量名类似__xxx__的,也就是以双下划线开头,并且以双下划线结尾的,是特殊变量,特殊变量是可以直接访问的

    1. bart = Student('Bart Simpson', 59)
    2. bart.get_name() #'Bart Simpson'
    3. bart.__name = 'New Name' # 设置__name变量!
    4. bart.__name #'New Name'
  • 表面上看,“成功”地设置了__name变量,但实际上这个__name变量和class内部的__name变量不是一个变量!内部的__name变量已经被Python解释器自动改成了__Student__name,而外部代码给bart新增了一个__name变量

    继承

  • 继承可以把父类的所有功能都直接拿过来,子类只需要新增自己特有的方法,也可以把父类不合适的方法覆盖重写

  • 动态语言的鸭子类型(看起来像鸭子,走起路来像鸭子)特点决定了继承不像静态语言那样是必须的

    获取对象信息

    使用type()

  • type('abc')==str #True

    使用isinstance

  • 优先使用instance()判断类型,可以将指定类型及其子类“一网打尽”,isinstance([1, 2, 3], (list, tuple))

    使用dir()

  • 可以使用dir()函数,返回一个包含字符串的list,比如获得一个str对象的所有属性和方法

  • 配合getattr()setattr()以及hasattr(),可以直接操作一个对象的状态
  • getattr(obj, 'z', 404),可以传入一个default参数,如果属性不存在,就返回默认值

    实例属性和类属性

  • 实例属性属于各个实例所有,互不干扰;类属性属于类所有,所有实例共享一个属性;不要对实例属性和类属性使用相同的名字,因为相同名称的实例属性将屏蔽掉类属性,而删除实例属性后,再使用相同的名称将访问到类属性