封装
可以提高程序的安全性。
将数据属性和行为方法包装袋类对象中。在方法内部对属性进行类对象的外部调用方法。这样无需关心方法内部的具体实现细节,从而减小复杂度。
可以从下面的例子可以看出
class Student:
def __init__(self,name,age):
self.name=name ##定义了name和age两个实例属性
self.__age=age ##年龄age不希望在类的外部被使用,所以加了两个__
'''
age 不可以在外部使用,但是可以在;类的内部使用
'''
def show(self):
print(self.name,self.__age)
stu1=Student('zhangsan',20)
stu1.show()
'''
如果在这里想输出年龄是不可以的
比如
print('stu1.__age')
程序是会报错的
'''
'''
但是想要输出年龄还是有办法的,qwq 笑死
有个办法
可以输入print(dir(stu1))
可以得到stu1可以调用输出的属性
print(stu1._Student__age)就可以输出年龄了
'''
print(stu1._Student__age)
继承
语句如下:
class 子类名(父类名1,父类名2....)
pass
python支持多继承,定义子类的时候,必须在其构造函数中调用父类的构造函数。
单继承的例子
class Person(object): #创建一个person的类 继承object类
def __init__(self,name,age): #定义它的初始方法
self.name=name
self.age=age
def info(self): #定义它的实例方法
print(self.name,self.age)
class Student(Person): #创建子类 student类
def __init__(self,name,age,stu_no): #多设置了学生号这个参数
super().__init__(name,age)##使用这个语句来调用父类中的初始方法,即父类的构造方法
self.stu_no=stu_no
class Teacher(Person): #创建子类,Teacher
def __init__(self,name,age,tea_no,teachofyear): #多设置了教职工号和教龄这个参数
super().__init__(name,age)##调用父类的构造函数
self.tea_no= tea_no
self.teachofyear=teachofyear
tea=Teacher('zhangsan',50,2017211797,20)
stu=Student('lisi',20,2017211797)
tea.info()
stu.info()
方法重写
- 如果子类对继承自父类的某个属性或方法不满意,可以在子类中对某个方法体进行重写
- 子类重写后的方法中可以通过super().xxx()调用父类中被重写的方法
class Person(object): #创建一个person的类 继承object类
def __init__(self,name,age): #定义它的初始方法
self.name=name
self.age=age
def info(self): #定义它的实例方法
print('姓名为:',self.name,'年龄为:',self.age)
class Student(Person): #创建子类 student类
def __init__(self,name,age,stu_no): #多设置了学生号这个参数
super().__init__(name,age)##使用这个语句来调用父类中的初始方法,即父类的构造方法
self.stu_no=stu_no
def info(self): #Student类进行对父类方法重写
super(Student, self).info()
print('学生的学号是:',self.stu_no)
class Teacher(Person): #创建子类,Teacher
def __init__(self,name,age,tea_no,teachofyear): #多设置了教职工号和教龄这个参数
super().__init__(name,age)##调用父类的构造函数
self.tea_no= tea_no
self.teachofyear=teachofyear
def info(self): #Teacher 类进行对父类进行方法重写
super(Teacher, self).info() #输出父类的结果
print('该教师的教师工号是:',self.tea_no,'教龄为',self.teachofyear)
tea=Teacher('zhangsan',50,2017211797,20)
stu=Student('lisi',20,2017211797)
tea.info()
stu.info()
可以与上面没有进行方法重写的程序进行对比
object类(是所有类的父类)
dir(Student)#查看这个类所有的属性和方法
'''
可以看见很多属性和方法 这些都是从父类object那里继承过来的
'''
object类中有个函数 str(),用于返回一个对于‘’对象的描述‘’,对应于内置函数str()经常用于print()方法,帮我们查看对象的信息,所以我们经常对__str__()进行重写
class Student:
def __init__(self,name,age):
self.name=name
self.age=age
def __str__(self): ##str()方法进行重写
print( '我的姓名是{0},今年{1}岁'.format(self.name,self.age)) ##这个格式记住就行了
stu=Student('zhangsan',20)
stu.__str__()
return ‘我的姓名是{0},今年{1}岁’.format(self.name,self.age)
上面这个格式记住就行了
多态
简单来说,多态就是‘’具有多种形态‘’,它指的是:即便不知道一个变量所引用的对象到底是什么类型,仍然可以通过这个变量调用方法,在运行过程中根据变量所引用对象的类型,动态决定调用哪个对象中的方法。
class Animal(object):
def eat(self):
print('动物吃东西')
class Dog(Animal):
def eat(self):
print('狗吃肉')
class Cat(Animal) :
def eat(self):
print('猫吃鱼')
class Person(object):
def eat(self):
print('人吃五谷杂粮')
def fun(animal):
animal.eat()
'''
就是说person和animal之间没有继承关系,但是这个函数调用只要你有eat这个方法就行,就可以进行调用
'''
fun(Dog())
fun(Person())
fun(Cat())
特殊方法和特殊属性
名称 | 属性 | |
---|---|---|
特殊属性 | _dict_ | 获得类对象或实例对象所绑定的所有属性和方法的字典 |
特殊方法 | _len_() | 通过重写__len__() 方法,让内置函数len()的参数可以是自定义类型 |
_add_() | 通过重写add()方法,可使用自定义对象具有‘’+‘’的功能 | |
_new()_ | 用于创建对象 | |
_init_() | 对创建的对象进行初始化 |
##__dict__语句
class Student:
def __init__(self,name):
self.name=name
x=Student('jack')
print(x.__dict__) ##可以输出绑定的属性
##__bases__语句
class A:
pass
class B:
pass
class Student(A,B):
def __init__(self,name,age):
self.name=name
self.age=age
x=Student('jack',20)
print(x.__dict__) ##可以输出绑定的属性
print(Student.__bases__)## 可以输出Student的父类有哪些
print(Student.__mro__)##可以查看类的层次结构
print(A.__subclasses__())##查看A的子类
##_add_()语句
a=100
b=100
c=a+b
print(c)
d=a.__add__(b) ##对两个整数可以实现相加
print(d)
'''
现在看看他在类中函数的使用
'''
class Person:
def __init__(self,name):
self.name=name
def __add__(self, other): ##self,other都是系统自定义的参数
return self.name+other.name
'''
这里相当于重写了add函数
必须重写了add函数
后续的方法一和方法二才能真的实现
否则就会报错
'''
stu1=Person('zhangsan')
stu2=Person('lisi')
print(stu1.__add__(stu2))##两个对象相加方法一 ##stu1代表self参数 ,进行传参,stu2代表other进行传参
s=stu1+stu2 ##两个对象相加方法二
print(s)
print(stu1.name+stu2.name) ##这个也是同理的 会更好理解一些
##_len_()语句
class Person:
def __init__(self,name):
self.name=name
def __add__(self, other): ##self,other都是系统自定义的参数
return self.name+other.name
'''
这里相当于重写了add函数
必须重写了add函数
后续的方法一和方法二才能真的实现
否则就会报错
'''
stu1=Person('zhangsan')
stu2=Person('lisi')
print(stu1.__add__(stu2))##两个对象相加方法一 ##stu1代表self参数 ,进行传参,stu2代表other进行传参
s=stu1+stu2 ##两个对象相加方法二
print(s)
print(stu1.name+stu2.name) ##这个也是同理的 会更好理解
'''
下面是len语句的例子
'''
lst=[11,22,33,44]
print(len(lst)) ##输出列表长度
print(lst.__len__()) ##也是输出列表长度 ##__len__()这个就是内置函数
'''
在类中需要去重写这样一个len函数
'''
class Student(Person): #创建Student类继承Person类
def __init__(self,name,stu_no): #重写init方法
super().__init__(name) ##调用父类的方法
self.stu_no=stu_no ##定义这个参数
def __len__(self): ##多编写了一个len的方法
return len(self.name) ,len(self.stu_no) ##
stu=Student('zhangsan','2017211797')
print(stu.__len__())
##_new_()语句
class Person:
def __init__(self, name, age):
print('__init__被调用了,self的id值为{0}'.format(id(self)))
self.name = name
self.age = age
def __new__(cls, *args, **kwargs): ##p1的person传给了new的cls
print('__new__被执行调用了,cls的id值为{0}'.format(id(cls)))
obj=super().__new__(cls) ##这里的person又传过来了,创建了对象obj
print('创建的对象的id为{0}'.format(id(obj)))
return obj ##返回的obj对象随后又传给了init
print('object这个类对象的id为{0}'.format(id(object)))
print('Person这个类对象的id为{0}'.format(id(Person)))
##创建Person类的实例对象
p1=Person('张三',20)
print('p1这个Person类的实例对象的id为{0}'.format(id(p1)))
'''
输出结果:
object这个类对象的id为8791489755984
Person这个类对象的id为65387984
__new__被执行调用了,cls的id值为65387984
创建的对象的id为83397456
__init__被调用了,self的id值为83397456
p1这个Person类的实例对象的id为83397456
'''
##由上述结果可以看出这个new创建的对象就是self和p1
##程序p1赋值,会先执行右侧的代码p1=Person('张三',20)
##上面这一步就会将Person传给实例方法new的cls(即对象类型传给cls)
##创建obj然后返回 传个self 随后要赋给了p1
##虽然但是 也不知道为什么是这个流程