Python 全栈开发七 面向对象
一、编程范式
编程是程序员用特定的语法+数据结构+算法组成的代码来告诉计算机如何执行任务的过程 , 一个程序是程序员为了得到一个任务结果而编写的一组指令的集合,正所谓条条大路通罗马,实现一个任务的方式有很多种不同的方式, 对这些不同的编程方式的特点进行归纳总结得出来的编程方式类别,即为编程范式,也可以将编程范式理解为武功秘籍,现在常见的编程范式有:面向过程编程,函数式编程,面向对象编程。
- 面向过程:指的是实现任务时从上到下一步步执行,从头至尾解决问题,将大问题分解成若干个小问题,将小问题继续分解直到问题可以被解决为止。总的来说就是:自顶向下,逐步求精。
- 函数式编程:就是数学意义上的函数和编程语言上的函数的结合。(也可以理解为,有返回值的函数编程)
- 面向对象编程:OOP编程是利用“类”和“对象”来创建各种模型来实现对真实世界的描述。也可以理解为,是对象属性和方法封装在一起的思想。
电影霍元甲有一句话:没有最强的武功,只有最强的人。
编程范式也是如此,没有最好的方式,只有最好的程序员,三种编程范式各有各的有点,不同的是使用的人而已。
二、面向过程编程
比如:学生早上起床这件事情来说
- 起床
- 穿衣
- 洗脸刷牙
- 去学校
1 def getup(name): 2 print(" %s 起床" % name) 3 4 def cloth(name): 5 print(" %s 穿衣" % name) 6 7 def washtooth(name): 8 print(" %s 洗脸刷牙" % name) 9 10 def go_school(name): 11 print(" %s 去学校" % name) 12 13 gt = getup("wallace") 14 cl = cloth("wallace") 15 sa = washtooth("wallace") 16 gs = go_school("wallace")
将起床去学校,化简为一个一个小问题,由上而下的执行。
三、函数式编程
函数式编程代码简洁,但相对来说不易理解:
1 def foo(name): 2 print("name") 3 4 def fun(func): 5 return func 6 7 a = fun(foo("wallce"))
四、面向对象设计
对于Python来说是一门纯面向对象的语言,有class方法来定义类,但是这不意味着面向对象设计就是用class定义类这种方式来编程。
例如:
1 def student(name,age,school): 2 def init(name,age,school): 3 stu={ 4 "stu_name":name, 5 "stu_age":age, 6 "stu_school":school, 7 "go_school":go_school, 8 "do_homework":do_homework 9 } 10 return stu 11 12 def go_school(student): 13 print("%s 去 %s 上学" %(student["stu_name"],student["stu_school"])) 14 15 def do_homework(name): 16 print("%s 正在做作业" % name) 17 18 return init(name,age,school) 19 20 wallace = student("wallace",18,"浙江大学") 21 name = wallace["stu_name"] 22 esc = wallace["go_school"](wallace)
以上就是一个面向对象设计思想实现的一个学生对象。即面向对像设计思想,将同一对象的属性和方法进行封装。
对应面向对象而言:世界万物,皆可分类;世界万物,皆为对象;只要是对象,就肯定属于某种品类;只要是对象,就有属性。
五、Python面向对象语言
面向对象常见的特性:
Class 类
一个类即是对一类拥有相同属性的对象的抽象、蓝图、原型。在类中定义了这些对象的都具备的属性(variables(data))、共同的方法
Object 对象
一个对象即是一个类的实例化后实例,一个类必须经过实例化后方可在程序中调用,一个类可以实例化多个对象,每个对象亦可以有不同的属性,就像人类是指所有人,每个人是指具体的对象,人与人之前有共性,亦有不同
Encapsulation 封装
在类中对数据的赋值、内部调用对外部用户是透明的,这使类变成了一个胶囊或容器,里面包含着类的数据和方法
Inheritance 继承
一个类可以派生出子类,在这个父类里定义的属性、方法自动被子类继承
Polymorphism 多态
多态是面向对象的重要特性,简单点说:“一个接口,多种实现”,指一个基类中派生出了不同的子类,且每个子类在继承了同样的方法名的同时又对父类的方法做了不同的实现,这就是同一种事物表现出的多种形态。
编程其实就是一个将具体世界进行抽象化的过程,多态就是抽象化的一种体现,把一系列具体事物的共同点抽象出来, 再通过这个抽象的事物, 与不同的具体事物进行对话。
对不同类的对象发出相同的消息将会有不同的行为。比如,你的老板让所有员工在九点钟开始工作, 他只要在九点钟的时候说:“开始工作”即可,而不需要对销售人员说:“开始销售工作”,对技术人员说:“开始技术工作”, 因为“员工”是一个抽象的事物, 只要是员工就可以开始工作,他知道这一点就行了。至于每个员工,当然会各司其职,做各自的工作。
多态允许将子类的对象当作父类的对象使用,某父类型的引用指向其子类型的对象,调用的方法是该子类型的方法。这里引用和调用方法的代码编译前就已经决定了,而引用所指向的对象可以在运行期间动态绑定
六、类的进阶
1、定义类
1 ''' 2 在定义学生类的时候,我们考虑到学生有姓名,年龄等 3 就个学生统一的属性和方法 4 ''' 5 6 class student(object): #定义一个学生类 7 def __init__(self,name,age): 8 self.name = name #学生的属性 9 self.age = age 10 def learning(self): #学生的方法 11 print("%s is learning" % self.name) 12 13 14 Wallace= student("wallace",18) #创建一个学生实例,根据传入参数的不同,学生也就不同 15 print(Wallace.name) #调用学生的属性 16 Wallace.learning() #调用学生的方法
2.类的方法
类的内置方法一:
1 class student(object): #定义一个学生类 2 ''' 3 这是一个学生类 4 ''' 5 def __init__(self,name,age): 6 self.name = name #学生的属性 7 self.age = age 8 def learning(self): #学生的方法 9 print("%s is learning" % self.name) 10 11 12 Wallace= student("wallace",18) #创建一个学生实例,根据传入参数的不同,学生也就不同 13 print(Wallace.name) #调用学生的属性 14 Wallace.learning() #调用学生的方法 15 16 print(student.__name__) #student 返回的是对应的类名 17 print(student.__doc__) #打印文档字符串 18 print(student.__bases__) #返回基类 19 print(student.__dict__) #返回对应的属性以字典的形式 20 print(student.__module__) #返回对应的模块名 21 #以上方法实例都可以使用 22 print(Wallace.__dict__) #返回实例对应的属性 23 print(Wallace.__dict__['name']) #Wallace.name实际的调用就是Python内部使用了字典进行调用,若在 24 #Wallace.__dict__字典里没有,就会去student.__dict__找对应的属性
类的内置方法二:
1 class Dog(object): 2 ''' 3 __doc__ 用于打印文档字符串 4 ''' 5 6 def __del__(self): 7 print('我自动删除了这实例') 8 ''' 9 当实例的指向别删除,即没有变量指向该实例,就会触发该函数 10 当程序运行结束时也会触发该函数,来删除内存中的实例对象 11 ''' 12 def __call__(self, *args, **kwargs): 13 print('对象加括号就可以触发') 14 def __str__(self): 15 print('在打印对象时,默认输出该方法的返回值') 16 return 'str返回值'
类的特殊方法:
- 属性方法
1 class student(object): #定义一个学生类 2 ''' 3 这是一个学生类 4 ''' 5 def __init__(self,name,age): 6 self.name = name #学生的属性 7 self.age = age 8 def learning(self): #学生的方法 9 print("%s is learning" % self.name) 10 @property 11 def eat(self): 12 print("%s is eating" % self.name) 13 14 #@property的作用是更改类所定义方法的调用方式,使其的调用方变为类似调用普通类属性的方式 15 16 wallace = student("wallace",18) 17 wallace.eat
- 类方法
1 class student(object): #定义一个学生类 2 ''' 3 这是一个学生类 4 ''' 5 name = "wallace" 6 def __init__(self,name,age): 7 self.name = name #学生的属性 8 self.age = age 9 def learning(self): #学生的方法 10 print("%s is learning" % self.name) 11 @classmethod 12 def eat(self): 13 print("%s is eating" % self.name) 14 15 #@classmethod类无法调用实例的属性,只能调用类里面定义的属性 16 17 wallace = student("wallace",18) 18 wallace.eat()
- 静态方法
1 class student(object): #定义一个学生类 2 ''' 3 这是一个学生类 4 ''' 5 name = "wallace" 6 def __init__(self,name,age): 7 self.name = name #学生的属性 8 self.age = age 9 def learning(self): #学生的方法 10 print("%s is learning" % self.name) 11 @staticmethod 12 def eat(self): 13 print("%s is eating" % self.name ) 14 15 @staticmethod 16 def play(name): 17 print("%s is playing" % name) 18 19 #@staticmethod的装饰后,变成一个完全独立于类的方法,调用的时候不会调用自身,需要自己传入参数 20 21 wallace = student("wallace",18) 22 wallace.eat(wallace) 23 wallace.play("wallace")
3、类的特性
类的特性:继承
1 #class People: 老式类 2 class People(object): #带object的就是新式类 3 def __init__(self,name,age): 4 self.name = name 5 self.age = age 6 self.friends = [] 7 print("--doesn't run--") 8 def eat(self): 9 print("%s is eating..." % self.name) 10 def talk(self): 11 print("%s is talking..." % self.name) 12 def sleep(self): 13 print("%s is sleeping..."% self.name) 14 15 class Relation(object): #传入的是一个实例 16 # def __init__(self,n1,n2): 17 # print("init is relation") 18 def make_friends(self,obj): 19 print("%s is making friends with %s" % (self.name,obj.name)) #实例调用属性 20 self.friends.append(obj.name) 21 class Man(Relation,People): 22 # def __init__(self,name,age,money): #当你需要重构构造函数是 23 # #People.__init__(self) #这种无需知道基类的属性 24 # super(Man,self).__init__(name,age) #需要知道基类的属性 25 # self.money = money 26 def piao(self): 27 print("%s is piaoing...20s...done."% self.name) 28 def sleep(self): 29 People.sleep(self) 30 print('Man is sleeping') 31 class Woman(People,Relation): 32 def get_borth(self): 33 print("%s is borthing a baby..."% self.name) 34 35 r = Man('qiang',23) #根据新式类的广度优先继承,会报错 36 r1 = Woman('wallace',24) 37 r1.make_friends(r) 38 r1.sleep()
新式类与经典类继承区别:
1 class A: 2 def __init__(self): 3 print("a") 4 class B(A): 5 pass 6 # def __init__(self): 7 # print('b') 8 class C(A): 9 def __init__(self): 10 print('c') 11 class D(B,C): 12 pass 13 14 r = D() 15 16 ''' 17 广度优先,即bca 18 经典类py2:深度优先bac 19 '''
多态
1 class Animal: 2 def __init__(self,name): 3 self.name = name 4 def talk(self): 5 pass 6 @staticmethod 7 def animal_talk(obj): 8 obj.talk() 9 class Cat(Animal): 10 def talk(self): 11 print('meow') 12 class Dog(Animal): 13 def talk(self): 14 print('wang') 15 16 d = Dog('兰博') 17 c = Cat('小米') 18 19 Animal.animal_talk(d)
接下来是两个面向对象的例子:
1 class Role: 2 n = 123 #类变量 3 n_list=[] 4 name = '我是类name' 5 def __init__(self,name,role,weapon,life_value=100,money=15000): 6 #构造函数 7 #是实例化时做一些类的初始化工作 8 self.name = name #实例变量,作用域就是当前实例本身 9 self.role = role 10 self.weapon = weapon 11 self.__life_value = life_value #私有变量,外部不可以访问,只作用于内部 12 self.money = money 13 def __del__(self): 14 #析构函数:在一实例的指向消失,或程序结束是进行删除 15 print('%s 死了'% self.name) #del 关键字,可以删除一个变量的指向。 16 def show_status(self): 17 print('name:%s weapon:%s life_val:%s' % (self.name,self.weapon,self.__life_value)) 18 def __shot(self): # 类的私有方法,功能(属性) 19 print('shooting...') 20 def got_shot(self): 21 self.__life_value -= 50 22 print('%s:ah...,I got shot...' % self.name) 23 def buy_gun(self,gun_name): 24 print('%s just bounght %s'%(self.weapon,gun_name)) 25 26 27 role1 = Role('wallace','police','ak47') 28 role1.buy_gun('98k') 29 role1.got_shot() 30 print(role1.show_status())
1 class School(object): 2 def __init__(self,name,addr): 3 self.name = name 4 self.addr = addr 5 self.students = [] 6 self.teachers = [] 7 def enroll(self,stu_obj): 8 print("为学员%s办理入学手续" % stu_obj.name) 9 self.students.append(stu_obj) 10 def hire(self,tec_obj): 11 print("雇佣%s老师"%tec_obj.name) 12 class Schoolmember(object): 13 def __init__(self,name,age,sex): 14 self.name = name 15 self.age = age 16 self.sex = sex 17 def tell(self): 18 pass 19 20 class Teacher(Schoolmember): 21 def __init__(self,name,age,sex,salary,course): 22 super(Teacher,self).__init__(name,age,sex) 23 self.salary = salary 24 self.course = course 25 def tell(self): 26 print(''' 27 ----info of Teacher %s --- 28 Name:%s 29 Age:%s 30 Sex:%s 31 Salary:%s 32 Course:%S''' % (self.name,self.name,self.age,self.sex,self.salary,self.course)) 33 def teach(self): 34 print('%s is teaching course [%s]',self.name,self.course) 35 36 class Student(Schoolmember): 37 def __init__(self,name,age,sex,stu_id,grade): 38 super(Student,self).__init__(name,age,sex) 39 self.stu_id = stu_id 40 self.grade = grade 41 def tell(self): 42 print(""" 43 ---- info of Student is %s--- 44 Name:%s 45 Age:%s 46 Sex:%s 47 Stu_id:%s 48 Grade:%s"""%(self.name,self.name,self.age,self.sex,self.stu_id,self.grade)) 49 50 def pay_tuition(self,amount): 51 print("%s coming pay tuition %s"% (self.name,amount)) 52 53 Sch1 = School('oldboy','北京') 54 stu1 = Student('wallace','24','m','11111','python') 55 Sch1.enroll(stu1) 56 stu1.pay_tuition(5000) 57 print(Sch1.students)
3、反射
反射的作用是在我们仅提供字符串的前提下,如果通过给定字符串来判断一个类是否有与之对应的属性,并且访问这个属性等方便我们使用的作用。
1 def bulk(self): 2 print('%s is bulking' % self.name) 3 4 class dog(object): 5 def __init__(self,name): 6 self.name = name 7 8 def eat(self): 9 print('[%s] is eating' % self.name) 10 11 12 f = dog('wallace') 13 print(hasattr(f,'name')) #判断是否存在某属性,某方法,若存在则返回True,否则返回Flase 14 gei = getattr(f,'name') #获取对象中的某属性,某方法,方法不运行,要运行可以调用括号 15 set1 = setattr(f,'age',22) #设置一个属性,方法 16 set3 = setattr(f,'bulk',bulk) 17 print(getattr(f,'age')) 18 set2 = setattr(f,'name','peilin') 19 print(getattr(f,'name')) 20 print(gei) 21 22 delattr(f,'name') #删除某一属性,或方法 23 print(getattr(f,'name'))