本文共 9014 字,大约阅读时间需要 30 分钟。
“面向过程”(Procedure Oriented)是一种以过程为中心的编程思想。分析出解决问题所需要的步
骤,然后用函数把这些步骤一步一步实现,使用的时候一个一个依次调用就可以了。 面向对象的方法也是含有面向过程的思想。面向过程最重要的是模块化的思想方 法。比如拿学生早上起来这件事说明面向过程,粗略的可以将过程拟为: (1)起床 (2)穿衣 (3)洗脸刷牙 (4)去学校 而这4步就是一步一步地完成,它的顺序很重要,你只需要一个一个地实现就行了。 而如果是用面向对象的方法的话,可能就只抽象出一个学生的类,它包括这四个 方法,但是具体的顺序就不一定按照原来的顺序。函数式编程是种编程方式,它将电脑运算视为函数的计算。函数编程语言最重要的基础是λ
演算(lambda calculus),而且λ演算的函数可以接受函数当作输入(参数)和输出(返回值)。 主要思想: 把运算过程尽量写成一系列嵌套的函数调用。面向对象是按人们认识客观世界的系统思维方式,把构成问题事务分解成各个对象,建立对
象的目的不是为了完成一个步骤,而是为了描叙某个事物在整个解决问题的步骤中的行为。# 类(Class)class Cat: # 属性:一般是名词,eg:name,age,gender.... name = 'name' kind = 'kind' # 方法:一般情况是动词,eg:create,delete,eating,run... def eat(self): print('cat like eating fish...')#对象(Object):对类得实例化(具体化)jiongjiong = Cat()print(Cat) #print(jiongjiong) #<__main__.Cat object at 0x000001E5D1684B50>
类(Class)是是创建实例的模板
对象(Object)是一个一个具体的实例面向对象的三大特性是指:封装、继承和多态
(1)封装,顾名思义就是将内容封装到某个地方,以后再去调用被封装在某处的内容。
所以,在使用面向对象的封装特性时,需要: 1). 将内容封装到某处 2). 从某处调用被封装的内容 1). 通过对象直接调用被封装的内容: 对象.属性名 2). 通过self间接调用被封装的内容: self.属性名 3). 通过self间接调用被封装的内容: self.方法名()构造方法__init__与其他普通方法不同的地方在于,当一个对象被创建后,会立即调
用构造方法。自动执行构造方法里面的内容。 对于面向对象的封装来说,其实就是使用构造方法将内容封装到 对象 中,然后通过 对象直接或者self间接获取被封装的内容。# 类(Class)class Cat: def __init__(self, name, kind): # 形参 """ 1. 构造方法,实例化对象时自动执行的方法 2. self是什么? self实质上是实例化的对象 3. 类方法中, python解释器会自动把对象作为参数传给self """ print('正在执行__init__构造方法') print('self:', self) # 属性:一般是名词,eg: name, age, gender..... # 封装: self.name将对象和name属性封装/绑定 self.name = name self.kind = kind # 方法: 一般情况是动词, eg: create, delete, eating, run...... def eat(self): print('cat %s like eating fish.....' %(self.name))# 对象(Object):对类的实例化(具体化)jiongjiong = Cat("囧囧", "美短虎斑")print(jiongjiong.name)print(jiongjiong.kind)jiongjiong.eat()
代码运行结果:
创建一个类People,拥有的属性为姓名, 性别和年龄, 拥有的方法为购物,玩游戏,学习;实例化 对象,执行相应的方法。 显示如下: 小明,18岁,男,去西安赛格购物广场购物 小王,20岁,男,去西安赛格购物广场购物 小红,22岁,女,在西部开源学习 提示: 属性:name,age,gender 方法:shopping(), playGame(), learning()"""创建一个类People,拥有的属性为姓名, 性别和年龄, 拥有的方法为购物,玩游戏,学习;实例化对象,执行相应的方法。 显示如下:小明,18岁,男,去西安赛格购物广场购物小王,20岁,男,去西安赛格购物广场购物小红,22岁,女,在西部开源学习提示:属性:name,age,gender方法:shopping(), playGame(), learning()"""class People: def __init__(self,name,age,gender): self.name = name self.age = age self.gender = gender def shopping(self): print(f'{self.name},{self.age}岁,{self.gender},去西安赛格购物广场购物') def learning(self): print(f'{self.name},{self.age}岁,{self.gender},在西部开源学习')p1 = People('小明','18','男')p2 = People('小王','20','男')p3 = People('小红','22','女')p1.shopping()p2.shopping()p3.learning()
代码运行结果:
面向对象的三大特性是指:封装、继承和多态
继承描述的是事物之间的所属关系,当我们定义一个class的时候,可以从某个现有的class继承,新的class称为子类、扩展类(Subclass),而被继承的class称为基类、父类或超类(Baseclass、
Superclass)。class Student: def __init__(self,name,age): self.name = name self.age = age def learning(self): print(f'{self.name}正在学习')class MathStudent(Student): """MathStudent的父类是student""" pass#实例化m1 = MathStudent('华罗庚',88)print(m1.name)print(m1.age)m1.learning() #子类没有就会去父类找# m1.choice_course() #子类和父类都没有就会报错
代码运行结果:
就是子类中,有一个和父类相同名字的方法,在子类中的方法会覆盖掉父类中同名的方法。
class Student: def __init__(self,name,age): self.name = name self.age = age def learning(self): print(f'{self.name}正在学习') def choice_course(self): print('正在选课中'.center(50,'*'))class MathStudent(Student): """MathStudent的父类是student""" def choice_course(self): # 需求:先执行父类的方法choice_course,再个性化执行自己的方法 #Student.choice_course(self) #方法1:直接执行父类的方法,但不建议 #方法2:通过super找到父类的方法,再执行()中的。 super(MathStudent,self).choice_course() info = """ 课程表 1. 高数 2. 线性代数 3. 概率论 """ print(info)#实例化m1 = MathStudent('华罗庚',88)m1.choice_course()
代码运行结果:
#Definition for singly-linked list.# class ListNode:# def __init__(self, val=0, next=None):# self.val = val# self.next = nextclass Solution: def addTwoNumbers(self, l1: ListNode, l2: ListNode) -> ListNode: res = 0 l3 = ListNode() cur = l3 while(l1 or l2): if(l1): res += l1.val # res=2 l1 = l1.next if(l2): res += l2.val # res=2+5=7 l2 = l2.next # res=10, val=0, res=>val val=res%10 # res=14, val=4, 14%10=4 l3.next = ListNode(res%10) l3 = l3.next # res=10, 进位为1, 10//10=1 # res=14, 进位为1, 14//10=1 res //= 10 if res == 1: l3.next = ListNode(1) return cur.next
"""参考链接 https://www.cnblogs.com/klyjb/p/11237361.html数组: 需要连续的内存空间链表: 不需要连续的内存空间 数组 链表增加元素 O(n) O(1)删除元素 O(n) O(1)修改元素 O(1) O(n)查看元素 O(1) O(n)"""# 封装节点类class ListNode: def __init__(self, val=0, next=None): self.val = val self.next = next def travel(self, head): """遍历链表里面的每一个元素""" while head: print(head.val, end=',') head = head.nextdef create_l1(): # l1 = 2,4,3 # l2 = 5, 6, 4 l1 = ListNode() node1 = ListNode(val=2) node2 = ListNode(val=4) node3 = ListNode(val=3) l1.next = node1 node1.next = node2 node2.next = node3 return l1.nextdef create_l2(): # l1 = 2,4,3 # l2 = 5, 6, 4 l2 = ListNode() node1 = ListNode(val=5) node2 = ListNode(val=6) node3 = ListNode(val=4) l2.next = node1 node1.next = node2 node2.next = node3 return l2.nextdef addTwoNumbers(l1: ListNode, l2: ListNode) -> ListNode: res = 0 l3 = ListNode() cur = l3 while(l1 or l2): if(l1): res += l1.val # res=2 l1 = l1.next if(l2): res += l2.val # res=2+5=7 l2 = l2.next # res=10, val=0, res=>val val=res%10 # res=14, val=4, 14%10=4 l3.next = ListNode(res%10) l3 = l3.next # res=10, 进位为1, 10//10=1 # res=14, 进位为1, 14//10=1 res //= 10 if res == 1: l3.next = ListNode(1) return cur.next if __name__ == '__main__': l1 = create_l1() l2 = create_l2() l3 = addTwoNumbers(l1, l2) l3.travel(l3)
多继承,即子类有多个父类,并且具有它们的特征
在Python 2及以前的版本中,由任意内置类型派生出的类,都属于“新式
类” ,都会获得所有“新式类”的特性;反之,即不由任意内置类型派生出的类, 则称之为“经典类”。 “新式类”和“经典类”的区分在Python 3之后就已经不存在,在Python 3.x之后的版本,因为所有的类都派生自内置类型object(即使没有显示的继承object类型),即所有的类都是“新式类”。 最明显的区别在于继承搜索的顺序不同,即: 经典类多继承搜索顺序(深度优先算法):先深入继承树左侧查找,然后再返回,开始查找右侧。 新式类多继承搜索顺序(广度优先算法):先在水平方向查找,然后再向上查找,"""新式类: 广度优先算法经典类: 深度优先算法(py2中的部分类属于经典类)python3所有的类都属于新式类。新式类的继承算法是广度优先。# 分析多继承的相关代码>pip install djangorestframeworkfrom rest_framework import viewsetsviewsets.ModelViewSet"""class D(object): def hello(self): print('D')class C(D): # def hello(self): # print('C') passclass B(D): pass # def hello(self): # print('B')class A(B, C): pass # def hello(self): # print('A')a = A()a.hello()
默认情况下,属性在 Python 中都是“public”, 大多数 OO 语言提供“访问控制符”来限定成员函数的访问。
在 Python 中,实例的变量名如果以 __ 开头,就变成了一个私有变量/属性 (private),实例的函数名如果以 __ 开头,就变成了一个私有函数/方法(private)只 有内部可以访问,外部不能访问。class Student: """父类Student""" def __init__(self, name, age, score): self.name = name self.age = age # 私有属性,以双下划线开头。 # 工作机制: 类的外部(包括子类)不能访问和操作,类的内部可以访问和操作。 self.__score = score def learning(self): print(f'{self.name}正在学习') def get_score(self): self.__modify_score() return self.__score # 私有方法是以双下划线开头的方法, #工作机制: 类的外部(包括子类)不能访问和操作,类的内部可以访问和操作。 def __modify_score(self): self.__score += 20class MathStudent(Student): """MathStudent的父类是Student""" def get_score(self): self.__modify_score() return self.__score# 报错原因: 子类无法继承父类的私有属性和私有方法。s1 = MathStudent('张三', 18, 100)score = s1.get_score()print(score)
多态(Polymorphism)按字面的意思就是“多种状态”。在面向对象语言中,接口的多种不同的实现方式即为多态。通俗来说: 同一操作作用于不同的对象,可以有不同的解释,产生不同的执行结果。
多态的好处就是,当我们需要传入更多的子类,只需要继承父类就可以了,而方法既可以直接不重写(即使用父类的),也可以重写一个特有的。这就是多态的意思。调用方只管调用,不管细节,而当我们新增一种的子类时,只要确保新方法编写正确,而不用管原来的代码。这就是著名的“开闭”原则:
对扩展开放(Open for extension):允许子类重写方法函数 对修改封闭(Closed for modification):不重写,直接继承父类方法函数