为了账号安全,请及时绑定邮箱和手机立即绑定

面向对象编程知识点综合

标签:
Python

一、面向对象编程与面向过程编程对比

  1、面向过程编程:核心过程二字,过程指的是解决问题的步骤,既先干什么、再干什么、后干什么,基于该思想的编程就好比在生产一条流水线,是一种机械式的思维方式。

    优点:复杂的问题流程化进而简单化

    缺点:可扩展性差

  2、面向对象编程:核心是对象二字,对象是技能与特征的结合体,基于该思想编写程序就好比在创造一个世界,世界是由一个个对象组成的,在上帝眼里任何存在的事物都是对象,任何不存在的事物也都可以创造出来,是一种上帝式的思维方式

    优点:可扩展性强

    缺点:编程的复杂度要高于面向过程

二、类与对象

  对象:对象是技能与特征的结合体

  类:对象相同特征与技能的结合体

    对象是具体存在的事物,而类则是抽象出来的概念,站在不同角度总结出来的类与对象是不同的

    在现实世界中,现有一个个具体存在的对象,然后随着人类文明的发展才总结出类的概念

复制代码

#在现实世界中,站在老男孩学校的角度:先有对象,再有类对象1:李坦克
    特征:
        学校=oldboy
        姓名=李坦克
        性别=男
        年龄=18
    技能:
        学习
        吃饭
        睡觉

对象2:王大炮
    特征:
        学校=oldboy
        姓名=王大炮
        性别=女
        年龄=38
    技能:
        学习
        吃饭
        睡觉

对象3:牛榴弹
    特征:
        学校=oldboy
        姓名=牛榴弹
        性别=男
        年龄=78
    技能:
        学习
        吃饭
        睡觉


现实中的老男孩学生类
    相似的特征:
        学校=oldboy
    相似的技能:
        学习
        吃饭
        睡觉

复制代码

View Code

 

    在程序中,是先定义出类的概念后调用类来产生对象

复制代码

#在程序中,务必保证:先定义(类),后使用(产生对象)PS:  1. 在程序中特征用变量标识,技能用函数标识  2. 因而类中最常见的无非是:变量和函数的定义#程序中的类class OldboyStudent:
    school='oldboy'
    def learn(self):        print('is learning')        
    def eat(self):        print('is eating')    
    def sleep(self):        print('is sleeping')  


#注意:
  1.类中可以有任意python代码,这些代码在类定义阶段便会执行  2.因而会产生新的名称空间,用来存放类的变量名与函数名,可以通过OldboyStudent.__dict__查看
  3.对于经典类来说我们可以通过该字典操作类名称空间的名字(新式类有限制),但python为我们提供专门的.语法  4.点是访问属性的语法,类中定义的名字,都是类的属性#程序中类的用法.:专门用来访问属性,本质操作的就是__dict__
OldboyStudent.school #等于经典类的操作OldboyStudent.__dict__['school']OldboyStudent.school='Oldboy' #等于经典类的操作OldboyStudent.__dict__['school']='Oldboy'OldboyStudent.x=1 #等于经典类的操作OldboyStudent.__dict__['x']=1del OldboyStudent.x #等于经典类的操作OldboyStudent.__dict__.pop('x')#程序中的对象#调用类,或称为实例化,得到对象s1=OldboyStudent()
s2=OldboyStudent()
s3=OldboyStudent()#如此,s1、s2、s3都一样了,而这三者除了相似的属性之外还各种不同的属性,这就用到了__init__#注意:该方法是在对象产生之后才会执行,只用来为对象进行初始化操作,可以有任意代码,但一定不能有返回值class OldboyStudent:
    ......    def __init__(self,name,age,sex):
        self.name=name
        self.age=age
        self.sex=sex
    ......


