python-进阶语法1

本文深入探讨Python的变量进阶,包括引用的概念、函数参数和返回值的传递,以及可变和不可变类型。接着介绍面向对象(OOP)的基础,涵盖类和对象、封装、继承、多态和单例设计模式。重点讲解了单例模式的实现,确保类在整个系统中只有一个实例。
摘要由CSDN通过智能技术生成

目录

 

一、变量进阶

变量的引用

       引用的概念

函数的参数和返回值的传递

可变和不可变类型

哈希

缺省参数

多值参数

元组和字典的拆包

函数的递归

 

二、面向对象(OOP)

         (一)概念

       类的概念——相当于一张图纸

       对象的概念——用图纸制造出来的物体

(二)面向对象基础语法

dir内置函数

定义类

创建对象

(三)封装

身份运算符

is 与 == 区别

私有属性和私有方法

(四)继承

        方法的重写

                  父类的私有属性和私有方法

         (五)多继承

         python中的MRO——方法搜索顺序

         新式类和旧式类

         (六)多态

                    术语

                    类是一个特殊的对象

                    静态方法

         (七)单例

                   单例设计模式

          __new__方法

         创建单例

初始化工作只执行一次


一、变量进阶

变量的引用

  • 变量 数据 都是保存在 内存 中的
  • 在 python 中 函数 参数传递 以及 返回值 都是靠 引用 传递的

引用的概念

  • 变量 和 数据是分开存储的
  • 数据保存在内存中的一个位置
  • 变量中保存着数据在内存的地址
  • 变量中记录数据的地址,就叫引用
  • 使用 id() 函数可以查看变量保存数据所在的内存地址
  • 注意:如果变量已经被定义,当给一个变量赋值的时候,实质是修改了数据的引用
    • 变量不再对之前的数据引用
    • 变量改为对新赋值的数据引用

 

函数的参数和返回值的传递

  • 函数的实参/返回值 都是靠引用来传递的
  • 传递的都是数据在内存中的地址(即引用),而不是数据本身

 

可变和不可变类型

  • 不可变类型,内存中的数据不允许被修改:
    • 数字类型 int,float,bool,complex,long(z,x)
    • 字符串 str
    • 元组 tuple
  • 可变类型,内存中的数据可以被修改
    • 列表 list
    • 字典 dict
  • 注意:
    • 字典的key只能使用不可变类型的数据
    • 可变类型的数据变化,是通过方法来实现的

 

哈希

  • 接收一个不可变类型的数据作为参数
  • 返回结果是一个整数
  • 哈希是一种算法,作用是提取数据的特征码
    • 相同的内容得到相同的结果
    • 不相同的内容得到不相同的结果
  • 在python中,设置字典的键值对是,会首先对key进行hash已决定如何在内存中保存字典的数据,方便后续对字典的操作:增、删、改、查
    • 键值对的key必须是不可变类型数据
    • 键值对的value可以是任意类型的数据

 

缺省参数

  • 定义函数时,可以给某个参数指定一个默认值,具有默认值的参数就叫做缺省参数
  • 调用函数时,如果没有传入缺省参数的值,则在函数内部使用定义函数时指定的参数默认值
  • 使用最常见的值作为默认值
  • 如果一个参数的值不能确定,则不应该设置默认值,具体的数值在调用函数时,由外界传递
  • 注意:
  1. 缺省参数的定义位置必须保证在参数列表末尾
  2. 调用带有多个缺省参数的函数,需要指定参数名

 

多值参数

  • 有时候可能需要一个函数能够处理的参数个数是不确定的,这个时候就可以使用多值参数
  • 参数名前增加一个*可以接收元组,一般使用*args——存放元组参数
  • 参数名前增加两个*可以接收字典,一般使用**kwargs——存放字典参数

 

元组和字典的拆包

  • 在调用带有多值参数的函数时,希望将一个元组变量,直接传递

 

函数的递归

  • 在函数内部自己调用自己,函数内部的代码是相同的,只是针对参数不同,处理的结果不同
  • 必须要有递归的出口,当参数满足某个条件时,不再执行函数,如果没有出口会出现死循环

 

