python-知识点(一)

运行机制

.py

1、python文件后缀名

.pyc

1、编译后的python文件名后缀

pip

pip是python安装工具管理包

mac安装pip

2、pip安装:先下载https://bootstrap.pypa.io/get-pip.py,然后直接sudo python get-pip.py
3、查看安装包 pip list
pip freeze

win10安装pip

1、安装:
cmd
python -m ensurepip
python -m pip install --upgrade pip
在python目录scripts下就有pip了
2、配置:
系统环境变量path下新建:
C:\Users\yangxiuxiu\AppData\Local\Programs\Python\Python37\Scripts
3、升级Pip版本:pip install --upgrade pip

python解释器

1、常见python解释器:Cpython(官方推荐使用的解释器);Ipython是基于CPython的交互解释器;Jython是运行在java平台的python解释器,可以直接把python代码编辑成java字节码运行。
2、python解释器-词法分析、语法分析、编译(用到虚拟机)、执行

解释性语言

1、解释性语言 就是无需编译源码为可执行文件,直接使用源码就可以运行的语言。
源码–>通过解释器->编译执行
解释型语言用到的是解释器+虚拟机
2、编译型语言:先编译后运行,一次编译永久执行。
源码–>通过编译器–>生成汇编代码–>通过汇编器–>生成机器语言(机器指令+操作数)–>通过链接器 -->将机器语言、其他目标代码、库文件组装成可机器可执行程序–>机器执行
编译型语言用到的是编译器+链接器
常见的编译语言:C,c++

环境搭建

虚拟环境

1、虚拟环境是真实python环境的复制版本
2、安装虚拟环境命令:
安装虚拟环境:sudo pip3 install virtualenv
安装虚拟环境扩展包:sudo pip3 install virtualenvwrapper
安装完虚拟环境后,如果提示找不到mkvirtualenv命令,须配置环境变量:
a.在~(家目录)下创建目录用来存放虚拟环境
mkdir .virtualenvs
b.打开~/.bashrc文件,并添加如下:
export WORKON_HOME=$HOME/.virtualenvs
source /usr/local/bin/virtualenvwrapper.sh
c.运行
source ~/.bashrc
3、创建虚拟环境
mkvirtualenv -p python3 虚拟环境名称
4、linux上所有的虚拟环境默认都位于/home/下的隐藏目录.virtualenvs下
5、查看所有虚拟环境的命令:workon
6、命令窗口使用虚拟环境的命令:workon 虚拟环境名称
7、Pycharm中设置虚拟环境
a.获取虚拟环境路径
$ workon 虚拟环境名称
$which python
b.pycharm中选择虚拟环境
Pycharm—>Preferences—>Project:Demo—>Project Interpreter—>选择local
8、退出虚拟环境命令:deactivate
9、删除虚拟环境的命令:先退出后删除
先退出:deactivate
再删除:rmvirtualenv 虚拟环境名
10、在虚拟环境中安装工具包:
进入虚拟环境: workon 虚拟环境名称
安装包:pip3 install 包名称
查看虚拟环境中安装的包 :pip3 freeze 或者 pip3 list

管理虚拟环境

变量

1、命名规则:小写字母,单词之间用_分割 ,this_is_a_var
2、变量保存在内存中,使用前必须被赋值
3、变量中存放的是被引用对象的内存地址值,使用id(变量)可查看变量中保存的内存地址值
4、python引用变量的顺序: 当前作用域局部变量->外层作用域变量->当前模块中的全局变量->python内置变量
5、交换两个变量的值
a,b = b,a 右边其实是元组,省略了括号
6、变量类型:私有变量、成员变量(实例变量、对象变量)、类变量、局部变量、全局变量、内置变量

动态类型

1、在定义变量或者参数时不需要指定数据类型,变量或者参数的数据类型在代码运行的过程自行决定。
相应的静态类型语言的变量和参数的数据类型在运行前就已经确定了。

引用

1、变量中记录数据的地址的操作叫作引用

局部变量

1、在函数内部或者方法内部定义的变量为局部变量
2、局部变量在函数或者方法开始执行时被创建
3、局部变量在函数或者方法执行结束时被收回
4、局部变量只能在函数或者方法内部使用

全局变量

1、.py文件中定义变量时 不缩进的变量是全局变量
2、.py文件被导入到其他模块时,其它模块可访问全局变量
3、在函数内部不能修改全局变量的引用,使用赋值语句会将变量指向新的数据

a = [1,2,3]
print(id(a))
def s():
    a=5
    print(id(a))
s()
print(id(a))

4、在函数内部可以修改可变类型全局变量的值

a = [1,2,3]
print(id(a))
def s():
    a.append(122)
    print(id(a))
s()
print(id(a))

5、如想在函数内部修改全局变量的引用,需在函数内部用global声明全局变量

a = [1,2,3]
print(id(a))
def s():
    global a
    a = [122]
    print(id(a))
s()
print(id(a))

6、命名:大写字母,单词之间用_分割
NUMBER
COLOR_WRITE
7、如果局部变量的名字和全局变量的名字相同,pycharm会在局部变量名下面显示灰色的虚线

global

1、在函数内部声明全局变量,常用于修改全局变量的引用
2、global是python关键字

nonlocal

要明确 nonlocal 关键字是定义在闭包里面的,用来在函数或其他作用域中使用外层(非全局)变量。使用 nonlocal 时,就声明了该变量不只在嵌套函数里面才有效, 而是在整个大函数里面都有效

def line():
    saw = 1
    def create_y():
        nonlocal saw
        print(saw)
        saw =2
        print(saw)

    return create_y

m = line()
m()

内置属性

1、内置属性的格式 方法名
2、查看所有内置属性

import builtins
print(dir(builtins))

3、mro 可查看
4、file //查看当前导入模块的完整路径
5、name 如果执行当前模块,则__name__==“main”,如果当前模块被其他模块调用执行,则__name__==模块名
6、doc 可以查看文件注释信息

数据

1、数据保存在内存中
2、python有多种数据类型,包括数字、字符串、字典、列表、元组

数据类型

1、python数据类型分为可变数据类型和不可变数据类型

序列

1、序列是Python中最基本的数据结构
2、序列,指的是一块可存放多个值的连续内存空间,这些值按一定顺序排列,可通过每个值所在位置的编号(称为索引)访问它们。
3、python中序列的最后一个元素标记为-1,倒数第二个标记为-2
4、在 Python 中,序列类型包括字符串、列表、元组、集合和字典

可变数据类型

1、python中的可变类型和不可变类型指的是内存地址与其对应的value值之间的关系是否可以改变,二者间的关系不可改变的即为不可变类型。
2、可变数据类型,允许变量的值发生变化。即如果对变量进行append等操作后,只是改变了变量的值,而不会新建一个对象,变量引用的对象的地址也不会变化,不过对于相同的值的不同对象在内存中会存在不同的对象。