s1=OldboyStudent('李坦克','男',18) #先调用类产生空对象s1,然后调用OldboyStudent.__init__(s1,'李坦克','男',18)s2=OldboyStudent('王大炮','女',38)
s3=OldboyStudent('牛榴弹','男',78)#程序中对象的用法#执行__init__,s1.name='牛榴弹',很明显也会产生对象的名称空间s2.__dict__{'name': '王大炮', 'age': '女', 'sex': 38}

s2.name #s2.__dict__['name']s2.name='王三炮' #s2.__dict__['name']='王三炮's2.course='python' #s2.__dict__['course']='python'del s2.course #s2.__dict__.pop('course')

复制代码

View Code

  __init__方法

复制代码

#方式一、为对象初始化自己独有的特征class People:
    country='China'
    x=1    def run(self):        print('----->', self)# 实例化出三个空对象obj1=People()
obj2=People()
obj3=People()# 为对象定制自己独有的特征obj1.name='egon'obj1.age=18obj1.sex='male'obj2.name='lxx'obj2.age=38obj2.sex='female'obj3.name='alex'obj3.age=38obj3.sex='female'# print(obj1.__dict__)# print(obj2.__dict__)# print(obj3.__dict__)# print(People.__dict__)#方式二、为对象初始化自己独有的特征class People:
    country='China'
    x=1    def run(self):        print('----->', self)# 实例化出三个空对象obj1=People()
obj2=People()
obj3=People()# 为对象定制自己独有的特征def chu_shi_hua(obj, x, y, z): #obj=obj1,x='egon',y=18,z='male'
    obj.name = x
    obj.age = y
    obj.sex = z

chu_shi_hua(obj1,'egon',18,'male')
chu_shi_hua(obj2,'lxx',38,'female')
chu_shi_hua(obj3,'alex',38,'female')#方式三、为对象初始化自己独有的特征class People:
    country='China'
    x=1    def chu_shi_hua(obj, x, y, z): #obj=obj1,x='egon',y=18,z='male'
        obj.name = x
        obj.age = y
        obj.sex = z    def run(self):        print('----->', self)


obj1=People()# print(People.chu_shi_hua)People.chu_shi_hua(obj1,'egon',18,'male')

obj2=People()
People.chu_shi_hua(obj2,'lxx',38,'female')

obj3=People()
People.chu_shi_hua(obj3,'alex',38,'female')# 方式四、为对象初始化自己独有的特征class People:
    country='China'
    x=1    def __init__(obj, x, y, z): #obj=obj1,x='egon',y=18,z='male'
        obj.name = x
        obj.age = y
        obj.sex = z    def run(self):        print('----->', self)

obj1=People('egon',18,'male') #People.__init__(obj1,'egon',18,'male')obj2=People('lxx',38,'female') #People.__init__(obj2,'lxx',38,'female')obj3=People('alex',38,'female') #People.__init__(obj3,'alex',38,'female')# __init__方法# 强调:#   1、该方法内可以有任意的python代码#   2、一定不能有返回值class People:
    country='China'
    x=1    def __init__(obj, name, age, sex): #obj=obj1,x='egon',y=18,z='male'
        # if type(name) is not str:
        #     raise TypeError('名字必须是字符串类型')
        obj.name = name
        obj.age = age
        obj.sex = sex    def run(self):        print('----->', self)# obj1=People('egon',18,'male')obj1=People(3537,18,'male')# print(obj1.run)# obj1.run() #People.run(obj1)# print(People.run)

复制代码

View Code

类是一系列对象相同特征与技能的结合体,既类体中最常见的就是变量与函数体,但其实类体中是可以存在任意python代码的,

类体中会在定义阶段立即执行,会产生一个类的名称空间,用来将类体代码执行过程中产生的名字都丢进去

总结:①类本质就是一个名称空间,或者说就是一个用来存放变量与函数的容器,

     ②类的用途之一就是当做名称空间,从其内部取出名字来使用

   ③类的用途之二是用来调用类产生对象

调用类产生对象:调用类的过程称之为类的实例化,调用类的返回值称之为类的一个对象