二、面向对象(OOP)

  • 相比较函数,面向对象是更大的封装,根据职责在一个对象中封装多个方法
  • 使用与复杂项目开发,提供固定套路

 

(一)概念

类的概念——相当于一张图纸

  • 类是对一群具有相同特征或者行为的事物的一个统称,是抽象不能直接使用的
  • 特征被称为属性,行为被称为方法
  • 设计类:
    • 类名:满足大驼峰命名法
    • 属性:这类事物具有什么样的特征
    • 方法:这类事物具有什么样的行为

 

对象的概念——用图纸制造出来的物体

  • 对象是由类创建出来的一个具体存在,可以直接使用
  • 有哪个类创建的对象,就拥有哪个类中定义的属性和方法

 

 

(二)面向对象基础语法

dir内置函数

  • 可查看对象内的所有属性及方法 
  • __方法名__格式的方法是python提供的内置方法/属性

定义类

class 类名:

    def 方法1(self,参数列表):
        pass

    def 方法2(self,参数列表):
        pass
    
  • 注意:第一个参数必须是self,哪一个对象调用的方法,self就是哪一个对象的引用(对象的内存地址)
  • 在方法内部,可以通过self访问对象的属性,和调用其他的对象方法

 

创建对象

对象变量 = 类名()

一个类可以创建多个对象

 

注意:在日常开发中,不推荐在类的外部给对象增加属性,如果在运行时没有找到属性,程序会报错,对象应该包含有哪些属性,应该封装在类的内部

 

(三)封装

  • 是面向对象编程的一大特点
  • 将属性和方法封装到一个抽象的类中
  • 外界使用类创建对象,然后让对象调用方法
  • 对象方法的细节都被封装在类的内部
  • 在对象的方法中,是可以直接访问类的属性
  • 同一个类创建的多个对象之间,属性互不干扰
  • 一个对象的属性可以是另外一个类创建的对象

 

身份运算符

身份运算符用于比较两个对象的内存地址是否一致——是否是对同一个对象的引用

针对None比较时,建议使用is判断

运算符描述实例
isis是判断两个标识符是不是引用同一个对象x is y 类似 id(x) == id(y)
is not is not 是判断两个标识符是不是引用不同对象x is not y, 类似id(a) != id(b)

 

 

 

 

is 与 == 区别

is用于判断两个变量引用对象是否同一个

== 用于判断引用变量的是否相等

 

私有属性和私有方法

  • 对象的某些属性或方法可能只希望在对象的内部被使用,而不希望在外部被访问到
  • 私有属性就是对象不希望公开的属性
  • 私有方法就是对象不希望公开的方法

定义方式

  • 在定义属性或方法时,在属性名或者方法名前增加两个下划线,定义的就是私有属性或方法

 

(四)继承

  • 继承实现代码的重用,相同的代码不需要重复的编写
  • 子类拥有父类的所有方法和属性

实例语法

class 类名(父类名):
    pass
  • 子类继承父类,可以直接使用父类中已经封装好的方法,不需要再次开发
  • 子类中应该根据职责,封装子类特有的属性和方法 
  • 专业术语
    • 子类 == 派生类   父类 == 派生类  继承 == 派生
  • 继承具有传递性,子类可以继承爷爷类

方法的重写

 

 两种情况:

1)覆盖父类的方法

父类的方法实现和子类的方法实现完全不同,就可以使用覆盖的方式,在子类中重新填写父类的方法实现,重写后,只会调用子类中重写的方法,而不会调用父类封装的方法

2)对父类方法进行扩展

子类的方法实现中包含父类的方法实现,父类原本封装的方法实现是子类方法的一部分(即子类中还需要用到父类的方法,而又想再定义更多的方法)

使用方法是 super().父类方法 来调用父类方法的执行

 

 

  • 当父类的方法实现不能满足子类需求是,可以对方法进行重写

 

父类的私有属性和私有方法

  • 子类对象不能再自己的方法内部,直接访问父类的私有属性或私有方法
  • 子类对象可以通过父类的公有方法间接访问到私有属性或私有方法

 

(五)多继承

  • 子类可以具有多个父类,并且拥有所有父类的属性和方法
  • 语法实例:
