💡 面向对象的抽象程度比函数要高,因为一个Class既包含数据,又包含操作数据的方法。数据封装、继承和多态是面向对象的三大特点
类和实例
如果没有合适的继承类,就使用
object
类,这是所有类最终都会继承的类- 注意到
__init__
方法的第一个参数永远是self
,表示创建的实例本身,在__init__
方法内部,可以把各种属性绑定到self
,因为self
就指向创建的实例本身 - 类是创建实例的模板,而实例则是一个一个具体的对象,各个实例拥有的数据都互相独立、互不影响
和静态语言不同,Python允许对实例变量绑定任何数据。对于两个实例变量,虽然它们都是同一个类的不同实例,但拥有的变量名称都可能不同
访问限制
如果要让内部属性不被外部访问,可以把属性的名称前加上两个下划线
__
变成私有变量,只有内部可访问在Python中,变量名类似
__xxx__
的,也就是以双下划线开头,并且以双下划线结尾的,是特殊变量,特殊变量是可以直接访问的bart = Student('Bart Simpson', 59)
bart.get_name() #'Bart Simpson'
bart.__name = 'New Name' # 设置__name变量!
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参数,如果属性不存在,就返回默认值实例属性和类属性
实例属性属于各个实例所有,互不干扰;类属性属于类所有,所有实例共享一个属性;不要对实例属性和类属性使用相同的名字,因为相同名称的实例属性将屏蔽掉类属性,而删除实例属性后,再使用相同的名称将访问到类属性