面向对象的三大特征:
封装:提高程序的安全性
·将数据(属性)和行为(方法)包装到类对象中。在方法内部对属性进行赋值。在类对象的外部调用方法。这样,无需关心方法内部的具体实现细节,从而降低程序复杂度。
·在Python中没有专门的修饰符用于属性的私有,如果访问,前边使用两个'_'。
继承:提高代码的复用性
多态:提高程序的可扩展性和可维护性
1、封装
class Car:
def __init__(self,brand):
self.brand=brand
def start(self):
print('嘟嘟嘟嘟!汽车启动!')
car=Car('BMWX5')
car.start()#嘟嘟嘟嘟!汽车启动!
print(car.brand)#BMWX5
使用__(两个_)使属性无法在外部被访问
但还是可以使用stu1._Student__age来访问
因此Python中的私有就得靠程序员的自觉了
class Student:
def __init__(self,name,age):
self.name=name
self.__age=age #年龄不希望在类的外部被使用,所以加了两个_
def show(self):
print(self.name,self.__age)
stu1=Student('张三',20)#
stu1.show()#张三 20
#在类的外部访问name和age
print(stu1.name)#张三 20
#使用__修饰,无法访问age
#print(stu1.age) AttributeError: 'Student' object has no attribute 'age'
print(dir(stu1))
print(stu1._Student__age)#20 在类的外部可以通过 _Student__age访问
2、继承
单继承:
class Person(object):
def __init__(self,name,age):
self.name=name
self.age=age
def info(self):
print(f'姓名:{self.name},年龄:{self.age}')
#定义子类
class Student(Person):
def __init__(self,name,age,score):
super().__init__(name,age)
self.score=score
class Teacher(Person):
def __init__(self,name,age,teachofyear):
super().__init__(name,age)
self.teachofyear=teachofyear
#测试
stu=Student('张三',20,100)
stu.info()#姓名:张三,年龄:20
teacher=Teacher('李四',30,10)
teacher.info()#姓名:李四,年龄:30
多继承:
class A(object):
pass
class B(A):
pass
#同时继承两个类
class C(A,B):
pass
3、方法重写
class Person(object):
def __init__(self,name,age):
self.name=name
self.age=age
def info(self):
print(f'姓名:{self.name},年龄:{self.age}')
#定义子类
class Student(Person):
def __init__(self,name,age,score):
super().__init__(name,age)
self.score=score
#重写info方法
def info(self):
super().info()#调用父类info方法
print(f'成绩:{self.score}')
class Teacher(Person):
def __init__(self,name,age,teachofyear):
super().__init__(name,age)
self.teachofyear=teachofyear
# 重写info方法
def info(self):
super().info() # 调用父类info方法
print(f'教龄:{self.teachofyear}')
#测试
stu=Student('张三',20,100)
stu.info()#姓名:张三,年龄:20
# 成绩:100
tea=Teacher('汪汪汪',30,10)
tea.info()#姓名:汪汪汪,年龄:30
# 教龄:10
4、object类
__str__方法类似于Java中的toString()方法
class Student:
def __init__(self,name,age):
self.name=name
self.age=age
def __str__(self):
return '我的名字是{0},今年{1}岁'.format(self.name,self.age)
stu=Student('张三',20)
print(dir(stu))#['__class__'................] 从object中继承的
print(stu)#未重写方法之前:<__main__.Student object at 0x02F89770>
#重写方法之后 我的名字是张三,今年20岁
print(type(stu))#<class '__main__.Student'>
5、多态
class Animal:
def eat(self):
print('动物会吃')
class Dog(Animal):
def eat(self):
print('狗吃骨头……^^')
class Cat(Animal):
def eat(self):
print('猫吃鱼^^')
class Person:
def eat(self):
print('人吃一切')
#定义一个函数
def fun(obj):
obj.eat()
#开始调用函数
fun(Cat())#猫吃鱼^^
fun(Dog())#狗吃骨头……^^
fun(Person())#人吃一切
Java就是静态语言,必须明确继承关系
而Python不关心这些,它关心的是有没有这个行为
6、特殊方法和特殊属性
类中的一些特殊属性
class A:
pass
class B:
pass
class C(A,B):
def __init__(self,name,age):
self.name=name
self.age=age
#创建C类的对象
x=C('Jack',20) #x是C类的一个实例对象
#__dict__获得类对象或实例对象所绑定的所有属性和方法的字典
print(x.__dict__)#{'name': 'Jack', 'age': 20}
print(C.__dict__)#{'__module__': '__main__', '__init__': <function C.__init__ at 0x00B2D270>, '__doc__': None}
print('------------')
#__class__输出对象所属的类
print(x.__class__)#<class '__main__.C'>
#__bases__输出的是类的父类类型的元组
print(C.__bases__)#(<class '__main__.A'>, <class '__main__.B'>)
#__base__输出的是第一个基类
print(C.__base__)#<class '__main__.A'>
#__mro__查看继承的层次结构
print(C.__mro__)#(<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class 'object'>)
#__subclasses__查看所有的子类列表
print(A.__subclasses__())#[<class '__main__.C'>]
类中的特殊方法:
a=20
b=100
c=a+b#两个整数类型的对象的相加操作
d=a.__add__(b)
print(c)#120
print(d)#120
class Student:
def __init__(self,name):
self.name=name
def __add__(self, other):
return self.name+other.name
def __len__(self):
return len(self.name)
stu1=Student('张三')
stu2=Student('李四')
'''
TypeError: unsupported operand type(s) for +: 'Student' and 'Student'
未写__add__前报错
重写完__add__方法后的结果为:
张三李四
'''
s=stu1+stu2
print(s)
print('-----------------------')
lst=[11,22,33,44]
print(len(lst))#len是内置函数 ,可以计算列表的长度
print(lst.__len__())
#想要输出一个对象的长度,得先编写__len__()方法
'''
重写__len__方法前TypeError: object of type 'Student' has no len()
重写后:4
'''
print(len(stu1))
__new__与__init__
·__new__用于创建对象
·__init__用于对创建的对象进行初始化
执行顺序:
person=Person('张三',20)
先执行Person('张三',20)然后转入__new__函数,将Person对象传给cls,然后调用父类方法创建obj对象,最后返回obj对象。
obj对象作为__init__函数中的self传入,执行初始化方法后传给person