列表

1.列表是可变数据类型,可通过列表的方法改变元素的值
2.可保存任何数据类型,数据项不需要具有相同的类型
3.创建 a=[]
4.访问、索引、分片
5.更改 a[1]=‘sds’
6.清空列表 a[:]=[]
7.批量插入a[1:1]=[’21’,’s’,’dsa’]
8.删除元素 del a[1] del list:不加索引,直接回收对象
9.其他:
list.appent(’21’) // 参数当一个字符串加入列表中
list.extend([‘a’,’d’,’w’]) //参数当一个列表加到list中
list.insert(2,’sadsad’) //在第三个位置插入字符串
list.count(‘a’) //a出现的次数
len(list) //统计列表的长度
list.index(‘a’) //a在list中出现的位置
m = list.pop() //弹出最后一个元素
list.remove(‘a’) //删除列表中的第一个元素,元素不存在则报错
list.clear() //清空列表
del list[1] //将变量从列表中删除
list.reverse() //list反转
list.sort() //原地升序排列
list.sort(reverse=True) //原地倒序排序
list.sort(key=len)//key等于自定义函数、内部函数
sorted(list)//内置排序函数
sorted(list,key=len,reverse=True)
list.copy()

1、python中的列表采用了顺序表的实现方式,它是一种分离结构的、元素外置的、元素个数可变的、线性、有序表。
2、基于下标更新或者访问元素时,时间复杂度是O(1)
3、列表扩展元素时,表对象不变(使用id()查看)
3、list内置操作时间复杂度

操作操作说明时间复杂度原因
index(value)查找list某个元素的索引O(1)
a = index(value)索引赋值O(1)
append(value)队尾添加O(1)
pop()队尾删除O(1)
pop(index)根据索引删除某个元素O(n)
insert(index, value)根据索引插入某个元素O(n)
iterration列表迭代O(n)
search(in)列表搜索(其实就是in关键字)O(n)需要遍历列表元素
slice [x:y]切片O(k)获取x, y为O(1), 获取x,y 中间的值为O(k)
del slice [x:y]删除切片,删除切片后数据需要重新移动/合并O(n)
reverse列表反转O(n)
sort排序O(nlogn)
del删除列表O(n)因为list的元素外置,删除list元素时要同时删除外置元素

python中的元组
1、python中的元组采用了顺序表的实现方式,
2、元组是不可变类型,即不变的顺序表,不支持改变其内部表的任何操作

字典

1、可变数据类型,可以通过字典的方法修改字典的值
2、字典的key值只能是不可变变量类型
Python中内置一个哈希函数,哈希是一种算法,其作用是提取数据的特征码,类似于人的指纹,独一无二。
Python设置字典的键值对时,会先对key进行hash已决定如何在内存中保存字典的数据,方便对字典进行增删改查
3、创建字典的方式:
dict() ==>{}
dict(zip([‘one’,’second’],[1,2])) ==> {‘one’:1,’second’:2}
dict({‘one’:1},**{second:2}) ==> {‘one’:1,’second’:2}
dict(a=‘a’, b=‘b’) ==> {‘a’:’a’, ‘b’:’b’}
dict([(‘one’,1),(‘second’,2)]) ==> {‘one’:1, ’second‘:2}

不可变数据类型

1、不可变数据类型,不允许变量的值发生变化。如果改变了变量的值,相当于是新建了一个对象,而对于有相同的值的对象,在内存中则只有一个对象,内部会有一个引用计数器来记录有多少个变量引用这个对象。
2、修改不可变会报错,抛出TypeErrory异常

字符串

1、表示:‘’ “” “”” ””” ‘’’ ’’’
2、转换:
str()
repr()[原始转换]
3、格式化:
%s %d %f %x %r
4、format使用

a={name}是谁?”.format(name=“贾金品”)

5、常见属性和操作:
(1)len() 只对序列元素求值
(2)分片索引 步长[ ::2] 拷贝[:]
(3)字符串连接
1)‘aasd’+’dsd’
2) list=[‘ds’,’dq’,’cxzc’]
’&’.join(list)
3) ‘a’*10
(4)替换
str.replace(‘a’,’b’,10) //字符串中的a替换成b ,替换10次
(5)比较 cmp(‘q’,’q’)
(6)查找
‘aaaabbbbbccccc’.find(‘c’,2,10)// 从第2个位置到第10个位置 返回c首次出现index,反之返回-1
‘asd’.index(0) //返回第0个位置的字符 a
(7)切割
Str.split(‘&’,10) // 将字符串以&切割,并切割10次,返回list
(8)大小写
Str.upper()//大写
str.lower()//小写
Str.capitalize()//首字母大写
Str.istitle()
Str.isupper()//是否全部大写
Str.islower//是否全部小写
(9)字符串去空格
Str.strip()//去除左右空格
str.lstrip()//去除左边空格
Str.rstrip()//去除右边空格
(10)其它
Str.isalnum() // 是否全是字母和数字
Str.isalpha() //是否全是字母
Str.isdigit() //是否全是数字
str.isspace() //是否全是空白字符
Str.count(‘a’) //统计字符在字符串中出现的次数
Str.startswith(‘qw’)//判断以qw开始
str.endswith(‘qw’) //判断以qw结束

Int

Bool
Float
long
Complex

元组

1、写法:a=(1,2) 或者a=1,2
2、访问元组:
a[0] = 1 a[1:2]
3、元组的值不可修改,不可变数据类型
4、删除元组删除的是变量定义,
5、元组之间也可拼接生成新的元组
a=(1,2) b=(2,4)
c= a+b=(1,2,2,4)
6、元组操作
a.index(‘b’) ‘b’在元组a中出现的第一次位置

集合

切片

1、sname[start : end : step]
2、切片操作是访问序列中元素的另一种方法,它可以访问一定范围内的元素,通过切片操作,可以生成一个新的序列。

有序集合

无序集合
len()
del()
max()
min()
cmp()(python3取消了这个函数)

正则表达式

命令
del
tree

关键字

1、查看python关键字:

import  keyword
print(keyword.kwlist)

[‘False’, ‘None’, ‘True’, ‘and’, ‘as’, ‘assert’, ‘async’, ‘await’, ‘break’, ‘class’, ‘continue’, ‘def’, ‘del’, ‘elif’, ‘else’, ‘except’, ‘finally’, ‘for’, ‘from’, ‘global’, ‘if’, ‘import’, ‘in’, ‘is’, ‘lambda’, ‘nonlocal’, ‘not’, ‘or’, ‘pass’, ‘raise’, ‘return’, ‘try’, ‘while’, ‘with’, ‘yield’]
2、pass 占位符,表示空语句,保证程序代码未完成时,代码不会因为结构错误而报错

