栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Python

Python知识点总结

Python 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Python知识点总结

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

文章目录
  • 前言
  • 1,魔法函数
    • 分类
    • __repr__
    • __str__
    • __len__
  • 2,深入类和对象
    • 2.1,鸭子类型和多态
      • 概念
    • 抽象基类(abc模块)
    • python中的抽象基类不能实例化,
      • 为什么Python中有鸭子类型却还有抽象基类
      • 实现
      • 注意
  • 3,instance和type
    • is和==
  • 4,类变量和实例变量
  • 5,类属性和实例属性
    • 深度优先算法与广度优先算法与C3算法
      • C3算法:
  • 6,类方法和实例方法
  • 7,数据封装和私有属性
  • 8,自省
    • 反射
  • 9,super
  • 10, mixin的继承案例
    • 模式特点
    • 优点
  • 11,Python中的上下文管理器
    • 概念
    • 更简单的上下文管理器
  • 12,自定义序列类
    • 序列类型的特点
    • 序列类型的分类
    • 序列列类型的abc继承关系
    • 序列的+,+=和extends的区别
    • 切片
  • bisect
    • 什么时候我们不使用列表
    • 几个推导式
      • 列表推导式
      • 生成器表达式
      • 字典推导式
  • 13,Dict和Set
    • Mapping协议
  • 14,引用,垃圾回收
    • python中的变量
    • is 和 ==符合的区别
    • del和垃圾回收
    • 一个经典错误
  • 15,迭代器,生成器,装饰器
    • 迭代器
    • 生成器
      • 为什么要用生成器
    • 装饰器
  • 16,一些小技巧
  • 17,面向对象
    • 概念
    • 面向过程和面向对象
    • 面向对象三大特性
      • 封装
      • 继承
      • 多态
        • 为什么python中没有函数重载
  • 18,可变对象和不可变对象
    • 分类
    • 当我们修改对象的值时
    • 函数的参数传递
  • 19,深浅拷贝
    • 赋值操作
  • 20,*args 和 **kwargs
  • 21,面向切面编程AOP
    • AOP
  • 22,新式类和旧式类
  • 23,read,readline和readlines
  • 24,函数式编程
    • 命令式编程
    • 声明式编程
    • 函数式编程
  • 25,闭包
    • 为什么要使用闭包
    • 总结


前言

python进阶总结
Python基于协议编程

1,魔法函数 分类

数学运算和非数学运算

  1. 与对象毫无关联,可以写到任何位置
  2. 魔法函数定义后,我们不需要调用,python自己会进行调用
repr

开发模式下使用的,输入对象时使用

str

字符串格式

len

对内置类型使用时,直接读取内置类型内存储的长度
对于其他类型,使用__len__的方法进行变量

2,深入类和对象 2.1,鸭子类型和多态

当一只鸟走起来像鸭子,游泳起来像鸭子,叫起来也像鸭子,那么这只鸟就可以被称为鸭子

概念

与静态语言不同,我们使用鸭子类型,只需要关注它是否有我们需要的方法,是什么类型的对象都不重要

就比如列表中使用extend(),只要目标对象实现了__getitems__,我们即可添加到列表中

鸭子类型和魔法函数构成Python动态语言的基础

抽象基类(abc模块)
  1. python中的抽象基类不能实例化,
  2. 我们在设计抽象基类时,为其设置一些方法,当我们基础该基类时,我们要覆盖这些方法
为什么Python中有鸭子类型却还有抽象基类

我们需要强制某个子类必须实现某些方法:

  • 事先定义好约定,用户实现抽象类的子类,用户替换时非常方便·
实现
import abc 
class CacheBase(metaclass=abc.ABCMeta):
	@abc.abstractmethod
	def get(self,key):
		pass
	@abc.abstractmethod
	def set(self,key):
		pass
注意

不经常使用抽象基类

  1. 其最大用处是帮组我们理解python。
  2. 抽象基类在设计时,很容易抽象过度,而不容易取理解它。
