OPP程序
Object Oriented Programming,OOP,面向对象程序设计
类和实例(对象)
python规定类的命名要首字母大写。
Class表示“类”;
Class()(加括号)则表示该类的一个“实例”(创建的一个对象),只是还没命名,不能记录;
class=Class()则表示该类的一个完整实例化,把该实例“存储”在class变量中。(说存储有点不太严谨)
类的访问限制
类的内部定义的属性可以被外部进行访问甚至修改,如果想避免这种情况,可以将内部属性命名为self.__name,__name表示为隐藏变量,不可以被外部调用,也不可被更改。
class Student(object): #来在廖雪峰的博客
def __init__(self, name, score):
self.__name = name
self.__score = score
这时如果调用属性会出错:
>>> bart = Student('Bart Simpson', 59)
>>> bart.__name
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'Student' object has no attribute '__name'
只有__name变量是隐藏变量,而__name__则变量不是隐藏变量,是可以被访问的特殊变量。只有一个下划线的_name也不是隐藏变量,可以访问,但是这么写的意思一般就默认他为隐藏变量了,就不要引用了。
类的继承与多态
- 继承:可以通过定义类的子类,来沿用父类的任何设定,且可以单独的为子类添加或修改其独特的方法。
- 多态:子类的实例属于父类,而父类的实例不是子类。
class Animal(): #来自廖雪峰的博客
def run(self):
print('Running...')
def eat(self):
print('Eating...')
class Dog(Animal): # Animal的子类,子类在继承的基础上可以添加或更改方法(更改直接替换就好)
def eat(self):
print('Eating meat...')
class Cat(Animal): # Animal的子类,子类在继承的基础上可以添加或更改方法(更改直接替换就好)
def eat(self):
print('Eating fish...')
print(isinstance(dog,Animal), isinstance(animal,Dog)) # 子类的对象依然属于“父类”,但父类的对象不是子类
结果为:
True False
如果一个函数调用的参数为是父类的实例,那么如果输入的实际参数为子类的实例也是完全可以的。
def run_twice(animal):
animal.eat()
animal.run()
print('*'*30)
dog = Dog()
cat = Cat()
animal = Animal()
run_twice(animal)
run_twice(dog)
run_twice(cat)
结果为
Eating...
Running...
******************************
Eating meat...
Running...
******************************
Eating fish...
Running...
******************************
这样的好处是函数的定义和使用更加灵活,定义时参数只需定义为父类的实例即可,而使用使任何一个子类都可已使用,不需再修改函数。
这就是著名的“开闭”原则:
对扩展开放:允许新增Animal子类;
对修改封闭:不需要修改依赖Animal类型的run_twice()等函数。
静态语言和动态语言
以上所说的使静态语言(Java)中的类的多态用法,实际上对于Python这种动态语言来说,实际用法要更加灵活。函数实际使用时甚至参数可以不是定义的子类,只要参数可以满足函数内的应用条件即可(如有相同的方法)。
例如我们把前面的函数改成下面这样,其余不变再运行一次:
def run_twice(a): # 定义中的形参a不知道是什么类,只需满足有eat和run方法即可
a.eat()
a.run()
print('*'*30)
结果与前面相同
Eating...
Running...
******************************
Eating meat...
Running...
******************************
Eating fish...
Running...
******************************
这就是动态语言的鸭子类型,它并不要求严格的继承体系,一个对象只要“看起来像鸭子,走起路来像鸭子”,那它就可以被看做是鸭子。