算术运算符

+、 -、 *、 /、 %、**、//
/: 除、结果为浮点数
%: 模,取余数
**: 幂次方
//: 地板除,结果为整数,向下取整
*跟在字符串、元组、列表后面,可重复
+跟在字符串、元组、列表后面,可合并

比较运算符

1、> 、< 、==、 !=、 <=、 >=
2、比较运算符可用于字符串、元组、列表的比较

赋值运算

= 、+=、 -=、 *=、 /=、 %=、 **=、 //=
+=: 是先加后赋值的操作, 但是+=用在list上就不是先加后赋值的操作,而是调用list的extend方法,不会改变变量引用

逻辑运算符

and 、or 、not

成员运算符

in、not in
常用于序列: 字符串、元组、列表

身份运算符 is

1、用于判断两个对象的内存地址是否一致,是否是对同一个对象的引用
2、python中针对None比较,建议使用is判断。

三目运算符

条件为真时的结果 if 判段的条件 else 条件为假时的结果

分支控制语句

if 条件1pass
elif 条件2pass
else:
	pass

循环控制语句

1、while

while 条件表达式:
		print ‘aaaa’
		if 条件:
			退出循环
			break

2、for

for a in list:
	print a
else:
	for 中没有break ,或者for都遍历完可执行else中的语句,否则不执行

函数

1、在.py文件中以def 开头定义,不在类中定义的是函数;类中定义的是方法
2、函数封装独立的功能,可直接调用
3、函数有内置函数、匿名函数等
4、函数可以利用元组返回多个值。如果函数返回的类型是元组,可省略小括号
5、当函数返回多个值时,可以使用元组下标方式获取值,也可以定义多个变量来接受函数返回值

def demo():
	a =1
	b=2
	return a,b
gl_a,gl_b = demo()
print(gl_a)
print(gl_b)

高阶函数

1、高阶函数就是在一个函数里,参数可以传递函数,或者一个函数的返回值为另外一个函数

def add(x,y,f):
    return f(x)+f(y)
print add(2,3, lambda x:x**2)

2、python内置高阶函数
(1)sorted函数,按指定元素进行排序

obj = [[1,2], [5,6], [2,8], [8,3], [3,10]]
func = lambda x: x[1]
new_list = sorted(obj, key=func, reverse=False)
print(new_list)  # [[1, 2], [8, 3], [5, 6], [2, 8], [3, 10]]

(2)filter函数

obj = filter(lambda x: x > 0, [-20, -10, -1, 0, 1, 10, 20])
print(obj) # <filter object at 0x004C9EB0>

for i in obj:
    print(i) # 1 10 20

(3)map函数

#函数映射
obj = map(lambda x: x+1, [0,6,10])
print(obj) # <map object at 0x0026DDB0>
for i in obj:
    print(i) # 1 7 11

#封包传递
obj2 = map(lambda x, y: x+y, *([0, 5, 8], [2, 2, 2]))
print(obj2)  # <map object at 0x0076FE90>
for i in obj2:
    print(i)  # 2 7 10

内置函数

1、查看所有内置函数或者内置变量

import builtins
print(dir(builtins))

2、dir() 查看对象的属性和方法
3、eval(“”) 执行字符串参数编译后的代码
4、abs(x) 返回一个数的绝对值
5、bin(x)将一个整数转变为一个前缀为“0b”的二进制字符串
6、divmod(a, b) 它将两个(非复数)数字作为实参,并在执行整数除法时返回一对商和余数。
7、hash(object) 返回该对象的哈希值(如果它有的话)。哈希值是整数。
8、id(object)返回对象的“标识值”,可返回对象的内存地址
9、isinstance(object, classinfo)
10、len(s):计算容器中元素的个数
11、max(iterable, *[, key, default])
max(arg1, arg2, *args[, key])
返回可迭代对象中最大的元素,或者返回两个及以上实参中最大的
12、min(iterable, *[, key, default])
min(arg1, arg2, *args[, key])
返回可迭代对象中最小的元素,或者返回两个及以上实参中最小的。
13、next(iterator[, default])
通过调用 iterator 的 next() 方法获取下一个元素。如果迭代器耗尽,则返回给定的 default,如果没有默认值则触发 StopIteration。
14、print(“”,end=“\d”)

匿名函数

1、语法:lambda 参数列表 : 表达式
2、所谓匿名函数,就是没有名字的函数。
3、匿名函数冒号后面的表达式有且只能有一个
4、匿名函数自带return,而return的结果就是表达式的计算后的结果。

缩进

1、.py文件中的缩进格式必须相同,否则会报错

函数嵌套调用

递归

1、在函数内部自己调用自己
2、递归出口:当参数满足某个条件时,函数不在执行

返回值

参数

1、

def user(username):   //username 是形参,不占用内存地址
    print("Hello World,"+username) 

user(‘asd’) //asd 是实参,占用内存地址

实参

1、实参占用内存空间
2、函数调用时,本质上传递的是实参保存数据的引用,而不是实参保存的数据;实参通过引用给形参传值

形参

1、形参不占用内存空间

位置实参

user(‘asd’) // 将实参和形参 按照位置对应起来

关键字实参

user(username = ‘asd’) 通过关键字=值的方式,将实参与形参关联映射,不需要考录形参的顺序

缺省参数(默认值)

1、给形参设置默认值,调用函数或者方法是可以不再给形参传值
2、带有默认值的参数必须在没有默认值参数的后面定义

多值参数

1、有时候需要一个函数可以处理的参数个数是不确定的,这时可使用多值参数
2、Python有两种多值参数
参数名前一个* ,可接收元组
参数名前两个**,可接受字典
3、多值参数命名习惯:*args,**kwargs
4、调用函数时,传参写法

def demo(*num,**mi):
	print(sum(num))
	print(mi)
s = (1,2,3)
m  = {"s":3}
demo(*s)
demo(**m)
demo(1,2,3,4,num=3,go=4)

拆包

1、拆包是指将一个结构中的数据拆分为多个单独变量中
2、拆包可简化参数的传递
3、拆包一种是以变量的方式来接收

a,b,c =("s","m","n")

4、拆包的另一种方式 用*号

a = [1,2,3]
print(*a)

单行注释

“” 或者’’

多行注释

“”“多行注释,可换行”“”

TODO 注释

用于标记未完成代码

文档注释

模块

1、一个.py文件就是一个模块
2、模块

import

1、_x是私有化变量或者私有化方法,import不可导入,但是类对象或者子类可以使用;__xx:类中的私有变量,类对象或者子类不可使用;
2、import 能防止模块重复导入
3、重新导入模块