3,instance和type

instance 内部会检测基础类
type 显示类型

is和==
  1. is判断是否为一个对象
  2. ==判断值是否相等
    尽量使用instance,type会有很多误差
class A:
    pass

class B(A):
    pass

isinstance(A(), A)  # returns True
type(A()) == A      # returns True
isinstance(B(), A)    # returns True
type(B()) == A        # returns False
4,类变量和实例变量
  1. 在类中定义的变量是类变量,属于类
  2. 实例化类时,初始化的值为实例变量
  3. 当我们查询实例中变量时,会优先在类中查询,再在类中查询
class A:
    aa = 1
    def __init__(self,x,y):
        self.x = x
        self.y = y

a = A(2,3)
A.aa = 11
print(A.aa)
print(a.aa)
a.aa = 12312
# 此刻会为a实例一个aa属性,跟A的属性无关了
print(A.aa)
print(a.aa)
5,类属性和实例属性
  1. 定义在类中的变量或是方法是类属性
  2. 实例化后实例中的属性和方法是实例属性
深度优先算法与广度优先算法与C3算法

深度:
先一条线不断进行查找
广度:
一层一层走

C3算法:
  1. 先将基础的所有节点的顺序合并为列表
  2. 重点在merge函数

公式

mro(E) = [E]+merge(mro(A)+mro(B))

merge 详细过程

  • 先判断一个数组的第一个元素是否是不在其他数组中,或是只在其他数组的第一位,那么我们就将其移到左边的列表中,将该元素删除
  • 继续向下判断直到右侧为空
6,类方法和实例方法

供类使用,假如说

  1. 静态方法就是一个普通的方法,与类和对象无关。
  2. 类方法属于类,被该类创建的各个对象所共享.
  3. 实例方法是属于类创建的某个对象的。

实例方法最大的特点在于,它至少也要包含一个self参数,用于绑定调用此方法的实例对象(Python会自动完成绑定)
类方法是会自动把类对象传递进去cls
静态方法无法调动任何的类属性和方法
在实际编程中,几乎不会用到类方法和静态方法,因为我们完全可以使用函数代替它们实现想要的功能,但在一些特殊的场景中(例如工厂模式中),使用类方法和静态方法也是很不错的选择。

7,数据封装和私有属性
  1. 变量名前,加_就可以称为私有属性。约定俗成,表示我不希望你直接调用
  2. __前置双下划线,私有化属性或方法,无法在外部直接访问(名字重整所以访问不到,只能是允许这个类本身进行访问了。连子类也不可以)

● foo:一种约定,Python内部的名字,用来区别其他用户自定义的命名,以防冲突.
● _foo:一种约定,用来指定变量私有.程序员用来指定私有变量的一种方式.
● __foo:这个有真正的意义:解析器用_classname__foo来代替这个名字,以区别和其他类相同的命名.

8,自省

自省就是面向对象的语言所写的程序在运行时,能够知道对象的类型。简单一句就是,运行时能够获知对象的类型。

列出对象的属性
dict
列出对象的所有属性
dir(user) 它返回传递给它的任何对象的属性名称经过排序的列表。
type() type() 函数有助于我们确定对象是字符串还是整数,或是其它类型的对象
hasattr() 对象拥有属性,并且 dir() 函数会返回这些属性的列表。
isinstance() isinstance() 函数测试对象,以确定它是否是某个特定类型或定制类的实例:

自省就是面向对象的语言所写的程序在运行时,所能知道对象的类型.简单一句就是运行时能够获得对象的类型.
● 自省是获取对象的能力
● 反射是操纵对象的能力

反射

先说正射:
正常情况下是导入模块,找到想要的类,再创建实例对象,接着再调用方法,这个方法太麻烦了,一个程序不停的运行,所需要的功能不断增多,不可能手动去一一导入,而且还需要程序去进行判断某个模块功能是否变动,这种情况必须只能是使用反射了。

