8.面向对象编程
8.1类和实例
__init__
用于给类绑定属性
class Student(object):
def __init__(self, name, score):
self.name = name
self.score = score
def print_score(self):
print('%s: %s' % (self.name, self.score))
8.2访问限制
- 名称前加
__
就变成了私有变量,只有内部可访问,外部不能访问
class Student(object):
def __init__(self, name, score):
self.__name = name
self.__score = score
def print_score(self):
print('%s: %s' % (self.__name, self.__score))
- 如果加
_
则外部可以访问,但按照约定,需将其视为私有变量
8.3继承和多态
- 继承
class Animal(object):
def run(self):
print('Animal is running...')
class Dog(Animal):
def run(self):
print('Dog is running...') #覆盖父类run()方法
class Cat(Animal):
def run(self):
print('Cat is running...') #覆盖父类run()方法
def run_twice(animal): #多态(类似向上转型)
animal.run()
animal.run()
-
多态的开闭原则
- 对扩展开放:允许新增
Animal
子类; - 对修改封闭:不需要修改依赖
Animal
类型的run_twice()
等函数。
- 对扩展开放:允许新增
-
静态语言 vs 动态语言
- 静态语言如Java,如果需要传入Animal类型,对象必须是Animal或其子类,否则无法调用run()方法
- 动态语言如Python,则不一定要输入Animal类型,只需要保证传入对象有一个run()方法就可以 → 鸭子类型
class Timer(object):
def run(self):
print('Start...')
def run_twice(animal): #多态(类似向上转型)
animal.run()
animal.run()
if __name__ == "__main__":
run_twice(Timer())
>>>
Start...
Start...
- Python的“file-like object“就是一种鸭子类型
8.4获取对象信息
8.4.1 type()
- type()方法来判断对象类型
>>> type(123)==type(456)
True
>>> type(123)==int
True
>>> type('abc')==type('123')
True
>>> type('abc')==str
True
>>> type('abc')==type(123)
False
- 判断一个 对象是否是函数:使用
types
定义的常量
>>> import types
>>> def fn():
... pass
...
>>> type(fn)==types.FunctionType
True
>>> type(abs)==types.BuiltinFunctionType
True
>>> type(lambda x: x)==types.LambdaType
True
>>> type((x for x in range(10)))==types.GeneratorType
True
8.4.2 isinstance()
- 如object -> Animal -> Dog -> Husky
>>> a = Animal()
>>> d = Dog()
>>> h = Husky()
>>> isinstance(h, Dog)
True
>>> isinstance(d, Husky)
False
- 并且还可以判断一个变量是否是某些类型中的一种
>>> isinstance([1, 2, 3], (list, tuple))
True
>>> isinstance((1, 2, 3), (list, tuple))
True
8.4.3dir()
- 获得一个对象的所有属性和方法
>>> dir('ABC')
['__add__', '__class__',..., '__subclasshook__', 'capitalize', 'casefold',..., 'zfill']
- 配合
getattr()
、setattr()
以及hasattr()
,我们可以直接操作一个对象的状态
>>> hasattr(obj, 'x') # 有属性'x'吗?
True
>>> obj.x
9
>>> hasattr(obj, 'y') # 有属性'y'吗?
False
>>> setattr(obj, 'y', 19) # 设置一个属性'y'
>>> hasattr(obj, 'y') # 有属性'y'吗?
True
>>> getattr(obj, 'y') # 获取属性'y'
19
>>> obj.y # 获取属性'y'
19
>>> getattr(obj, 'z', 404) # 获取属性'z',如果不存在,返回默认值404
404
- 判断对象是否存在某个方法
def readImage(fp):
if hasattr(fp, 'read'):
return readData(fp)
return None
8.5实例属性和类属性
- 实例属性在
__init__
中定义;类属性在类中定义,归类所有(类的实例也可以访问类属性) - 注意:实例属性优先级比类属性高
>>> class Student(object):
... name = 'Student'
...
>>> s = Student() # 创建实例s
>>> print(s.name) # 打印name属性,因为实例并没有name属性,所以会继续查找class的name属性
Student
>>> print(Student.name) # 打印类的name属性
Student
>>> s.name = 'Michael' # 给实例绑定name属性
>>> print(s.name) # 由于实例属性优先级比类属性高,因此,它会屏蔽掉类的name属性
Michael
>>> print(Student.name) # 但是类属性并未消失,用Student.name仍然可以访问
Student
>>> del s.name # 如果删除实例的name属性
>>> print(s.name) # 再次调用s.name,由于实例的name属性没有找到,类的name属性就显示出来了
Student
参考教程
(转载整理自网络,如有侵权,联系本人删除,仅供技术总结使用)