View Code

  调用类发生了:

    1、产生一个空对象

    2、触发类中的__init__方法,将对象连同调用类括号内指定的参数一同传入__init__  

      类中定义的变量是类的数据属性,类可以用,对象也可以用,大家都指向同一个地址,类变量值一旦改变,所有对象都跟着改变

      类中定义的函数是类的函数属性,类可以用,类来调用就是一个普通的函数,但其实类中定义的函数就是给对象用的,而且是绑定给对象用的

      绑定方法:指向类的函数(特殊之处是绑定给谁就应该由谁调用)

      类的函数:该传几个参数就传几个参数

三大特性之继承:

  利用继承能来解决类与类之间的代码冗余问题

  继承是一种新建类的方法,新建的类称之为子类(派生类),被继承的类称之为父类、基类、超类

  继承的特性:子类可以遗传、重用父类的属性

python中继承类的特点:

  1、在python中一个子类可以同时继承多个父类

  2、在继承背景下说,python中类分为两种:新式类和经典类

    新式类:但凡继承了object的类以及该类的子类都是新式类

      python中一个类即便没有显示的继承任何类,默认就会继承object,即在python3中所有的类都是新式类

    经典类:没有继承object的类以及该类的子类都是经典类

   在单继承的基础下属性查找的顺序是:对象——》对象类——》父亲——》父类。。。

子类中重用父类的属性:

  方式一:

      在子类派生出的新方法中指名道姓的引用某一个类中的函数

      与继承无关,访问的是父类中的函数没有自动传值功能

继承解决的是类与类之间代码冗余的问题,一定是一个类是另外一个类的子类

总结对象之间的相似之处得到类,总结类之间的相似之处得到的就是父类

  多继承背景下属性查找的顺序:对象--》对象的类--》按照从左往右的顺序一个个的分支找下去

一旦出现菱形继承问题,新式类与经典类在属性查找上的区别是:

  新式类:广度优先查找,在最后一个分支查找顶级类

  经典类:深度优先查找,在第一个分支就查找顶级类

mro()查找的顺序:

  在子类派生出的新的方法中重用父类功能的方式二

    在子类中用super()方法

      python2中:super(自己的类名,对象自己)

      python3中:super()

  调用super()方法会得到一个特殊的对象,该对象是专门用来引用父类中的属性,完全参照mro()列表 访问是绑定方法,有自动传值的效果

组合:

  组合指的是一个对象拥有一个属性,该属性的值属于另外一个类的对象

  组合通过一个对象添加属性(属性的值是另外一个类的对象)的方式,可以间接的将两个类关联、整合,从而减少类之间的代码冗余问题

多态:

  多态指的是同一事物的不同形态

  在多态背景下,可以不用考虑对象具体的类型的前提下直接使用对象多态的精髓:统一

  父类只是用来建立规范的,不能用来实例化的,更无需实现内部方法。

  python崇尚鸭子类型

封装:

  装:往容器、名称空间内存入名字

  封:代表存放于名称空间的名字给藏起来,这种隐藏对外不对内

  在类内定义的属性前加__开头(没有__结尾)

总结:

  1、__开头的属性实现的隐藏仅仅只是一种语法上的变形,并不会真正的限制类外部的访问

  2、该变形操作只在类定义阶段检测语法时发生一次,类定义阶段之后新增的__开头的属性不会变形

  3、如果父类不想让子类覆盖自己的属性,可以在属性前加__开头

  4、peoperty装饰器是用来将类内的函数属性伪装为数据属性

绑定方法与非绑定方法

 

一:绑定方法(绑定给谁,谁来调用就自动将它本身当作第一个参数传入):

    1. 绑定到类的方法:用classmethod装饰器装饰的方法。

                为类量身定制

                类.boud_method(),自动将类当作第一个参数传入

              (其实对象也可调用,但仍将类当作第一个参数传入)

    2. 绑定到对象的方法:没有被任何装饰器装饰的方法。

               为对象量身定制

               对象.boud_method(),自动将对象当作第一个参数传入

             (属于类的函数,类可以调用,但是必须按照函数的规则来,没有自动传值那么一说)

 

