面向对象编程,简称OOP,是一种程序设计思想。OOP把对象作为程序的基本单元,一个对象包含了数据和操作数据的函数
在Python中,所有数据类型都可以视为对象,当然也可以自定义对象
类和实例
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))
stu1 = Student('Tom', 99)
stu2 = Student('Sam', 88)
stu1.print_score()
stu2.print_score()
Tom: 99
Sam: 88
Process finished with exit code 0
数据封装、继承和多态是面向对象编程的三大特点
面向对象最重要的概念是类和实例,类是抽象的模板,而实例是根据类创建出来的一个个具体的“对象”,每个对象拥有相同的方法,但各自的数据可能不同
访问限制
如果要让内部属性不被外部访问,可以把属性名称前加两个下划线,在Python中,实例的变量名如果以双下划线开头,就变成类一个私有变量,只有内部可以访问,外部不能访问
在Python中,以双下划线开头,并且以双下划线结尾的,是特殊变量,特殊变量是可以直接访问的,不是private变量
class Student(object):
def __init__(self, name, score):
self.__name = name
self.__score = score
def get_name(self):
return self.__name
def get_score(self):
return self.__score
def set_name(self, name):
self.__name = name
def set_score(self, score):
if score > 100 or score < 0:
print("输入的成绩有误!")
else:
self.__score = score
def print_score(self):
print("%s: %s" % (self.__name, self.__score))
stu1 = Student("Tom", 10)
stu1.print_score()
stu2 = Student("Sam", 20)
stu2.print_score()
stu1.set_name("Bob")
stu2.set_score(100)
print(stu1.get_name())
print(stu2.get_score())
Tom: 10
Sam: 20
Bob
100
Process finished with exit code 0
有些时候,你会看到以一个下划线开头的实例变量名,比如_name,这样的实例变量外部是可以访问的,但是,按照约定俗成的规定,当你看到这样的变量时,意思就是,“虽然我可以被访问,但是,请把我视为私有变量,不要随意访问”。
双下划线开头的实例变量是不是一定不能从外部访问呢?其实也不是。不能直接访问__name 是因为 Python 解释器对外把__name 变量改成了_Student__name,所以,仍然可以通过_Student__name 来访问__name 变量
继承和多态
当我们定义一个类的时候,可以从某个现有的类继承,新的类称为子类,而被继承的类称为基类、父类和超类
"""
继承和多态
"""
class Animal(object):
def __init__(self, name):
self.name = name
def run(self):
print("Animal: %s is running..." % self.name)
class Dog(Animal):
def __init__(self, name):
super(Dog, self).__init__(name)
self.name = name
def run(self):
print("Dog: %s is running..." % self.name)
def eat(self):
print("Dog: %s is eating" % self.name)
class Cat(Animal):
def __int__(self, name):
super(Cat, self).__init__(name)
self.name = name
def run(self):
print("Cat: %s is running..." % self.name)
def say(self):
print("%s: 喵喵" % self.name)
if __name__ == '__main__':
animal = Animal("Tom")
animal.run()
dog = Dog("Sam")
dog.run()
dog.eat()
cat = Cat("Betty")
cat.run()
cat.say()
print(isinstance(dog, Animal))
print(isinstance(dog, Dog))
print(isinstance(dog, Cat))
Animal: Tom is running...
Dog: Sam is running...
Dog: Sam is eating
Cat: Betty is running...
Betty: 喵喵
True
True
False
Process finished with exit code 0
多态的好处是,当我们需要传入Dog、Cat时,我们只需要接收Animal类型就可以了,因为Dog和Cat都是Animal类的子类
def animal_run(animal_obj):
animal_obj.run()
animal_obj.run()
animal_run(animal)
animal_run(dog)
animal_run(cat)
Animal: Tom is running...
Animal: Tom is running...
Dog: Sam is running...
Dog: Sam is running...
Cat: Betty is running...
Cat: Betty is running...
Process finished with exit code 0
调用方只管调用,当我们增加新的Animal子类时,只要确保run()方法编写正确就可以了
对扩展开放:允许增加新的Animal子类
对修改封闭:不需要修改依赖Animal类型的函数