from importlib import reload
import sys
reload(sys)

4、import搜索路径
a.在当前目录下搜索该模块
b.在环境变量 PYTHONPATH 中指定的路径列表中依次搜索,sys.path
c.在 Python 安装路径的 lib 库中搜索

traceback

1、打印堆栈信息

import trackback
trackback.print_exc()

1、类的三要素:类名、属性、方法

class  A(object):  //类对象
	aa  =  1 //类变量(类属性)
	__bb  =  "sd"  //私有变量(类属性)
	def  __init__(self,name):  //构造方法
		self.name  =  name  //实例变量
		A.aa += 1 
		print(aa)

	def  __pp(self):  //私有方法
		print  AA  

	@classmethod  //python装饰器
	def  pri(cls):    //类方法
		print  cls.aa
		print  cls.bb

	@staticmethod
	def  ll():  //静态方法
		print  A.aa

a = A()   	//实例对象
A.aa // 访问类属性
A.pri() //访问类方法

2、类名命名规则:单词首字母大写,单词和单词之间没有下划线
AdStats
ConfigUtil
3、类是一个对某一类具有共同特点的事物的抽象,只是概念,不代表一个具体的个体
4、类也是对象,当定义类、全局变量、函数时,其实就是创建了一个对象,然后globals获取的这个字典中添加对象名,并让这个对象名指向对象空间。
5、元类创建类,类创建实例对象

新式类

1、继承Object
2、在py3中定义的类都是新式类,如果没有指定父类,会默认使用object作为该类的基类
3、为了保证编写的代码能同时在py2和py3中运行,建议统一继承object
4、新式类和经典类在多继承时,会影响到方法的搜索顺序。
python的类如果继承了多个类,其寻找方法的方式有两种,分别是广度优先和深度优先。当类是经典类时,多继承情况下会按照深度优先的方式查找;当类是新式类时,多继承情况下会按照广度优先的方式查找。

旧式类

1、不继承Object
2、在py2中,如果没有指定父类,则不会以object作为基类

对象

python中对象无处不在,变量、数据、函数都是对象
证明方法:
(1)在标识符/数字后输入. 会提示该对象可调用的常用方法列表
(2)使用内置函数dir() 可查看对象内的所有属性和方法

实例对象

1、通过a = A() 来创建实例对象,a 仍然引用的是对象在内存中的地址
2、在计算机中用16进制数表示内存地址
3、使用类名()创建对象时,python的解释器会先调用__new__方法为对象分配内存空间并返回对象的引用,然后调用__init__方法初始化对象的属性
重写new方法可实现单例,__new__一定要返回super().new(cls),如果没有返回对象引用,就不会调用__init__方法

类对象

1、python中一切都是对象,类是特殊的对象。在程序运行时,类同样会被加载到内存中。
2、类对象除了封装的属性和方法外,类对象还有自己的属性和方法,叫类属性和类方法

面向对象

1、面向对象是一种以对象为基础,以事件或者消息来驱动对象执行处理的程序设计思想。
面向过程面是分析出解决问题所需要的步骤,然后用函数把这些步骤一步一步实现,使用的时候一个一个调用就可以了。
2、面向对象特征:封装、基础、多态、抽象
3、面向对象和面向过程的区别:
a、考虑问题的出发点不同。面向过程是以事物流程为考虑问题的出发点,面向对象则以参与事件的角色(对象)为考虑问题的出发点。
b、从结构上讲,面向过程的特点是模块化和流程化;而面向对象的特点是封装、继承和多态。
c、面向过程程序流程在写程序时就已经确定了;面向对象程序流程由用户在使用中决定。

封装

1、 根据职责将属性和方法封装到一个抽象的类中

单继承

1、继承:子类拥有父类的所有属性和方法
2、语法:

class 类名(父类名):
	pass

3、继承的好处:实现代码的重用,相同的代码不需要重写
4、继承具有传递性
5、如果子类不实现__init__(),初始化时调用父类的初始化函数,如果子类实现这个函数,就覆盖了父类的__init__();如果要继承父类的初始化方法,就要在这个函数里显式调用一下父类的__init__()
supper().__init(参数)
6、子类调用父类的属性和方法

class Animal(object):
    def __init__(self, name):
        self.name = name

    def eat(self):
        print("annimal吃")

class Cat(Animal):
    def __init__(self, name):
        super().__init__(name)  
        self.toll = "sdas"

    def eat(self):
      	super().eat()  //调用父类的方法
        print("%s吃" %self.name)  //调用父类的属性
        print(self.toll)
c = Cat("猫咪")
c.eat()

7、python实现继承的原理:python对于定义的每个类,python会计算出一个方法解析顺序列表(MRO),这个MRO列表就是一个简单的所有方法的线性顺序列表。

多继承

1、定义:

class 类名(父类名1,父类名2):
	pass

2、查看继承:
子类.base :只能查看从左到右继承的第一个父类 (<class ‘main.ParentClass1’>,)
子类.bases :能查看所有继承的父类 (<class ‘main.ParentClass1’>,<class ‘main.ParentClass2’>)

super

1、Super是python中的特殊类,super()就是使用super类创建出来的对象。
2、调用父类的方法:super().父类方法
还有一种调用父类方法:父类名.方法(self),但是不推荐使用
3、子类继承父类的初始化方法:如果子类初始化时没有定义__init()(),那么它便调用父类的__init();如果子类实现了这个函数,就会覆盖父类的初始化函数。如果继承父类的__init__(),就需要在子类中使用super()显示调用父类的__init__(), super().__init()。子类也可以在初始化函数中定义自己的属性。

MRO方法搜索顺序

重写

重写的两种情况
1、覆盖父类的方法:父类的方法实现和子类的方法实现完全不同,就在子类中定义一个和父类同名的方法并实现

2、扩展父类的方法:子类的方法实现中包含父类的方法实现,在子类中重写父类的方法,在需要的位置使用super().父类方法来调用父类方法执行,代码的其他位置编写子类的代码

多态

1、多态的前提是继承和重写

class Animal(object):
    def __init__(self, name):
        self.name = name

    def eat(self):
        print("动物吃")

class Cat(Animal):

    def eat(self):
        print("猫咪吃")

class People(object):
    def __init__(self, animal):
        self.animal = animal

    def play(self):
        print("人和动物玩耍")
        self.animal.eat()

a = Animal("动物")
c = Cat("猫咪")
p1 = People(a)
p1.play()
p2 = People(c)
p2.play()

接口
抽象类
dir()

成员变量(实例变量、对象变量、成员属性)