● 反射就是以字符串的形式去导入模块,通过字符串的形式,去模块中寻找指定函数,并执行。利用字符串的形式去对象中操作成员,一种基于字符串的事件驱动
● 就是把一个对象类型拆解。可以使用字符串的形式去访问和修改对象。
● 应用场景:当我们动态输入一个模块名的就可以使用反射
● 通过hasattr,getattr,delattr,setattr等四 个函数来操作

反射的优点
● 能够用字符串的形式去操作对象,提高了程序的灵活性和扩展性。
● 降低耦合性
● 这种形式可以应对任何类的对象

9,super

super并不是调用父类的属性,而是调用mro中下一个类的构造函数

class A:
    def __init__(self):
        print("A")


class E:
    def __init__(self):
        print("E")


class B(A):
    def __init__(self):https://blog.csdn.net/lxqArticle/article/details/125270911
        print("B")
        super(B, self).__init__()
    
    
class C(E):
    def __init__(self):
        print("C")
        super(C, self).__init__()
        
class D(B,C):
    def __init__(self):
        print("D")
        super(D, self).__init__()

print(D.__mro__)
d = D()

结果
(, , , , , )
D
B
A

10, mixin的继承案例

混合模式
我们写一个mixin类,这个mixin中的每个类功能很单一

模式特点
  1. 功能单一
  2. 不是我们真正的类,只是一些接口而已
  3. 不和基类关联,可以和任何基类组合,基类可以不和mixin关联就能初始化成功
  4. 在mixin中不要使用super
  5. 不成文规范,mixin类以mixin结尾
优点

避免设计多层次的复杂的继承关系,混入类是为代码重用而生,使得代码结构简单清晰

11,Python中的上下文管理器 概念

始于try except finally

上下文管理器协议

  1. 我们定义一个类,它需要实现__enter__和__exit__俩个魔法函数
  2. 进入时,进入__enter__获取资源,出去时调用__exit__释放资源
  3. 利用with语句来使用该类

::: 协议与魔法函数挂钩

更简单的上下文管理器
import contextlib
'''
用装饰器转换为上下文管理器
enter内容放于yield之前
exit内容放于yield之后
'''
@contextlib.contextmanager
#它修饰的必须是生成器
def file_open(file_name):
    print("file open")
    yield 1
    print("file end ")

with file_open("bobby.txt") as f_opened:
    print("sadasdasd")
12,自定义序列类 序列类型的特点
  1. 序列类型可以基于for循环遍历
序列类型的分类
  1. 容器序列:list,tuple,deque
  2. 扁平序列:str,bytes,bytearray,array.array
  3. 可变序列:list,deque,bytearray,array
  4. 不可变: str,tuple,bytes
序列列类型的abc继承关系

跟容器类的抽象基类都放于abc中

  • len
  • getitem
  • setitem
  • delitem
  • iter
序列的+,+=和extends的区别
  • +是将俩个序列连接,是将一个值给其他数组
  • +=就地加, 不需要将内容给其他数组,而且后面可以相加任意序列类型
  • extend后面只要是iter就可以添加,没有返回值
    关于append和extend
  • append 直接会把值放到列表中,就是将列表当成一个整体放到该列表中
切片
alist[len(alist):] = [9]  #在尾部增加元素
alist[:0] = [1,2]  # 在列表头部插入元素
alist[3:3] = [4]  # 在列表中间指定位置插入元素
alist[3:] = [4,5,6] # 将三到最后位置变成四五六
alist[::3] = [0]*3
长度必须相等 

如何新建一个可以切片的对象

import numbers


class Group:
    def __init__(self, group_name, company_name, staffs):
        self.group_name = group_name
        self.company_name = company_name
        self.staffs = staffs

    def __reversed__(self):
        self.staffs.reverse()

    # 对序列进行切片操作
    def __getitem__(self, item):
        cls = type(self)
        if isinstance(item,slice):
            return cls(group_name=self.group_name,company_name=self.company_name,staffs=self.staffs)
        elif isinstance(item,numbers.Integral)
            return cls(group_name=self.group_name,company_name=self.company_name,staffs=[self.staffs[item]])
        return self.staffs[item]

    def __len__(self):
        return len(self.staffs)

    def __iter__(self):
        return iter(self.staffs)

    def __contains__(self, item):
        if item in self.staffs:
            return True
        else:
            return False


