个人觉得以具体案例说明功能会更好一些。下面,以校园学生信息为背景做的相关总结。
初步概述:
之前我们讲到面向对象是一个个具体的类,比如人类、动物等。而实例就是一个个实例化的类值,比如张三、李四、小狗、小猫等,而张三年龄是多少,性别男的女的是指定的属性值,那张三会不会赚钱呢,会不会讨女孩子喜欢是给指定的方法值。
那下面回到背景分析,首先当社会人类(Human)要进入学校的时候,应当收集这个人类的一些信息,当信息收集完毕将赋予学生(Student)这个类;
(在这里面会有一个知识点,就是有学生类别的肯定有个人类类别,但是不是所有的人类都有学生类别,这里面有一个继承概念)。当我们以学生身份进入校园的时候,我们开始寻找我们的教室、找我们亲爱的辅导员报道、办理校园电子卡、再认识我们的我们的宿舍等,这些是我们学生的特定属性。
等我们把学生入学安排好之后,就要开始学习了,学习的话我们得知道我们学习哪些课程,对应课程分数、对应考核等级等学科(Subject)类。
而我们这个人(People)又是人类、学生、学科等相关类别,拥有对应属性。
接下来我们进行代码构造:
一、初步建设框架:
class Human(object):
pass
class Student(Human):
pass
class Subject(object):
pass
class People(Human,Student,Subject):
pass
在这里面我们可以看到Student类为Human类的子类【继承】,而People类是其余三者的子类【多重继承】。
二、内容优化:
我们已经有最简单的框架了,那接下面我们就应该具体化对应属性、判别对应逻辑等了。首先定义人类必须有哪些对应的属性呢,用这些对应属性我们可以来区分一个个的人,比如这里面有姓名(name)、年龄(age)、性别(sex)、身份证号码(card)、手机号码(phone)、家庭住址(address)等属性;那对于Student来说哪些是应该有的属性呢,比如这里面有年级别(grade)、专业(major)、班级(banji)、辅导员(instructor);那对应Subject来说应该有哪些属性呢,比如这应该有语文(yuwen)、数学(math)、英语(yingyu)等课,那调整代码如下:
class Human(object):
def __init__(self,name,age,sex,card,phone,address):
self.name = name
self.age = age
self.sex = sex
self.card = card
self.phone = phone
self.address = address
class Student(Human):
def __init__(self,grade,major,banji,instructor):
self.grade = grade
self.major = major
self.banji = banji
self.instructor = instructor
class Subject(object):
def __init__(self,yuwen,math,yingyu):
self.yuwen = yuwen
self.math = math
self.yingyu = yingyu
class People(Human,Student,Subject):
pass
在这里面我们已经初步定义了各个类别的属性值,下面我们创建试试这些属性值试试。下面我们创建一个人类Oliver,但是创建实例的时候发现报错,提示缺失这六个属性值。查找了解到在___init__为初始化属性,就是创建的实例必须含有字这些属性,创建的属性可以在创建的过程中赋值,也可以是类初始化定义值。下面我们填写上对应值就不会报错了。创建如下,发现则是创建成功了,但是提供了一长长信息发现,查找到这是对应的内存地址。那下面我们就让打印出来查看信息方便直观点。增加函数如下:
def __str__(self):
return "各个信息如下:name: {0}, age: {1}, sex: {2}, card: {3}, phone: {4}, address: {5}".format(self.name,self.age,self.sex,self.card,self.phone,self.address)
__repr__ = __str__
增加完之后我们再试试查看下,需要的信息都直接展现出来了。我们创建了一个Oliver实例,在这里我们尝试修改里面的属性值试试看。我们发现,里面属性被修改了,我们都知道Python是面向对象语言是个动态语言,如果我们没有做任何限制的话,在类里面我们可以任意添加、修改、删除属性值(想想好可怕,我都变成千年老妖了)。为了防止我们的数据被任意调整,我们需要限制我们的属性,代码如下:
class Human(object):
def __init__(self,name,age,sex,card,phone,address):
self.__name = name
self.__age = age
self.__sex = sex
self.__card = card
self.__phone = phone
self.__address = address
下面我们尝试一下再次调用年龄,我们会发现说没有找到这个name属性,这样外部就无法调用了。那我们继续用赋值试试。在这我们发现我们name属性可以赋值成功,可是对应的打印信息出来是没有信息调整的,原来是程序对实例创建了一个Oliver.name的新属性,我们查看Oliver.name试试看。《还是有些疑问》现在我们的属性不会被外部调用了,但是对于生产环境来说这些实例的属性肯定是存在调整的,那以我们调整name信息为例,代码调整如下:
@property
def name(self):
return self.__name
@name.setter
def name(self,value):
self.__name == value
@name.deleter
def name(self):
del self.__name
在这里面用的装饰器定义,初步感觉应该用的这个。在这里面我们定义的name属性查看,name的setter值修改,name属性的删除deleter,下面我们来尝试修改一下。这样我们又可以调整里面的内部属性了。看一下对比图
那么就有这样的疑问了,这里面我们输入什么类型其实都可以输出,比如我的name叫[1,2,3,4,5]其实也是可以的,测试结果在这里面应该输入的是str字符串。所以在这里面我们还要加上输入类型的判断。代码如下:
@name.setter
def name(self,value):
if isinstance(value,str):
self.__name = value
else:
raise ValueError('Is not string type!')
我们在修改named的地方做了判断语句,当类型正常的时候我们返回值,不正确的时候我们报错误信息。测试如下:
那现在我们可以正常的修改我们的属性了,并且也可以获得想要的类型。
在这就又产生一个问题,我们修改一个属性值创建装饰器单独修改,那如果我有十个,百个属性需要修改,也是要创建一百份对应修改嘛,那岂不是有很多的工作量,必然有一些是重复的。是否有方法可以把能合并的合并处理呢。暂时没有想到办法,待后续继续研究查询,初步想法是创建一个子类,这个子类相当于修改类,修改父类的属性值,因为属性值有类型区分,做对应的条件判断再输出。构想的代码框架为:
class Human():
def call_adjustment(self):
child_method = getattr(self, 'out')# 获取子类的out()方法
class adjustment(Human):
def out(self,attribute,value):
if isinstance(attribute,str): #之前定义的属性类型只有字符串与整形两种,这都是字符串的类型
if isinstance(value,str): #如果调整的值也是字符串
self.attribute = value
else:
raise ValueError('Is not string type!')
else: #反之就是整形了
pass
我们程序做了优化,到现在为止的代码信息如下:
class Human(object):
def __init__(self,name,age,sex,card,phone,address):
self.__name = name
self.__age = age
self.__sex = sex
self.__card = card
self.__phone = phone
self.__address = address
def __str__(self):
return "各个属性内容如下:name: {0}, age: {1}, sex: {2}, card: {3}, phone: {4}, address: {5}".format(self.__name,self.__age,self.__sex,self.__card,self.__phone,self.__address)
__repr__ = __str__
@property
def name(self):
return self.__name
@name.setter
def name(self,value):
if isinstance(value,str):
self.__name = value
else:
raise ValueError('Is not string type!')
@name.deleter
def name(self):
del self.__name
def call_adjustment(self):
child_method = getattr(self, 'out') # 获取子类的out()方法
Oliver = Human("Oliver",25,"男",1818181818181818,12345678911,"北京")
class Student(Human):
def __init__(self,grade,major,banji,instructor):
self.__grade = grade
self.__major = major
self.__banji = banji
self.__instructor = instructor
class Subject(object):
def __init__(self,yuwen,math,yingyu):
self.__yuwen = yuwen
self.__math = math
self.__yingyu = yingyu
class People(Human,Student,Subject):
pass
class adjustment(Human):
def out(self, attribute, vlaue):
if isinstance(attribute, str): # 之前定义的属性类型只有字符串与整形两种
if isinstance(vlaue, str):
pass
else:
raise ValueError('Is not string type!')
else: # 反之就是整形了
pass
接下来会继续做优化、逻辑判断等。请看下次总结。