zoukankan      html  css  js  c++  java
  • chapter8.1、面向对象

    面向对象

    面向机器,机器指令,代表是汇编语言

    面向过程,规范化,分支,循环等,将要完成的事按步骤进行,问题规模小,可以步骤化,规模较大时也可以使用,也是一套方法论。代表是C语言

    抽象对象增多时,解决方法较复杂,不适合工业化

    面向对象,OOP,方法论,问题规模的增多,需要的人,物增加,从人,物的角度出发,考虑问题,C++,Java,Python

    编程范式,假如模式是武功的招式,那么范式就是武功的内功。

    认知世界,分析世界的方法论,将万事万物都抽象成类

    类class

    抽象的概念,是万事万物的抽象,是一类事物的共同特征,

    属性和方法

    对象 instance object

    对象是类的具象,是一个实体

    属性,对象状态的抽象,数据结构描述,保存

    操作,对象行为的抽象,操作名和操作方法

    类决定了该有的属性,不能保存具体的值

    每个对象的具体属性有差异,不能保存在类上,人类的每个实例的基本属性各有不同,所以属性保存在每个实例的人身上

    哲学

    一切皆对象

    对象是数据和操作的封装

    对象是独立的,但对象之间可以相互作用

    目前OOP是最接近人类认知的编程范式

    面向对象的3要素

    封装

      组装,将数据和操作组装到一起

      隐藏数据,对外暴露一些接口,开汽车不需要知道汽车怎么跑。暴露一些属性和方法,比如你知道车怎么开,可以选择颜色,但不用知道怎么操作发动机。

    继承

      多复用,继承,动物类有的,人类可以继承,父类有的子类就可以继承,继承来了就不用再写

      多继承少修改,OCP(Open-closed Principle),使用继承来改变,来体现个性,人类也吃,但吃法不同于其他的动物类,要继承下来修改,继承就是为了修改

    多态

      多种表现,灵活,动态绑定

    人类就是封装

    人类继承自动物类,孩子继承父母特征,分为单一继承,多继承

    多态,继承自动物类的人类、猫类的操作“吃”不同,动态绑定

    Python的类

    class ClassName

    关键字,必须使用class,其他命名不能使用关键字

    类名必须使用大驼峰命名,每个单词首字母大写

    类对象,用标识符和类对象绑定

    class MyClass:
        """example"""
        x = 'abc'
        def foo(self):
            return "My class"
    
    print(MyClass.x)
    
    print(MyClass.__doc__)

    类对象,类定义就会形成一个类对象

    类的属性,类中的变量和方法都是类的属性

    类变量,上例中x就是类的变量

    上例中foo是类的方法对象(method),和普通函数不同,要求至少有一个参数,第一个是self,指当前的实例本身

    a=MyClass(),实例化,只能生成一个具体的实例,每次都产生完全不同的对象,调用实例化和初始化方法

    实例化__new__,有这个方法,一般不用自己调,不用自己写

    Python实例化后,会自动调用__init__方法,也就是初始化(构造器,构造方法)方法,这个方法第一个参数必须留给self,,其他参数根据情况决定。

      只要实例化,一定会初始化,__init__可以不定义,没有会在实例化时隐式调用,从父类中一定会有调用,实例化就是生产,构造一个实例,初始化就是为了能让产品使用,出场配置__init__

    初始化可以配参数,__init__函数要求必须返回None,不能返回任何值

    self指代实例本身,后边可以传入类的对象的属性,可以加缺省值,也可以要求创建时加入

      self.name=name,为当前实例添加属性,每个单独的实例都有自己的属性,都在不同的内存位置

      实例调用方法时,对象调用类的方法,隐含着self参数,self指实例本身

    tom.showage()  对象调用类的方法,隐含着self参数

    Person.showage(tom)  类调用属性,参数是实例,必须加参数

    class Person:
        address = 'Beijing'##类的属性,对象在自己的字典里没有的话,就到类这里来找
        def __init__(self,name,age=3):##初始化函数,每次创建新的对象就会调用一次
            self._name = name##实例的属性,每个对象单独保存各自的属性
            self.age =age
        def showage(self):##类的属性,也是类的方法
            print ('{} is {}'.format(self.name,self.age))
    
    print(Person.__dict__)
    tom = Person('tom',12)##创建对象
    print(Person.__dict__)##调用类不会改变类的属性
    Person.age = 14##!!注意只是在类中增加了属性,不会影响__init__方法中的缺省值3
    jerry = Person('jerry')##这里的age使用了__init__中的缺省值
    
    print(jerry.__dict__)##对象的字典,不能用类查看
    jerry.age+=2##修改对象的属性
    print(Person.__dict__)##修改对象的属性,不影响类的属性
    print(jerry.__dict__)##对象的字典更新
    print(jerry.address)##从字典看出,jerry没有address的属性,就去类中取了Beijing
    tom.address = 'shanghai'##给类的对象tom增添属性
    print(tom.__dict__)##查看对象的字典,增添了新的属性

    以上print语句可以一条条打,观察变化

    实例变量,实例变量保存在实例对象上,是每个实例自己独有的变量,类变量是类的变量,是类的所有实例共享的属性和方法

    __name__   对象名,  __class__.__name__    返回对象的类的类名,类型是str

    __class__  对象的类型,对象.__class__  等同于  type(对象),大部分对象可以通过字典看内部变化

    __dict__  对象的属性和字典,对象.__class__.__dict__   查看对象的类的属性字典

    __qualname__  类的限定名

    对象都会动态的为自己增加属性__dict__,可以通过实例.__dict__.[变量名]和实例.变量名查看

      实例.变量名  : 访问实例的属性,优先访问自己的__dict__里找属性,没有就去访问类的字典,在没有就报AttributeError

      实例.__dict__.[变量名]  : 通过字典访问时,访问谁的字典就去谁的字典找,不会去别的字典找,找不到就报KeyError

      实例的同名变量会隐藏类变量,或者说覆盖这个类变量,就是在实例的字典里找到了,就不去类的字典里找了

      实例变量是每一个实例自己的变量,是自己独有的;类变量是类的变量,是类的所有实例共享的属性和方法

    全大写表示常量,一般开发遵守的原则,不是强制规定

    可以用装饰器传参来给类添加属性↓

    def add_name(name):
        def warpper(cl):
            cl.NAME = name
            return cl
        return warpper
        
    @add_name('tom')
    class Person:
        AGE = 20
    Person.__dict__

    类属性的定义,无第一参数也可以,将函数放在类下。类可以调用,但类的实例不可以调用 ,会提示少参数,禁止这样写

    类方法和静态方法

    类方法:加装饰器@classmethod

      类方法,必须传入至少一个参数,传入的第一个参数是类对象,就算用实例调用,传入的第一个参数也是类对象,习惯用cls表示参数,这是为了易读,不要改。可以通过cls直接操作类的属性。

    class Person:
        @classmethod
        def class_method(cls):
            print(cls)
    Person.class_method()##类调用,打印类对象
    Person().class_method()##实例调用,打印类对象

    静态方法:装饰器中间没有符号,@staticmethod,

      静态方法,不要形参,不会隐式传入其他形参,直接是本身的参数传入,只是表明方法的命名空间,方便组织管理,不论是类调用,还是实例调用,都不会隐式传入参数

    class Person:
        @staticmethod
        def static_method():
            print('1111')
    Person.static_method()##类调用,打印1111
    Person().static_method()##实例调用,打印1111

    类的属性只能通过类和实例访问

    类几乎可以调用所有的方法,但是对于普通的函数,需要加对象,实例作为第一参数

    实例几乎可以调用所有类中定义的方法,包括类方法和静态方法,但要找到实例的类。普通方法传入实例自身,括号中不用在写自己

    访问控制

    私有属性(private),私有成员,使用双下划线开头,通过方法来访问私有属性,可以在方法中加入控制,使用双下划线时,python解释器会将其改名,在字典中保存为  _类名__变量名  的名称,但还是可以通过该名称来修改,没有真正的隐藏,类内可修改,类外不可修改

    class Person:
        __x = 200##类的私有属性
        
        def __init__(self,name,age=19):
            self.name = name##对象的公有属性
            self.__age = age##对象的私有属性
            
        def getage(self):##通过getage访问私有属性
            return self.__age
        
        def growup(self,incr=1):
            if incr<50 and incr>0:##粗略的判断一下
                self.__age += incr
        
    tom = Person('tom')
    print(tom.getage())
    tom.growup()
    print(tom.getage())
    tom.__age = 1000##这里改变了对象的属性,相当于又在对象上加了一条属性,不会影响类
    print(tom.getage())
    tom.growup(incr=200)##没有通过判断,不会改变
    print(tom.getage())
    print(tom._Person__age)##其实藏在这里,还是可以修改得

    保护属性,保护成员,保护方法,使用一个下划线来控制,是开发者约定,解释器不做特殊处理

    class Person:
        _x = 200##类的保护属性
        
        def __init__(self,name,age=19):
            self.name = name##对象的公有属性
            self._age = age##对象的保护属性
    tom = Person('tom')
    print(tom._age)##并没有被修改,
    print(tom.__dict__)##解释器不会修改字典的内容

    共有成员,共有属性,共有方法,其他的方法都是

    开发者约定,使用_,__,仅是提醒或警告,除非必要,不要修改或者使用

    没有绝对安全的私有成员或者保护成员

    改名仅在类定义内实现,在外部使用下划线只会修改实例的字典内的属性

    补丁

    通过修改或者替换类的成员,使用者调用方式不变,但是类的功能可能已经改变了

    Monkey Patch

    在运行时对属性,方法,函数等进行动态的替换

    目的往往是通过替换、修改来增强功能,扩展原有代码的能力

    黑魔法,慎用

    属性装饰器@property#gatter  getter就是以后的属性名,获取值,有了getter至少是只读属性

    @age.setter设置值,与属性名同名,接受两个参数,第一个是self,第二个是将要赋的值,属性可写

    @age.deleter清除值,很少用,删除属性

    使用property装饰器的这三个方法同名,

    必须有gatter,才有setter

    类的实例消亡时,会调用__del__,(其他语言叫析构函数),将清理工作放在里边,会释放占用的资源,比如释放连接

    注意并不能真正的销毁对象,对象消亡由tc管,不是他管,他只是对象销毁时会调用它。

    使用del语句删除实例,引起计数减一,当引用计数为0时,会自动调用__del__

    由于python的垃圾回收机制,不能确定何时执行垃圾回收。

    除非明确·知道自己的目的,否则不要使用这个方法

    overload,方法重载,其他语言中静态语言会由传入的参数的类型和数目决定要调用的函数,函数同名

    python中没有重载,不能重载,不需要重载

    或者说python本身就实现了重载

    Encapsulation封装

    将数据和操作组织起来到类中,即属性和方法

    将数据隐藏起来,给使用者提供方法,使用者通过操作就可以获取或者修改数据,getter和setter

    通过访问控制,暴露适当的数据和操作提供给用户,将该隐藏的隐藏起来,例如保护成员和私有成员

  • 相关阅读:
    Mybatis批量插入
    easyui中datagrid常见功能
    mysql下载和安装方式
    Mybatis注意事项
    ol3对地图上某些特定的经纬度进行标注
    ol3开发离线地图
    java利用poi生成excel文件后下载本地
    log4j的基本使用方法
    tomcat8.5之后版本,远程无法登录管理页面
    但构造函数返回对象时
  • 原文地址:https://www.cnblogs.com/rprp789/p/9642929.html
Copyright © 2011-2022 走看看