staffs = ["bobby1","immoc","bobby2"]
group = Group(company_name="imooc",group_name="user",staffs=staffs)

a = group[::2 ]
print(a)

a = group[0]
print(a)
bisect

用来处理已经排序的序列(维护已排序序列)
insort 插入并排序
bisect 查找并插入

bisect库是python中针对有序列表的一个模块,接收已排序列表作为参数。

一.函数介绍
————1 2 查询

  1. bisect.bisect(a,x)(默认等同于bisect.bisect_right())
    参数:
    a——已排序的列表
    x——要插入的元素
    返回值:
    返回x在a中会被顺序插入的位置。若a中已有一个或多个x,返回的位置在最后一个x之后。

  2. bisect.bisect_left(a,x)
    参数:
    a——已排序的列表
    x——要插入的元素
    返回值:
    返回x在a中会被顺序插入的位置。若a中已有一个或多个x,返回的位置在第一个x之前。

————3 4 5 插入

  1. bisect.insort(a,x)
    参数:
    a——已排序的列表
    x——要插入的元素
    返回值:
    None
    功能:
    在a中上述对应函数会返回的位置插入x。

  2. bisect.insort_right(a,x)
    参数:
    a——已排序的列表
    x——要插入的元素
    返回值:
    None

  3. bisect.insort_left(a,x)
    参数:
    a——已排序的列表
    x——要插入的元素

什么时候我们不使用列表
  1. array是C语言的数组
  2. array只能存放指定类型数据类型
  3. array的效率很高
  4. append()
几个推导式 列表推导式

通过一行代码生产列表

odd_list ==  [i for i in range(21) if i % 2 == 1 ]
  1. 逻辑复杂时,可以放函数
  2. 逻辑太复杂就可以不使用列表生成式
  3. 列表生成式性能高于列表操作
生成器表达式

如果列表推到式的中括号变成小括号

字典推导式
dict = {value:key for key,value in my_dict.items()}

集合推导式set

set = {key for key,value in my_dict.items()}
13,Dict和Set

先看collections中的abc
dict的子类:

Set和frzenset 无序不重复
Set 集合
frzenset 不可变集合

实现原理:

  1. dict的查找性能远远大于list
  2. 底层结构hash表
Mapping协议 14,引用,垃圾回收 python中的变量

变量就是对内存地址的引用,内存地址中存放数据

is 和 ==符合的区别

is是对地址的引用,==是对内容的判断

del和垃圾回收

python的垃圾回收机制是采用引用计数
del 一个对象时,实际是将该引用删除,同时将内存地址中的地址减一

一个经典错误

定义类时,尽量不要传递list,如果不传递参数时,会使用默认的类参数地址,可能下次实例化进行的修改会影响到其

15,迭代器,生成器,装饰器 迭代器

迭代,是重复反馈过程的活动,通常是为了逼近所需目标或结果。每对过程重复一次称为一次“迭代”,而每次迭代得到的结果会作为下一次迭代的初始值。在 Python 中,迭代是访问集合型数据的一种方式,对于字符串、列表、元组、集合和字典,都可以使用迭代来遍历其中的每个元素,而这些可以使用 for 循环遍历的对象也被称为可迭代对象。
可迭代对象:

可以利用迭代器逐个获取值

要实现的魔法函数

  1. next函数
  2. iter函数

迭代器实例

# 迭代器例子
class Fibs:
    def __init__(self):
        self.a = 0
        self.b = 1

    def __next__(self):
        self.a, self.b = self.b, self.b + self.a
        return self.a

    def __iter__(self):
        return self


fibs = Fibs()