1、属性定义在__init__()方法中
2、在类的外部给对象添加属性,直接用 对象名.name=“s”
不推荐使用,因为对象的属性应该封装在类的内部
3、在成员方法内用self.可访问成员变量
4、在类外部使用对象.访问成员变量
5、一个对象的属性可以是另一个类创建的对象

私有属性(私有变量)

1、定义方式 __变量名
2、私有变量只能在类内部通过self.访问,类外部不可以访问
3、类外部可以通过类的非私有方法访问私有变量
4、python将 __变量名 转换成了_类名__变量名,使用这种可以在类外访问私有变量(不建议这么操作,道德问题)

类属性(类变量)

1、定义在class下方,方法的外面
2、在类外面可通过类名.访问,也可以通过对象名.访问

class A(object):
    a = "s"
    def s(self):
        print(A.a)

    @classmethod
    def b(cls):
        print(cls.a)
print(A.a)
m = A()
print(m.a)

3、在内的内部可通过类名.访问,也可以通过cls.访问,

class A(object):
    a = "s"
    def s(self):
        print(A.a)

    @classmethod
    def b(cls):
        print(cls.a)
m = A()
m.s()
m.b()

3、类属性就是类对象中定义的属性;通常用来记录与这个类相关的特性。类属性不会记录具体对象的特征
4、类变量常用来存储常量、定义默认值、追踪类的所有对象等。

方法

1、类中定义的叫作方法,类外定义的是函数
2、常见的方法有成员方法、静态方法、类方法、私有方法、内置方法

成员方法

1、在类中定义,通过对象来调用,表示针对这个对象做操作
对象.方法名(参数)
2、类中定义方法

class A(object):
	def a(self,*arg,**kwargs)
		pass

3、self代表当前对象,存储的是内存管理中对象的地址
4、同一个类的多个对象的方法在内存中只保存一份,在类内存中。每个对象都有自己独立的内存空间,保存各自不同的属性。多个对象的方法在内存中只保存一份。在调用方法时,需把对象的引用传递到方法内部

类方法

1、定义方式

@classmethod  //修饰符
def 类方法(cls):
	pass

2、cls 是类引用,说明是哪个类调用的方法。
3、在类方法内部使用cls.访问类属性和调用其他类方法,不能访问对象属性和对象方法,可以访问静态方法

私有方法

1、定义方式

def __a():
	pass

2、私有方法只能在类内部调用,不能通过实例调用

静态方法

1、定义方法:

@staticmethod
def sds():
    print("sds")

2、不能访问对象属性、对象方法、类方法
3、调用方法:类名.静态方法

内置方法

1、内置方法的格式__方法名__()
2、new() 创建对象时给对象分配内存空间,是object基类提供的内置的静态方法。
3、init(self) 是初始化函数,也叫构造函数,创建对象时会首先执行
4、del() 对象被从内存中销毁前,会被自动调用
5、str() 返回对象的描述信息,print函数输出使用。类似java的toString()方法,让class作用于print()函数
在python 中输出对象变量时会输出变量的引用对象是由哪个类创建的对象及对象在内存中的地址(16进制表示);如果想要输出自定义的内容,需重写__str__方法,str__必须返回一个字符串。
6、repr() 返回程序开发者看到的字符串
7、iter() 不重写这个方法就不能做索引
实际上只要类实现了__iter
() getiter() next()方法就可以做索引,否则不能索引,字符串、列表、元组等实现了这三个方法。
8、call() 将一个类变成一个函数,使这个类的实例可以像函数一样调用

class A():
    def __init__(self, k, b):
        self.k = k
        self.b = b

    def __call__(self, x):
        print(self.k*x + self.b)
a = A(1, 2)
a(1)
a(3)

闭包

def line(k, b):
    def create_y(x):
        print(k*x + b)
    return create_y

m = line(12, 21)
m(0)

异常

1、语句

import traceback  //引入堆栈包
try:
   	pass  //可能会发生异常的语句
except (IndexError,NameError)as e:
  	//出现异常后执行的语句
	 print e //打印异常信息
	trackback.print_exc() //打印堆栈信息
	return 0 //执行完后会执行finally
else:
	pass  // 没有发生异常时执行的语句
finally:
	pass  //不管有没有发生错误,都执行的语句

2、自定义抛出异常
raise Exception(‘自定义异常’)
3、当函数出现异常时,会将异常传递给函数的调用方。如果传递到主程序,仍没有异常处理,程序才会被终止。
4、在开发中,可以在主函数中增加异常捕获,这样就不需要在代码中增加大量的异常捕获,保证代码的整洁
5、python中的异常都是对象,基础类是BaseException
6、常见异常:
#ImportError 导入模块错误
#IndexError 索引超出范围
#KeyError 字典中key不存在
#NameError 变量没定义
#IndentationError 缩进错误
#SyntaxError 语法错误
#TypeError 不同类型间的无效操作
#ZeroDivisionError 除数为0

调试

发布模块

=制作发布模块(就是模块共享)============
1.创建setup.py文件
From distutils.core import setup

setup(name=‘Distutils’,
version=‘1.0’,
description=‘Python Distribution Utilities’,
author=‘Greg Ward’,
author_email=‘gward@python.net’,
url=‘https://www.python.org/sigs/distutils-sig/’,
packages=[‘distutils’, ‘distutils.command’],
)

2、构建模块
Python3 setup.py build

3、生成发布压缩包
Python3 setup.py sdist

=安装模块============
tar -zxvf .tar.gz
sudo python3 setup.py install

=卸载模块============
cd 目录
sudo rm -rf *

1、包是包含多个模块的特殊目录,目录下有一个特殊的文件__init__.py文件
2、使用包下工具的两种方式
第一种:
from blade.logger import infoLogger as log
第二种:
第一步:在blade 包下的__init__.py文件中指定对外界提供的模块列表
From . Import logger
第二步:Import blade
第三步:访问blade.logger.infoLogger

文件读写

