面向过程编程
关键在于过程 过程指的是,先干啥 再干啥 最后干啥,设计思想好比一条流水线 注意:面向过程与函数编程是完全不同的 优点:将复杂的问题流程化,简单化 缺点:由于代码严格按照流程编写,导致扩展性极差 ----------------------------------- #面共对象对比面向过程 #使用面向对象来编写程序时,不去思考具体的实现步骤,重点是什么样的对象可以完成这个事情 面向过程想的是:怎么做 面向对象想的是:谁来做 优点:扩展性高,修改单独某一个对象,不会影响其他对象灵活度,复用性,降低耦合度 缺点:1、相对于面向过程而言,编程的复杂度提高了 2、无法准确预知执行结果 使用场景:对扩展性要求较高的应用程序(面向用户的应用程序扩展性较高)
一、面向对象简介
#什么是面向对象 是一种编程思想 关键在于对象, #什么是对象:一系列特征和技能的结合体 ------------------------------------------------------ 1、使用面型对象开发,第一步是设计 类 2、使用 类名() 创建对象,创建对象的动作有两步: 1)在内存中为对象分配空间 2)调用初始化方法__init__ 为对象初始化 3、对象创建后,内存中就有了一个对象的 实实在在 的存在--实例 因此,通常会把: 1、创建出来的 对象 叫做 类的实例 2、创建对象的 动作 叫做实例化 3、对象的属性叫做实例属性 4、对象的调用方法叫做实例方法 在程序执行时 1、对象各自拥有自己的 实例属性 2、调用对象方法,可以通过self. 访问自己的属性 调用自己的方法 结论 ·每一个对象 都有自己 独立的内存空间 ,保存各自不同的属性 ·多个对象的方法,在内存中只有一份,在调用方法时,需要把对象的引用 传递到方法的内部
二、类与对象基础
#2.1类和对象的关系 生活中:先有对象,再有类 (先有人,再有人类) 程序中:先有类,再由类产生对象 (先定义需求,再产生对象 #2.2什么是类 类是一系列相同特征(变量)与技能(函数)的对象的结合体,即类体中最常见的就是变量和函数的定义 #2.3类的本质 类体代码会在类定义阶段立即执行,会产生一个类的名称空间,用来将类体代码执行过程中产生的名字都丢进去 本质:是一个名称空间,或者说是一个用来存放变量与函数的的容器 #2.4类的用途 类的用途之一:当做名称空间从内部取出名字来使用 类的用途之二:调用类来产生对象
三、对象传值的两种方式
class Student: def choose_course(self): pass stu1=Student() stu1.name = 'pdun' #对象. stu1.age = 1 stu1.sex = 'man'
#__init__的功能:是在实例化时就为对象初始自己独有的特征 #注意:不能有返回值 class Student: def __init__(self,name, age, sex): self.name = name self.age = age self.sex = sex stu =Student('pdun',1,'man')
类方法
#类方法可以直接被类调用,不需要对象 #当一个方法只涉及改变静态属性(类中的变量)时,应考虑用@classmethod class Goods(): price=10 @classmethod def new_price(cls,new_price): cls.price=new_price print(cls.price) Goods.new_price(5) obj = Goods() print(obj.price)
静态方法
#在完全面向对象编程中,如果一个函数,既和对象没有关系,也与类没有关系,就用staticmethod把它变成静态方法,使用时直接 对象.该方法 class Static(): @staticmethod def login(): user = input('用户名:') pwd = input('密码:') print(user,pwd) Static.login()
#总结 1、类方法和静态方法都是类调用的 2、对象可以调用静态方法和类方法吗? 可以,但一般推荐类调用 3、静态方法没有参数,它就相当于一个普通的函数,只不过在调用的时候多加一个类名罢了,它相当于普通函数,当然可以传参
元类
#exec:三个参数 #参数一:包含一系列python代码的字符串 #参数二:全局作用域(字典形式),如果不指定,默认为globals() #参数三:局部作用域(字典形式),如果不指定,默认为locals() #可以把exec命令的执行当成是一个函数的执行,会将执行期间产生的名字存放于局部名称空间中 例如
class_dic = {}
exec("x=1",{},class_dic)
print(class_dic)
>>{'x': 1}
会把x=1执行时产生的名称空间放到class_dic中
如果在执行代码时需要用到全局的名称空间,就到参数二中找
#拿到类名 class_name = "OldBoy" #拿到类的基类们 class_bases = (object,) #执行函数体代码,拿到名称空间 class_dic = {} x = """ school = "oldboy" def __init__(self,name,age): self.name = name self.age = age def score(self): print("name is %s" % self.name) """ exec(x,{},class_dic) #执行代码,将所产生的名称空间放到class_dic中 print(class_dic) OldBoy = type(class_name,class_bases,class_dic) #调用元类得到类
#!!但凡继承了type的类,才称之为元类,否则只是普通的类!! class Mymetaclass(type): def __init__(self,class_name,class_bases,class_dic): print(self) print(class_name) print(class_bases) print(class_dic) class OldBoy(metaclass=Mymetaclass): a = 1 def __init__(self,name): self.name = name ------------------------------------------------------ #错误的 class Mymetaclass(type): def __init__(self): #错误在此处 print(self) class OldBoy(metaclass=Mymetaclass): a = 1 def __init__(self,name): self.name = name >>TypeError: __init__() takes 1 positional argument but 4 were given #说明底层原理是 #OldBoy = Mymetaclass(OldBoy ,class_bases,class_dic) #需要把自身,类名,类的基类,所产生的名称空间一起传给元类
自定义元类控制类的产生
自定义元类可以控制类的产生过程,类的产生过程其实就是元类的调用过程, 即OldboyTeacher=Mymeta('OldboyTeacher',(object),{...}), 调用Mymeta会先产生一个空对象OldoyTeacher, 然后连同调用Mymeta括号内的参数一同传给Mymeta下的__init__方法,完成初始化,于是我们可以
class Mymeta(type): #只有继承了type类才能称之为一个元类,否则就是一个普通的自定义类 def __init__(self,class_name,class_bases,class_dic): # print(self) #<class '__main__.OldboyTeacher'> # print(class_bases) #(<class 'object'>,) # print(class_dic) #{'__module__': '__main__', '__qualname__': 'OldboyTeacher', 'school': 'oldboy', '__init__': <function OldboyTeacher.__init__ at 0x102b95ae8>, 'say': <function OldboyTeacher.say at 0x10621c6a8>} super(Mymeta, self).__init__(class_name, class_bases, class_dic) # 重用父类的功能 if class_name.islower(): raise TypeError('类名%s请修改为驼峰体' %class_name) if '__doc__' not in class_dic or len(class_dic['__doc__'].strip(' ')) == 0: raise TypeError('类中必须有文档注释,并且文档注释不能为空') class OldboyTeacher(object,metaclass=Mymeta): # OldboyTeacher=Mymeta('OldboyTeacher',(object),{...}) """ 类OldboyTeacher的文档注释 """ school='oldboy' def __init__(self,name,age): self.name=name self.age=age def say(self): print('%s says welcome to the oldboy to learn Python' %self.name)
自定义元类控制类的调用