for f in fibs:
    if f > 1000:
        print(f)
        break


# 对可迭代对象利用iter生成一个可迭代对象
it = iter([1, 2, 3])
print(next(it))
print(next(it))

#利用迭代器生成序列
class TestIterator:
    value = 0

    def __next__(self):
        self.value += 1
        if self.value > 10: raise StopIteration
        return self.value

    def __iter__(self):
        return self


ti = TestIterator()
print(list(ti))

生成器

生成器是迭代器的子集,在Python中一个函数可以用yiled替代return返回值,这样的话这个函数就变成了一个生成器对象
● yield
● yield from
加上可迭代对象,这样可以把可迭代对象变成生成器

为什么要用生成器
	考虑到如果我们使用其他可迭代对象处理庞大的数据时,当创建或者返回值时会申请用于存储整个可迭代对象的内存,显然这是非常浪费的,因为有的元素当前我们用不到,也不会去访问,但它却一直占用这内存。
	所以我们可以用到生成器,它不是一次性把所有的结果都返回,而是当我们每读取一次,它会返回一个结果,当我们不读取时,它就是一个生成器表达式,几乎不占用内存。

生成器的函数和迭代器

nested = [[1, 2], [3, 4], [5]]

# 存储每个值,利用next函数进行迭代
def flatten(nested):
    for sublist in nested:
        for element in sublist:
            yield element


print(list(flatten(nested)))

# 生成器推导式
g = ((i+2)**2 for i in range(2,27))
print(next(g))
print(next(g))
print(next(g))
print(next(g))


g = sum(i ** 2 for i in range(10))
print(g)



def flatten(nested):
    try:
        for sublist in nested:
            for element in flatten(sublist):
                yield element
    except TypeError:
        yield nested

a = list(flatten([[[1],2],3,4,[5,[6,7]],8]))
print(a)

# 存在问题 如果里面是字符串就会出现错误所以开始前先进行检测

# 修改代码为
def flatten(nested):
    try:
        try:
            nested + ''
        except TypeError:pass
        else:raise TypeError
        for sublist in nested:
            for element in flatten(sublist):
                yield element
    except TypeError:
        yield nested

b = list(flatten(['foo', ['bar',['baz']]]))
print(b)
装饰器

在不改变原函数调用以及内部代码的情况下,为期添加新的功能

def sleep(fun):
    def begin():
        fun()
        print("你看到我了")
    return begin
@sleep#装饰器
def eat():
    print("你吃饭了?")
eat()
16,一些小技巧

1,
import sys
这句语句告诉Python,我们想要使用这个模块。sys模块包含了与Python解释器和它的环境有关的函数
2,
range(start,end,step)
给定一个范围相当于for(i=0;i<=10;i++)

>>> range(0, -10, -1) # 负数
[0, -1, -2, -3, -4, -5, -6, -7, -8, -9]

3,
A[i], A[min_idx] = A[min_idx], A[i]
可以这样交换列表元素

17,面向对象 概念

不同的对象总是有着不同的特征,同一类的对象总是有着相似或者相同的特征

面向过程和面向对象
  1. 面向过程是一种以事件为中心的编程思想,编程的时候把解决问题的步骤分析出来,并且按步骤实现。
  2. 面向对象就像洗衣机,将一些功能封装给一个对象,我们直接调用该对象的方法即可实现,就像直接点击洗衣就可以实现洗衣
面向对象三大特性 封装

把客观事务封装成抽象的类,隐藏实现细节,仅仅对外公开一个可以调用的接口

继承

子类可以实现父类的所有功能,并修改其细节。子类会有父类的一些特点

多态

同一事物在不同形态下的表现形式不同

为什么python中没有函数重载
  1. 首先函数重载是为了解决可变参数类型和可变参数各数
  2. 对于可变参数类型:因为Python中的函数可以接收任意类型的参数
  3. 对于可变参数个数:Python中有缺省参数,将那些缺少的参数设置为缺省参数即可解决问题
  4. 所以python中不需要函数重载
