面向对象的三大特性:封装、继承、多态
- 封装
属性“私有”:在Python中,没有专门的修饰符用于属性的私有,if该属性不希望被访问,属性前加 两个_
- 继承
if 该类没有继承任何类,则默认继承object;
Python支持多继承;
定义子类时,必须在其构造函数中调用父类的构造
- 方法重写
if 子类对继承自父类的某个属性或方法不满意,可在子类对其重写;
重写仍可调用父类原来的内容:super().xxx()
- object类
object类是所有类的父类,内置函数dir()可查看指定对象的所有属性、方法;
object有__str__()方法,返回“对象的描述”,常在类内对其进行重写
- 多态
although不知道一个函数中传入对象的类型,仍可通过对象调用方法;
所以python是动态语言,比如不需要关心Person是什么类型,只用关心是否有eat行为;
而静态语言,在实现多态时,必须明确继承关系,如:C++ JAVA
'''面向对象的三大特性:封装、继承、多态
在Python中,没有专门的修饰符用于属性的私有,
if该属性不希望被访问,属性前加 __
'''
#==================== 封装之 属性“私有”
class Student:
def __init__(self,name,age):
self.name = name
self.__age = age # 不希望被访问的属性前加__
def show(self):
print('类内show函数:',self.name, self.__age) # 但在类内可访问
stu = Student('NANA',21)
stu.show() # 类内show函数: NANA 21
print(stu.name) # NANA
# print(stu.__age) # AttributeError
# 如果执意访问(犯贱,不推荐):
print(dir(stu)) # (略,查看stu已有的属性、方法。反正是个可访问的属性大列表)
print(stu._Student__age) # 21
'''if该类没有继承任何类,则默认继承object
Python支持多继承
定义子类时,必须在其构造函数中调用父类的构造
'''
#==================== 继承
class Person(object): # 默认继承object,可省略?
def __init__(self,name,age):
self.name = name
self.age = age
def info(self):
print(self.name,self.age)
class Student(Person):
def __init__(self,name,age,stu_no):
super().__init__(name,age) # 调用父类
self.stu_no = stu_no
class Teacher(Person):
def __init__(self,name,age,teachofyear):
super().__init__(name,age) # 调用父类
self.teachofyear = teachofyear
stu = Student('NANA',21,'1023')
stu.info() # NANA 21 继承父类方法
teach = Teacher('Lijian',36,10)
teach.info() # Lijian 36 继承父类方法
print('-------------多继承--------------')
class A(object):
pass
class B(object):
pass
class C(A,B):
pass
'''if子类对继承自父类的某个属性或方法不满意,可在子类对其重写
重写仍可调用父类原来的内容:super().xxx()
'''
#==================== 方法重写
class Person(object):
def __init__(self,name,age):
self.name = name
self.age = age
def info(self):
print(self.name,self.age)
class Student(Person):
def __init__(self,name,age,stu_no):
super().__init__(name,age)
self.stu_no = stu_no
def info(self): # 重写父类的info()方法
super().info()
print(self.stu_no)
class Teacher(Person):
def __init__(self,name,age,teachofyear):
super().__init__(name,age)
self.teachofyear = teachofyear
def info(self): # 重写父类的info()方法
super().info()
print(self.teachofyear)
stu = Student('NANA',21,'1023')
stu.info() # NANA 21 1023
teach = Teacher('Lijian',36,10)
teach.info() # Lijian 36 10
'''object类是所有类的父类,内置函数dir()可查看指定对象的所有属性、方法
object有__str__()方法,返回“对象的描述”,常在类内对其进行重写
'''
#==================== object类
# 查看默认object类的属性和方法
class Student():
pass
stu = Student()
print(dir(stu)) # 略(一大坨)注意里边的 __str()__方法,下议
print(stu) # <__main__.Student object at 0x0000024CF0EC7588>
# 直接print stu默认调用__str__()方法,所以默认得到的是对象的内存地址,与下面对比
class Student():
def __init__(self,name,age):
self.name = name
self.age = age
def __str__(self): # 重写object(父类)方法
return '我的名字是{0},今年{1}岁。'.format(self.name, self.age)
stu = Student('NANA',21)
print(stu) # 我的名字是NANA,今年21岁。
# 所以经常用__str__()重写默认方法
'''多态:although不知道一个函数中传入对象的类型,仍可通过对象调用方法
所以python是动态语言,比如不需要关心Person是什么类型,只用关心是否有eat行为
而静态语言,在实现多态时,必须明确继承关系,如:C++ JAVA
'''
#==================== 多态
class Animal(object):
def eat(self):
print('动物能吃饭')
class Dog(Animal):
def eat(self): # 重写eat()
print('狗吃肉')
class Cat(Animal):
def eat(self):
print('猫吃鱼')
class People(object):
def eat(self):
print('人吃五谷杂粮')
def fun(obj):
obj.eat()
fun(Animal()) # 动物能吃饭
fun(Dog()) # 狗吃肉
fun(Cat()) # 猫吃鱼
print('---------------')
fun(People()) # 人吃五谷杂粮