1、f = open(file_path, mode, encoding=‘utf-8’,errors=‘’ ) 返回文件对象(文件句柄)
2、f.read() 一次性读取并返回文件的所有内容
3、f.readline() 一行一行读取文件
4、f.write()
5、f.close()
6、with open(file_path) as file1 可以避免打开文件后忘记关闭,占用资源或当不能确定关闭文件的恰当时机的时候,不用特意关注关闭文件
7、f.readlins() 将每一行形成一个元素,放到一个列表中,将所以的内容全部读出来,如果文件很大,占内存,容易崩盘。
8、f.seek(n) 移动光标位置
9、f.tell() 查看光标位置
10、为open指定errors = ,出现编码错误时,'strict’引发ValueError异常
‘ignore’忽视异常
11、为open指定 buffering =
文件的io操作的缓冲行为有
全缓冲:同系统及磁盘块大小有关,n个字节后执行一次写入操作
行缓冲:遇到换行符执行一次写操作
无缓冲:立刻执行写操作
buffering默认为-1,系统默认的全缓冲
buffering可以设置为大于1的任意整数,字节数为buffering的全缓冲
buffering=1,设置为行缓冲模式
buffering=0, 设置为无缓冲模式
12、newline参数用来指定读写时,对换行符的处理。
在读文件时,
缺省为 None,表示通用的换行符(“\n”),即文件的换行符是啥,读出来都是 “\n”.
newline = “” 表示读取的换行符保持不变,原来是啥,读出来还是啥。
newline = “\n” 表示遇到 “\n” 才一行结束,“\r” 像其他普通字符一样对待。
newline = “\r” 表示遇到 “\r” 才一行结束,“\n” 像其他普通字符一样对待。
在文件写入时,
newline = None时,写入的“\n” 自动都变为系统默认的换行符。所以 “\r\n” 在windows下会变成“\r\r\n”写入。
newline = “” 表示不做任何转换写入。
newline = “\n” 表示不做任何转换写入。
newline = “\r” 表示将 “\n” 和 “\r” 都当做 “\r” 进行写入,所以“\r\n” 会变成 “\r\r”进行写入。
‘’’

文件操作

1、判断文件是否存在
(1)

try:
    f =open()
    f.close()
except FileNotFoundError:
    print "File is not found."
except PersmissionError:
    print "You don't have permission to access this file."

(2)

import os
os.path.isfile("test-data")

(3)

import pathlib
path = pathlib.Path("path/file")
path.is_file()

2、文件重新命名

import os
os.rename(源文件名, 目标文件名)

3、删除文件

import os
os.remove(文件名)

目录操作

1、创建文件目录

import os
os.mkdir(目录名)

2、查看目录列表

import os
os.listdir(目录名)

3、删除目录

import os
os.rmdir(目录名)

4、获取当前目录

import os
os.getcwd()

5、修改当前目录

import os
os.chdir(目标目录)

6、判断是否为文件目录

import os
os.path.isdir(文件路径)

进程

1、进程和线程的联系及区别:
进程和线程都可以实现多任务。(1)进程是资源分配的基本单位,程序运行时会系统创建一个进程,并为它分配资源。线程是程序执行的最小单位。(2)线程不可独立存在,需要依赖于进程。(3)一个进程可以有多个线程,多个线程共享进程的资源,而多个进程间资源是独立的,所以CPU切换一个线程的花费比切换进程的小,同时创建一个线程的开销也比进程要小很多。(4)多进程稳定性高,一个子进程崩了不会影响其他进程,因为每个进程都有独立的资源;但是任何一个线程挂掉都可能直接造成整个进程崩溃,因为多个线程共享一个进程资源(5)由于GIL锁的缘故,python 中线程实际上是并发运行(即便有多个cpu,线程会在其中一个cpu来回切换,只占用一个cpu资源),而进程才是真正的并行(同时执行多个任务,占用多个cpu资源)(6)IO密集型使用多线程,计算密集型使用多进程。

2、进程状态:就绪、运行、等待(阻塞)、死亡
3、Ps -aux 可查看某个程序的进程数
4、代码实现同线程类似

import multiprocessing

def test_1():
    while True:
        print("进程1")


def test_2():
    while True:
        print("进程2")

if __name__=="__main__":
    p1 = multiprocessing.Process(target=test_1)
    p2 = multiprocessing.Process(target=test_2)
    p1.start()
    p2.start()

5、一个程序至少有一个进程,一个进程至少有一个主线程。
6、可以通过socket、文件读写、Queue队列完成进程间通信

进程池

1、主进程或者主线程会等待子进程或者子线程执行完毕后结束,但是创建线程池后,主进程不会等待进程池中的代码执行完,可以使用进程池的.join()方法等待子进程执行完。
2、示例:

import os
import multiprocessing


def copy_file(file_name):
    with open(file_name) as f:
        cont = f.read()
        with open(file_name,'wb') as f2:
                f2.write(cont)


def main():
    folder_name = ""
    try:
        os.mkdir(folder_name+"复制")
    except Exception as e:
        pass
    files_names = os.listdir(folder_name)
    po = multiprocessing.Pool(5)
    for fi in files_names:
        po.apply_async(copy_file, args = (fi,))
    po.close()
    po.join()


if __name__ == "__main__":
    main()

线程

1、多线程比单线程抓取数据的时候快,
2、线程实现方式有两种:
(1)类式

import threading,time

class myThread(threading.Thread):
    def __init__(self, name, delay, counter):
        super().__init__()
        self.name = name
        self.delay = delay
        self.counter = counter
    # 重写run
    def run(self):
        self.name = threading.Thread.getName(self)
        print_time(self.name, self.delay, self.counter)
        print("线程名:"+self.name)

def print_time(name, delay, counter):
    while counter:
        time.sleep(delay)
        print("{}: {}".format(name, time.ctime(time.time())))
        counter -= 1

#创建线程
thread1 = myThread("THREAD-1", 2, 3)
thread2 = myThread("THREAD-2", 5, 2)
print("THREAD-1 is alive?", thread1.is_alive())
thread1.start()
thread2.start()
print("THREAD-1 is alive?", thread1.is_alive())
thread1.join()
thread2.join()
print("THREAD-1 is alive?", thread1.is_alive()) 

(2)函数式

import threading
def A():
	print("线程1")
def B()print("线程2")
if __name__ == "__main__":
	t1 = threading.Thread(target = A, args=(,))
	t2 = threading.Thread(target = B)
	t1.start()  //start 创建线程,start前不会创建线程
	t2.start()
	print “主线程”

3、主线程在子线程执行结束后结束
4、一个程序运行起来,一定有一个主线程
5、多线程共享全局变量有抢占资源的问题,可采用同步的互斥锁来解决问题
6、threading常用方法
threading.enumerate() 返回当前正在运行的线程list,正在运行是指线程启动后、结束前;
threading.current_thread() 返回当前线程变量
threading.active_count() 返回当前正在运行的线程数

同步 互斥锁

同步是“协同步骤”,不是“一起”
当多个线程几乎同时修改某一个共享数据的时候,需要进行同步控制。线程同步能保证多个线程安全访问竞争资源。最简单的同步机制是引入互斥锁。
互斥锁保证了每次只有一个线程进行写入操作,从而保证了多线程先数据的准确性。

创建锁 :mt = threading.Lock()
锁定 :mt.acquire()
释放 :mt.release()

死锁

两个锁互相等待时会出现死锁,此时可以添加超时时间等来解决死锁问题。

线程并发

并发是指两个或多个事件在同一时间间隔发生,python中的线程属于并发,不管计算机有多少个CPU,不管你开了多少个线程,同一时间多个任务会在其中一个CPU来回切换,只占用一个CPU,效率并不高;