复制代码

import settingsclass MySQL:    def __init__(self,host,port):
        self.host=host
        self.port=port

    @classmethod    def from_conf(cls):        print(cls)        return cls(settings.HOST,settings.PORT)print(MySQL.from_conf) #<bound method MySQL.from_conf of <class '__main__.MySQL'>>conn=MySQL.from_conf()

conn.from_conf() #对象也可以调用,但是默认传的第一个参数仍然是类

复制代码

 

 

 

二:非绑定方法:用staticmethod装饰器装饰的方法

        1. 不与类或对象绑定,类和对象都可以调用,但是没有自动传值那么一说。就是一个普通工具而已

    注意:与绑定到对象方法区分开,在类中直接定义的函数,没有被任何装饰器装饰的,都是绑定到对象的方法,可不是普通函数,对象调用该方法会自动传值,而staticmethod装饰的方法,不管谁来调用,都没有自动传值一说

 

复制代码

import hashlibimport timeclass MySQL:    def __init__(self,host,port):
        self.id=self.create_id()
        self.host=host
        self.port=port
    @staticmethod    def create_id(): #就是一个普通工具
        m=hashlib.md5(str(time.time()).encode('utf-8'))        return m.hexdigest()print(MySQL.create_id) #<function MySQL.create_id at 0x0000000001E6B9D8> #查看结果为普通函数conn=MySQL('127.0.0.1',3306)print(conn.create_id) #<function MySQL.create_id at 0x00000000026FB9D8> #查看结果为普通函数

复制代码

View Code

 

classmethod与staticmethod的区别

复制代码

import settingsclass MySQL:    def __init__(self,host,port):
        self.host=host
        self.port=port

    @staticmethod    def from_conf():        return MySQL(settings.HOST,settings.PORT)    # @classmethod #哪个类来调用,就将哪个类当做第一个参数传入
    # def from_conf(cls):
    #     return cls(settings.HOST,settings.PORT)

    def __str__(self):        return '就不告诉你'class Mariadb(MySQL):    def __str__(self):        return '<%s:%s>' %(self.host,self.port)


m=Mariadb.from_conf()print(m) #我们的意图是想触发Mariadb.__str__,但是结果触发了MySQL.__str__的执行,打印就不告诉你:

复制代码

View Code

三、 元类

  元类源自一句话,在python中一切皆对象,而对象都是由类实例化得到的,既然这样那样类也是对象,也是通过实例化得到的,内置类为type

调用关系是:

  调用元类——》自定义的类

  调用自定义的类——》自定义的对象

自定义类的三个关键组成部分

  1 类名

  2 类的基类们

  3 类的名称空间

class关键字的底层的工作原理

   1、先拿到类名(oldboyteacher)

  2、再拿到类的基类们:(object,)

  3、拿到类的名称空间(执行类体代码,将产生的名字放到类的名称空间也就是一个字典里,补充exec)

  4、调用元类实例化得到自定义的类:、oldboyTeacher=type('oldboyTeacher',(object){})

实现代码

 

复制代码

class_name="OldboyTeacher"class_bases=(object,)
class_dic={}
class_body='''
    school=self.shcool
    def  __init__(self,...)
       .............
    def score(......)         
    ...........
exec('x=1',{},class_dic)
 
print(class_dic)
OldboyTeacher_type(class_name,class_bases,class_dic)

复制代码

View Code

 

自定义元类来控制类的产生:

  但凡继承了type的类才能称之为自定义的元类,否则就是一个普通的类

  对象之所以可以调用是因为对象有一个函数__call__

  实例化发生的三件事:

    1、产生一个空对象

    2、执行__init__方法,完成对象初始化属性的操作

    3、返回初始化好的那个对象

自定义类来控制类的调用

原文出处:https://www.cnblogs.com/chenchuanjide/p/9512446.html

点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消