class 子类名(父类1, 父类2, ...)

注意:如果不同的父类中存在同名的方法,子类对象调用方法时,会调用哪一个父类的方法呢?

开发时,应该尽量避免这种容易产生混淆的情况,如果父类之间存在同名的属性或者方法,应该尽量避免使用多继承

 

python中的MRO——方法搜索顺序

  • 提供一个内置属性__mro__可以看到方法搜索顺序
  • MRO主要用于多继承时判断方法、属性的调用路径

新式类和旧式类

  • object是python为所有对象提供的基类,提供有一些内置的属性和方法,可以使用dir函数查看
  • 新式类:以object为基类的类,推荐使用
  • 旧式类:不以object为基类的类,不推荐使用
  • 在python 3.x中定义类时,如果不指定父类,就会默认使用object 为基类,所以都是新式类
  • 在python 2.x中定义类时,如果不指定父类,就不会以object为基类,所以是旧式类
  • 为保证同时在python 2.x 和 3.x中运行,定义类时,统一继承自object

 

(六)多态

不同的子类调用相同的父类时,产生不同的执行结果

  • 多态可以增加代码的灵活性
  • 以继承和重写父类方法为前提
  • 是调用方法的技巧,不会影响类的内部设计

 

术语

  1. 创建出来的对象叫做类的实例
  2. 创建对象的动作叫做实例化
  3. 对象的属性叫做实例属性
  4. 对象调用的方法叫做实例方法

 

类是一个特殊的对象

  • 在程序运行时,类同样会被加载到内存中
  • 类是一个特殊的对象——类对象
  • 程序运行时,类对象在内存中只有一份,使用一个类可以创建很多个对象实例
  • 除了封装实例的属性和方法,类对象还可以拥有自己的属性和方法——类属性、类方法
  • 类属性:
    • 就是给类对象中定义的属性
    • 通常用来记录与这个类相关的特征(模板)
    • 类属性不会用于记录具体对象的特征(实例)
  • 属性的获取机制——向上查找机制
    • 1.类名.类属性
    • 2.对象.类属性(不推荐)
    • 注意:使用对象名.类属性 = 值 赋值语句,只会给对象添加一个属性,而不会影响到类属性的值
  • 类方法:
    • 定义类方法:需要用修饰器@classmethod来标识,告诉解释器这是一个类方法,第一个参数应该是cls,与self类似
@classmethod
def 类方法名(cls):
    pass

 

静态方法

如果需要封装一个方法,即不需要访问实例属性或者调用实例方法,也不需要访问类属性或者调用类方法,就可以封装成静态方法

@staticmethod
def 静态方法名():

    pass

通过 类名. 的方法直接调用静态方法,不需要创建对象

 

类属性和实例属性的区别:类属性就相当于全局属性,比如记录该类创建了多少个对象;实例属性就相当于局部属性,每个对象的属性都不一样,互不影响(实例属性下初始化方法中定义)

 

五大概念:类属性、类方法、实例属性、实例方法、静态方法

 

(七)单例

单例设计模式

  • 让类创建的对象,在系统中只有唯一一个实例
  • 每一次执行 类名()返回的对象,内存地址是相同的

__new__方法

  • 功能
    • 在内存中为对象分配空间
    • 返回对象的引用
  • 重写__new__方法一定要return super().__new__(cls)
  • 否则解析器得不到分配了空间的对象引用,就不会调用对象的初始化方法
  • __new__是一个静态方法,在调用时需要主动村传递cls参数

 

创建单例

  1. 定义一个类属性,初始值是None,用于记录单例对象的引用
  2. 重写__new__方法
  3. 如果类属性is None ,调用父类方法分配空间,并在类属性中记录结果
  4. 返回类属性中记录的对象引用

初始化工作只执行一次

  1. 定义一个类属性 init_flag 标记是否执行过初始化动作,初始值为False
  2. 在__init__方法中,判断init_flag, 如果为false就执行初始化动作
  3. 然后将init_flag设置为True
  4. 这样,再次自动调用 __init__ 方法时,初始化动作就不会被再次执行了

 

 

 

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值