进程并行

并行是指两个或者多个事件在同一时刻发生,python中的进程属于并行,能充分利用计算机资源,效率最高,同时执行多个任务,占用多个cpu资源;

1、栈是先进后出型数据结构
2、写一个模拟栈的程序。用户可以输入的参数如下:
在这里插入图片描述

import sys
class Stack():

    def __init__(self):
        self.stack = []

    def push_stack(self, arg):
        self.stack.append(arg)
        return self.stack

    def get_top(self):
        if self.stack:
            return self.stack[-1]
        else:
            return None

    def get_len(self):
        return len(self.stack)

    def is_empty(self):
        return self.stack == []

    def pop_stack(self):
        self.stack.pop()
        return self.stack

    def show_stack(self):
        return self.stack

    def do_exit(self):
        sys.exit()
s = Stack()
s.push_stack("aaa")
s.push_stack("bbb")
s.push_stack("ccc")
s.push_stack("ddd")
r = s.get_len()
print(r)
q = s.get_top()
print(q)
print(s.is_empty())
s.pop_stack()
print(s.show_stack())

队列Queue

1、队列是先进先出型数据结构
2、写一个模拟队列的程序。用户可以输入的参数如下
在这里插入图片描述

import sys
class Queue():
    def __init__(self, size):
        self.queue = []
        self.size = size

    def enqueue(self, ele):
        if self.isfull():
            raise Exception("queue is full")
        else:
            self.queue.append(ele)

    def dequeue(self):
        if self.isempty():
            raise Exception("queue is empty")
        else:
            self.queue.pop(0)
    def top_queue(self):
        return self.queue[0]

    def last_queue(self):
        return self.queue[-1]

    def len_queue(self):
        return len(self.queue)

    def isfull(self):
        return len(self.queue) == self.size

    def isempty(self):
        return self.queue == []

    def do_exit(self):
        sys.exit()

    def show_queue(self):
        return self.queue

q = Queue(3)
q.enqueue("a")
q.enqueue("b")
q.enqueue("c")
q.dequeue()
q.enqueue("d")
print(q.show_queue())

全局解释器锁(GIL)

1、每个线程执行前都需要先获取到GIL,保证同一时刻只能有一个线程在执行
2、全局解释器锁只对线程有影响,对进程、协程没有影响
3、如果用cpython 解释器,建议用多进程;如果不使用cpython解释器,多线程比多进程更节省资源

迭代器

1、迭代是访问集合元素的一种方式。
2、可直接作用于for循环的对象为可迭代对象Iterable。判断是否可迭代,可以使用isinstance()判断一个对象是否是Iterable对象。如果想让一个对象成为可迭代对象,类必须实现__iter__()方法。
3、迭代器是一个可以记住遍历位置的对象,用来帮助我们记录每次迭代访问到的位置。
迭代器从集合的第一个元素开始访问,直到所有元素都被访问完结束。迭代器只能往前不能往后。
可以被next()函数调用并不断返回下一个值的对象称为迭代器:Iterator
使用next()函数的时候,调用的就是迭代器对象的__next__方法,python要求迭代器本身是可迭代的,所以我们还要为迭代器实现__iter__方法。一个实现了__iter__方法和__next__方法的对象,就是迭代器。
4、判断一个对象是否可以使用for循序,先判断对象是否可迭代,实现__iter__()的对象即可迭代;再判断__iter__()方法是否返回迭代器,iter()需返回一个具有iter方法和next方法的对象引用,这个对象引用叫作迭代器)。
for循环的本质就是先通过iter()函数获取可迭代对象的迭代器,然后调用迭代器的next()方法获取下一个值,直到报出StopIteration.。
在这里插入图片描述
5、判断是否可迭代:
from collections import Iterable
print(isinstance([], Iterable))
6、判断__iter__()方法是否返回一个具有iter方法和next方法的对象引用(迭代器),可直接使用iter(对象)。iter函数会直接调用对象中的__iter__(),并返回__iter__()的返回值。
7、可迭代对象一类是集合数据类型,如str, list、tuple、dict、set、str等;一类是generator,包括生成器和带yield的generator function。
8、迭代器协议:具有next和iter方法的对象
7、list、dict等是可迭代对象,但不是迭代器。执行iter方法可以把可迭代对象变成迭代器
8、迭代器存储的是生成数据的方式,而不是生成数据的结果,迭代器占用内存小。示例:

class Fibonacci(object):
    def __init__(self, count):
        self.m = 0
        self.n = 1
        self.count = count

    def __iter__(self):
        return self

    def __next__(self):
        if self.count<0:
            raise StopIteration
        temp = self.m
        self.m, self.n = self.n, self.m+self.n
        self.count -= 1
        return temp

for i in Fibonacci(10):
    print(i)

9、不是只有for循环可以接受可迭代对象,list,tuple等都可以接收可迭代对象。list(),tuple()转换
10、除了next()方法外,还可以使用send()方法唤醒迭代器
在这里插入图片描述

生成器

1、生成器是一种特殊的迭代器。
2、创建生成器
方法1(不常用):
‘’‘把列表生成式的中括号变成小括号’‘’

nums = [x*2 for x in range(10)]    //列表生成式
print(nums)
nums = (x*2 for x in range(10)) 	//生成器
print(nums)

方法2:

'''如果一个函数中有yield语句,那么这个函数就不是一个函数,而是一个生成器的模板'''
def create_num(all_num):
    a, b = 0, 1
    current_num = 0
    while current_num < all_num:
    '''每次yield a 返回的值 其实是next(s)'''
        yield a
        a, b = b, a+b
        current_num += 1
    '''py3中的生成器允许使用return返回最终运行的返回值,py2不允许 '''
   	return "ok"
'''调用create_num 不是调用函数,而是创建一个生成器对象'''
s = create_num(10)
'''调用next()函数唤醒生成器'''
qq = next(s)  
print(qq)
'''可以使用next()函数让生成器从断点处继续执行'''
qq = next(s)
print(qq)
qq = next(s)
print(qq)
//for num in s:
//    print(num)

yield

yield关键字有两个作用:
(1)保存当前运行状态,然后暂停执行,即将生成器函数挂起
(2)将yield关键字后面表达式的值作为返回值返回,此时可理解为起到return作用

Python 的 generator 提供了一种实现迭代器协议的便捷方式。 如果容器对象 iter() 方法被实现为一个生成器,它将自动返回一个迭代器对象(从技术上说是一个生成器对象),该对象提供 iter() 和 next() 方法。
generator 就是生成器

协程

协程切换任务占用资源很少,效率高
1、使用yield实现多任务,就是协程

