标签:参数传递 容器 school 单点 释放 close 任务 函数 err
对不同的编程方式的特点进行归纳总结得出来的编程方式类别,即为编程范式。 不同的编程范式本质上代表对各种类型的任务采取的不同的解决问题的思路。 两种最重要的编程范式分别是面向过程编程和面向对象编程。
面向过程编程(Procedural Programming)
Procedural programming uses a list of instructions to tell the computer what to do step-by-step.
面向过程又被称为top-down languages, 就是程序从上到下一步步执行,一步步从上到下,从头到尾的解决问题 。基本设计思路就是程序一开始是要着手解决一个大的问题,然后把一个大问题分解成很多个小问题或子过程,这些子过程再执行的过程再继续分解直到小问题足够简单到可以在一个小步骤范围内解决。
举个典型的面向过程的例子, 数据库备份, 分三步,连接数据库,备份数据库,测试备份文件可用性。
代码如下
1 def db_conn(): 2 print("connecting db...") 3 4 def db_backup(dbname): 5 print("导出数据库...", dbname) 6 print("将备份文件打包,移至相应目录...") 7 8 def db_backup_test(): 9 print("将备份文件导入测试库,看导入是否成功") 10 11 def main(): 12 db_conn() 13 db_backup(‘my_db‘) 14 db_backup_test() 15 16 if __name__ == ‘__main__‘: 17 main()
这样做的问题也是显而易见的,就是如果你要对程序进行修改,对你修改的那部分有依赖的各个部分你都也要跟着修改, 举个例子,如果程序开头你设置了一个变量值 为1 , 但如果其它子过程依赖这个值 为1的变量才能正常运行,那如果你改了这个变量,那这个子过程你也要修改,假如又有一个其它子程序依赖这个子过程 , 那就会发生一连串的影响,随着程序越来越大, 这种编程方式的维护难度会越来越高。
所以我们一般认为, 如果你只是写一些简单的脚本,去做一些一次性任务,用面向过程的方式是极好的,但如果你要处理的任务是复杂的,且需要不断迭代和维护 的, 那还是用面向对象最方便了。
OOP编程是利用“类”和“对象”来创建各种模型来实现对真实世界的描述,使用面向对象编程的原因一方面是因为它可以使程序的维护和扩展变得更简单,并且可以大大提高程序开发效率 ,另外,基于面向对象的程序可以使它人更加容易理解你的代码逻辑,从而使团队开发变得更从容。
面向对象的几个核心特性如下
Class 类
一个类即是对一类拥有相同属性的对象的抽象、蓝图、原型。在类中定义了这些对象的都具备的属性(variables(data))、共同的方法
Object 对象
一个对象即是一个类的实例化后实例,一个类必须经过实例化后方可在程序中调用,一个类可以实例化多个对象,每个对象亦可以有不同的属性,就像人类是指所有人,每个人是指具体的对象,人与人之前有共性,亦有不同
Encapsulation 封装
在类中对数据的赋值、内部调用对外部用户是透明的,这使类变成了一个胶囊或容器,里面包含着类的数据和方法
Inheritance 继承
一个类可以派生出子类,在这个父类里定义的属性、方法自动被子类继承
Polymorphism 多态
多态是面向对象的重要特性,简单点说:“一个接口,多种实现”,指一个基类中派生出了不同的子类,且每个子类在继承了同样的方法名的同时又对父类的方法做了不同的实现,这就是同一种事物表现出的多种形态。
编程其实就是一个将具体世界进行抽象化的过程,多态就是抽象化的一种体现,把一系列具体事物的共同点抽象出来, 再通过这个抽象的事物, 与不同的具体事物进行对话。
多态允许将子类的对象当作父类的对象使用,某父类型的引用指向其子类型的对象,调用的方法是该子类型的方法。这里引用和调用方法的代码编译前就已经决定了,而引用所指向的对象可以在运行期间动态绑定
适用场景:①根据一个模板创建多个对象时
②很多函数有多个共同的参数时
③很多函数有相同的功能时
类的定义(默认使用新式类)
经典类定义示例代码
1 class SchoolMember: 2 def __init__(self,name,age): 3 self.name = name 4 self.age = age 5 def sayhi(self): 6 print("in class SchoolMember") 7 8 class Teacher(SchoolMember): 9 def __init__(self,name,age): 10 SchoolMember.__init__(self,name,age) #经典类的继承 11 def sayhi(self): 12 print("in class Teacher" ) 13 14 t1 = Teacher ("zjt",23) 15 t1.sayhi()
新式类定义示例代码
1 class SchoolMember(object): 2 def __init__(self,name,age): 3 self.name = name 4 self.age = age 5 def sayhi(self): 6 print("Hello , my name is %s"%self.name) 7 8 class Teacher(SchoolMember): 9 def __init__(self,name,age): 10 super(Teacher,self).__init__(name,age) #新式类的继承 11 def sayhi(self): 12 print("Hello , I‘m a teacher,my name is %s" % self.name) 13 14 t1 = Teacher ("zjt",23) 15 t1.sayhi()
类的语法
1 class Role(object): 2 def __init__(self,name,role,weapon,life_value=100,money=15000): 3 ‘‘‘构造方法(初始化方法、初始化函数)‘‘‘ 4 self.name = name #属性,成员变量,作用域为整个类 5 self.role = role 6 self.weapon = weapon 7 self.life_value = life_value 8 self.money = money 9 self.__heart = "normal" #私有属性 10 11 nationality = "中国" #公有属性 12 __money = "10000" #公有的?私有属性 13 14 def get_heart_money(self): #私有属性对外部提供的只读访问接口 15 return [self.__heart,self.__money] 16 17 def eat(self,food): #方法(动态属性),food 的作用域只是在这个方法里边 18 print("%s is eatting %s"%(self.name,food)) 19 20 def __del__(self): #可不写 21 ‘‘‘析构方法‘‘‘ 22 print("\033[31;1mmember [%s] is dead!\033[0m" %self.name) 23 24 r1 = Role(‘Alex‘,‘police‘,‘AK47‘) #生成一个角色,会自动把参数传给 Role下面的__init__(...)方法 25 r2 = Role(‘Jack‘,‘terrorist‘,‘B22‘) #生成一个角色 26 27 #print(r1.__heart) #直接访问私有属性 28 #执行结果:报错 >>>AttributeError: ‘Role‘ object has no attribute ‘__heart‘ 29 print(r1.get_heart_money()) #通过类对外部提供的只读访问接口访问私有属性 30 #执行结果:[‘normal‘, ‘10000‘] 31 print("__heart: %s,__money: %s"%(r1._Role__heart,r1._Role__money)) #强制访问私有属性 32 #执行结果:__heart: normal,__money: 10000 33 34 print(Role.nationality) #执行结果:中国 35 Role.nationality = "美国" # 修改类里边的 36 print(Role.nationality) #执行结果:美国 37 r1.nationality = "日本" # 修改实例里边的,访问时先找本地的,没有再找全局的 38 print(Role.nationality) #执行结果:美国 39 print(r1.nationality) #执行结果:日本
代码解析:
1、class Role(object) >>> 定义一个类, class是定义类的语法,Role是类名(通常首字母大写),(object)是新式类的写法
2、__init__(self,...) >>> 初始化方法(或构造方法), 在类被调用时,这个方法会自动执行,进行一些初始化的动作
self,就是实例本身!你实例化时python会自动把这个实例本身通过self参数传进去。
3、构造方法里边定义的变量 --> 普通属性,成员变量,作用域为整个类
self.name = name
self.role = role
...
4、私有属性:变量名以两条下划线开头,可以在类里直接定义或者在构造方法里定义,只允许类内部访问不允许类外访问.
外部访问的方法:①可通过内部提供的只读访问接口 (较为安全)
def get_heart(self):
return self.__heart
②强制访问:实例名._类名__私有属性名
r1._Role__heart
5、公有属性(类变量):在类里直接定义的属性,而不是在构造方法 __init__里边定义的,保存在类中
6、析构方法:在实例释放、销毁的时候自动执行的,通常用于做一些收尾工作,如关闭一些数据库连接,关闭打开的临时文件
python默认存在析构方法,默认不执行任何操作,用户写析构方法,就是重构默认的析构方法。
示例代码运行结束后会自动执行以下析构方法:
def __del__(self):
print("\033[31;1mmember [%s] is dead!\033[0m" %self.name)
执行结果:
member [Jack] is dead!
member [Alex] is dead!
7、r1 = Role(‘Alex‘,‘police‘,‘AK47’)
①、生成一个角色,会自动把参数传给 Role下面的__init__(...)方法
②、此时self 相当于 r1,r1 = Role(‘Alex‘,‘police‘,‘AK47’) == Role(r1,‘Alex‘,‘police‘,‘AK47’)
这个动作就是类的“实例化”,也就是把一个虚拟的抽象的类,通过这个动作,变成了一个具体的对象了,这个对象就叫做实例.
封装是面向对象的特征之一,是对象和类概念的主要特性。
1、防止数据被随意修改
2、使外部程序不需要关注对象内部构造,只需通过此对象对外提供的接口进行直接访问即可
类中封装了属性(字段)、方法,而对象中封装了普通属性的值。
示例代码:
1 class F1: 2 def __init__(self,n): 3 self.N = n 4 print(‘F1‘) 5 class F2: 6 def __init__(self,arg1): 7 self.a = arg1 8 print(‘F2‘) 9 class F3: 10 def __init__(self,arg2): 11 self.b = arg2 12 print(‘F3‘) 13 o1 = F1(‘Alex‘) 14 o2 = F2(o1) 15 o3 = F3(o2) 16 17 ##### 输出Alex####### 18 #o3.b = o2 , o2.a = o1 ,o1.N = "Alex" 19 print(o3.b.a.N)
封装可以封装字符串、数字、函数,也可以封装对象(把对象当参数)。
面向对象编程 (OOP) 语言的一个主要功能就是“继承”。继承是指这样一种能力:它可以使用现有类的所有功能,并在无需重新编写原来的类的情况下对这些功能进行扩展。
通过继承创建的新类称为“子类”或“派生类”。
被继承的类称为“基类”、“父类”或“超类”。
继承的过程,就是从一般到特殊的过程。
要实现继承,可以通过“继承”(Inheritance)和“组合”(Composition)来实现。
在某些 OOP 语言中,一个子类可以继承多个基类。但是一般情况下,一个子类只能有一个基类,要实现多重继承,可以通过多级继承来实现。
继承概念的实现方式主要有2类:实现继承、接口继承。
OO开发范式大致为:划分对象→抽象类→将类组织成为层次化结构(继承和合成) →用类与实例进行设计和实现几个阶段。
1 class F1: 2 def __init__(self): 3 print(‘F1‘) 4 def a1(self): 5 print(‘F1a1‘) 6 def a2(self): 7 print(‘F1a2‘) 8 9 class F2(F1): 10 def __init__(self): 11 print(‘F2‘) 12 def a1(self): 13 self.a2() 14 print(‘F2a1‘) 15 def a2(self): 16 print(‘F2a2‘) 17 18 class F3(F2): 19 def __init__(self): 20 print(‘F3‘) 21 # def a1(self): 22 # print(‘F3a1‘) 23 def a2(self): 24 print(‘F3a2‘) 25 26 obj = F3() 27 obj.a1() #self == obj,先在F3找a1,找不到就到父类F2找 28 #执行结果:F3 >>> F3a2 >>> F2a1
多重继承时,需要注意圆括号中基类的顺序。再调用方法时首先调用本类方法,然后搜索基类方法。调用方法或访问属性时本类采用self,基类则使用括号中基类的名字指定。
1 class SubClass(BaseClass1, BaseClass2): 2 pass
Python中还提供了super()
来解决多重继承问题,直接用类名调用父类方法在使用单继承的时候没问题,但是如果使用多继承,会涉及到查找顺序(MRO)、重复调用(钻石继承)等种种问题。super机制里可以保证公共父类仅被执行一次,执行的顺序由__mro__
决定。
1 class SchoolMember(object): 2 def __init__(self,name,age,sex): 3 self.name = name 4 self.age = age 5 self.sex = sex 6 def tell(self): 7 pass 8 9 class Teacher(SchoolMember): 10 def __init__(self,name,age,sex,salary,course):#先覆盖 11 super(Teacher,self).__init__(name,age,sex)#再继承 12 self.salary = salary #再重构 13 self.course = course #再重构 14 15 class Student(SchoolMember): 16 def __init__(self,name,age,sex,stu_id,grade): #先覆盖 17 super(Student,self).__init__(name,age,sex) #再继承 18 self.stu_id = stu_id #再重构 19 self.grade = grade #再重构 20 21 t1 = Teacher("Oldboy",56,"MF",200000,"Linux") 22 t2 = Teacher("Alex",22,"M",3000,"PythonDevOps") 23 24 s1 = Student("ChenRonghua",36,"MF",1001,"PythonDevOps") 25 s2 = Student("徐良伟",19,"M",1002,"Linux")
若是基类中有相同的方法名,而在子类使用时未指定,Python从左至右搜索 即方法在子类中未找到时,从左到右查找基类中是否包含方法。
1 class A(object): 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 #pass 10 def __init__(self): 11 print("C") 12 class D(B,C): 13 pass 14 # def __init__(self): 15 # print("D") 16 17 18 obj = D()
多级继承的顺序:
Python3:经典类与新式类都是广度查询优先,方法在子类中未找到时,从左到右查找基类中是否包含方法。
Python2:经典类:深度查询优先(从下往上),新式类:广度查询优先(从左到右)
组合
继承多个类时,并且父类的构造方法所封装的属性不一样,可以使用组合的方式,就是把父类实例化后的对象当做参数传递进来,封装在构造方法里
1 class SchoolMember(object): 2 def __init__(self,name,age): 3 self.name = name 4 self.age = age 5 6 class School(object): 7 def __init__(self,addr): 8 self.addr = addr 9 10 class Teacher(SchoolMember): 11 def __init__(self,name,age,school_obj): #把一个实例化后的对象当做参数传递进来 12 super(Teacher,self).__init__(name,age) 13 self.school = school_obj 14 15 s1 = School("beijing") 16 t1 = Teacher(‘alex‘,20,s1) 17 #多继承的继承顺序:Python3 广度继承优先(从左往右) 18 print(t1.school.addr)
1 class Animal: 2 def __init__(self, name): 3 self.name = name 4 5 def talk(self): 6 raise NotImplementedError("子类必须重构 talk 方法!") 7 8 @staticmethod 9 def animal_talk(obj): 10 obj.talk() 11 12 # def animal_talk(obj): #一个接口,多种形态 13 # obj.talk() 14 15 class Cat(Animal): 16 def talk(self): 17 print(‘Meow!‘) 18 class Dog(Animal): 19 def talk(self): 20 print(‘Woof! Woof!‘) 21 22 d = Dog("Alex") 23 c = Cat("Jack") 24 d.talk() 25 c.talk() 26 27 #多态,接口的通用 28 Animal.animal_talk(d) 29 Animal.animal_talk(c)
标签:参数传递 容器 school 单点 释放 close 任务 函数 err
原文地址:http://www.cnblogs.com/zjtong/p/7367769.html