18,可变对象和不可变对象

Python中可变对象和不可变的区别在于对象本身存放的数据是否可变

分类

在python的内置类型中:

  1. 可变对象:list,dict,set
  2. 不可变对象:tuple,string,int,float,bool
当我们修改对象的值时
  • 在对可变对象的内容进行修改后,地址是没有发生改变的
  • 而对不可变对象而言,改变对象的值后,会重新为其生成一个新的地址存放改变的数据
函数的参数传递
  • 可变对象作为函数参数传递时,会在函数中进行修改,可以影响到全局的变量值
  • 不可变对象,改变对象的值后,会生成一个内存地址来存储改变的值
19,深浅拷贝
  1. 深拷贝:将对象的所有内容拷贝一份,放于新的地址中
  2. 浅拷贝:将引用拷贝一份,地址不变
赋值操作
  • 赋值时将一个对象的地址赋给一个变量,让变量指向该地址
  • 修改不可变对象时,需要开辟新的内存空间,深拷贝一份对象
20,*args 和 **kwargs

*args和**kwargs只是为了方便并没有强制使用它们.

  1. *args 是当你不确定你要传递多少参数时使用。其可以传递任意数量的参数。
  2. **kwargs允许你使用事先没有先定义的参数名
  3. *args必须在**kwargs前面使用
21,面向切面编程AOP AOP
	简言之、这种在运行时,编译时,类和方法加载时,动态地将代码切入到类的指定方法、指定位置上的编程思想就是面向切面的编程。

我们管切入到指定类指定方法的代码片段称为切面,而切入到哪些类、哪些方法则叫切入点。有了AOP,我们就可以把几个类共有的代码,抽取到一个切片中,等到需要时再切入对象中去,从而改变其原有的行为。

优点是:这样的做法,对原有代码毫无入侵性

22,新式类和旧式类
	旧式类:没有继承object的类; 在早期的Python版本中,程序员在定义类的时候必须要指明类继承了object,类不会默认继承object,这些没有继承object的类就称为旧式类。

	新式类:继承object的类 ; 与上面相反,继承了object类的子类就叫做新式类,而在python3中,所有的类都会默认继承object类,所以python3中的类都是新式类。
23,read,readline和readlines
  • read 读取整个文件
  • readline 读取下一行,使用生成器方法
  • readlines 读取整个文件到一个迭代器以供我们遍历
24,函数式编程

函数式编程是一种编程范式

命令式编程
	命令式编程 是面向计算机硬件的抽象,有变量、赋值语句、表达式、控制语句等,可以理解为 命令式编程就是冯诺伊曼的指令序列。 它的主要思想是关注计算机执行的步骤,即一步一步告诉计算机先做什么再做什么。
声明式编程
	声明式编程 是以数据结构的形式来表达程序执行的逻辑。它的主要思想是告诉计算机应该做什么,但不指定具体要怎么做。SQL 语句就是最明显的一种声明式编程的例子
函数式编程
  • 而函数式编程和声明式编程是有所关联的,因为他们思想是一致的:即只关注做什么而不是怎么做。但函数式编程不仅仅局限于声明式编程。
  • 函数式编程是面向数学的抽象,将计算描述为一种表达式求值,其实,函数式程序就是一个表达式。
25,闭包

闭包使得局部变量在函数外访问成为可能

为什么要使用闭包
	闭包避免了使用全局变量,此外,闭包允许将函数与其所操作的某些数据(环境)关连起来。这一点与面向对象编程是非常类似的,在面对象编程中,对象允许我们将某些数据(对象的属性)与一个或者多个方法相关联。
总结
	闭包是一种函数,它保留了定义函数时存在的自由变量的绑定,因此,即便是函数返回后作用域不存在了,那些绑定仍然能够被使用。闭包可以很容易地实现一些简单的类的功能,同时基于此还有很多Python的魔法能够实现,比如装饰器。
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/971281.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号