def test1():
    while True:
        print("--1--")
        yield


def test2():
    while True:
        print("--2--")
        yield


def main():
    t1 = test1()
    t2 = test2()
    while True:
        next(t1)
        next(t2)


if __name__ == "__main__":
    main()

2、为了更好的使用协程来完成多任务,可使用greenlet模块来实现(使用比较少)
安装:sudo pip3 install greenlet

from greenlet import greenlet

def test1():
    while True:
        print("--1--")
        gr2.switch()


def test2():
    while True:
        print("--2--")
        gr1.switch()


gr1 = greenlet(test1)
gr2 = greenlet(test2)
gr2.switch()

3、使用gevent实现协程(常使用方法)
安装sudo pip3 install gevent
gevent不同于yield和greenlet,它有个优点,遇到延时会自动切换
在这里插入图片描述
程序中有耗时时,将程序中用到的耗时操作的代码自动换成gevent.sleep()

import gevent
from gevent import monkey
monkey.patch_all()

批量添加任务

gevent.joinall(
    [
        gevent.spawn(函数名, "参数1"),
        gevent.spawn(函数名, "参数2")
    ]
)

装饰器

1、python装饰器(fuctional decorators)就是用于拓展原来函数功能的一种函数,目的是在不改变原函数名(或类名)的情况下,给函数增加新的功能。
装饰器函数的特殊之处在于它的返回值也是一个函数,这个函数是内嵌“原”函数的函数。
2、python内置装饰器:

  • staticmethod 是类静态方法,其跟成员方法的区别是没有 self 参数,并且可以在类不进行实例化的情况下调用
  • classmethod 与成员方法的区别在于所接收的第一个参数不是 self (类实例的指针),而是cls(当前类的具体类型)
  • property 是属性的意思,表示可以通过类实例直接访问的信息
  • unique 定义枚举函数, value值唯一
    3、原始装饰器实现方法:
import time

def deco(f):
    def wrapper():
        start_time = time.time()
        f()
        end_time = time.time()
        execution_time = (end_time - start_time)*1000
        print("time is %d ms" %execution_time )
    return wrapper

@deco  
def f():
    print("hello")
    time.sleep(1)
    print("world")
if __name__ == '__main__':
	f()

@deco //等价于 f = deco(f)

4、带有固定参数的装饰器

import time

def deco(f):
    def wrapper(a,b):
        start_time = time.time()
        f(a,b)
        end_time = time.time()
        execution_time = (end_time - start_time)*1000
        print("time is %d ms" % execution_time)
    return wrapper

@deco
def f(a,b):
    print("be on")
    time.sleep(1)
    print("result is %d" %(a+b))
if __name__ == '__main__':
    f(3,4)

5、无固定参数的装饰器

import time

def deco(f):
    def wrapper(*args, **kwargs):
        start_time = time.time()
        f(*args, **kwargs)
        end_time = time.time()
        execution_time_ = (end_time - start_time)*1000
        print("time is %d ms" %execution_time)
    return wrapper

@deco
def f(a,b):
    print("be on")
    time.sleep(1)
    print("result is %d" %(a+b))

@deco
def f2(a,b,c):
    print("be on")
    time.sleep(1)
    print("result is %d" %(a+b+c))

if __name__ == '__main__':
    f2(3,4,5)
    f(3,4)

6、使用多个装饰器,装饰一个函数

import time

def deco01(f):
    def wrapper(*args, **kwargs):
        print("this is deco01")
        start_time = time.time()
        f(*args, **kwargs)
        end_time = time.time()
        execution_time = (end_time - start_time)*1000
        print("time is %d ms" % execution_time)
        print("deco01 end here")
    return wrapper
def deco02(f):
    def wrapper(*args, **kwargs):
        print("this is deco02")
        f(*args, **kwargs)

        print("deco02 end here")
    return wrapper

@deco01
@deco02
def f(a,b):
    print("be on")
    time.sleep(1)
    print("result is %d" %(a+b))
    
if __name__ == '__main__':
    f(3,4)
”f(3, 4) = deco01(deco02(f(3, 4)))

7、装饰器的作用和功能
引入日志
函数执行时间统计
执行函数前预备处理
执行函数后的清理功能
权限校验等场景
缓存
8、带有返回值的装饰器

def line(f):
    def create_y():
        return f()
    return create_y

@line
def test1():
    return "test1"

ret = test1()
print(ret)

9、用类对函数进行装饰

class Test(object):
    def __init__(self, func):
        self.func = func

    def __call__(self):
        print("为装饰器添加功能")
        return self.func()

@Test
def get_str():
    return "haha"

print(get_str())

框架搭建

1、开发时,python代码模式
导入模块
定义全局变量
定义类
定义函数

def main():
pass

if name==“main”:
main()

设计模式

单例设计模型

1、用类创建的对象,在系统中只有唯一的实例(每次执行类名创建对象, 返回对象的内存地址都是一样的)
2、实现

class A():
    instance = None
    def __new__(cls, *args, **kwargs):
        print("创建对象分配空间")
        if A.instance is None:
            A.instance =  super().__new__(cls)
        return A.instance

p1 = A()
p2 = A()
print(id(p1))
print(id(p2))

虽然每次都使用第一次创建的对象,但是会多次调用初始化方法。
修改方法:

class A():
    	instance = None
	init_flag = False

    	def __new__(cls, *args, **kwargs):
        		print("创建对象分配空间")
        		if A.instance is None:
            		A.instance =  super().__new__(cls)
		return A.instance

	def __init__(self):
		if not init_flag:
			print(“初始化”)
			init_flag = True
p1 = A()
p2 = A()
print(id(p1))
print(id(p2))

哈希

1、哈希是一种算法,hash函数接受一个不可变类型的数据作为参数,返回一个整数。传入数据相等返回的哈希值也相等。

深拷贝、浅拷贝

1、浅拷贝是对一个对象的顶层拷贝。浅拷贝后,改变原始对象中为可变类型的元素的值,会同时影响拷贝对象;改变原始对象中为不可变类型的元素的值,不会响拷贝对象。
2、深拷贝,除了顶层拷贝,还对子元素也进行了拷贝。经过深拷贝后,原始对象和拷贝对象所有的可变元素地址都不相同。
在这里插入图片描述
3、不论深拷贝还是浅拷贝,拷贝list时 会新建地址,但是拷贝int、str不可变数据类型时不会新建地址。
4、元组中没有可变类型时,深拷贝浅拷贝都不会拷贝,都是引用指向;但是元组中有可变类型时,浅拷贝不拷,深拷贝会新建地址
5、copy.copy()是浅拷贝
copy.deepcopy()是深拷贝
6、另外 列表的切片是浅拷贝;
字典的.copy()方法也是浅拷贝

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值