python笔记
2024-05-05 09:53:48 1 举报
AI智能生成
基础语法
作者其他创作
大纲/内容
尽管会警告,但还是照样运行告诉程序员看:我这个函数规定了数据类型,你传错类型后续出了什么事不负责
给变量赋值的时候,不需要指定变量的数据类型
python是动态语言
这个在下面字符串格式化里会详细讲
1+2=3
print(\"{0}+{1}={2}\".font color=\"#ff0000\
不写end,默认换行(end=\"\\")
print(\"balabalabala\
%10s,表示10个字符的宽度
字符串
%s
同上
整数
%i or %d
%.3f,保留三位小数
%10.3f,宽10并保留三位小数
浮点数
%f
\"这个是%s常用的%s格式化\" % (\"我\
f'我叫{\"你猜\"},今年{88}岁'
print
保留字
换行,一般在末尾,strip对其也有效
\
空字符
\\0
tab,四个空格
\\t
‘
\\'
“
\\''
\\
\\\\
以下不常用
发出系统响铃声
\\a
退格符,覆盖删除前一个
\\b
换行,并将当前字符串之前的所有字符删除
不常用
\\v
\\f
转义字符
不可变数据(3 个):Number(数字<包括int(整型)、float(浮点型:小数)、bool(布尔型)、complex(复数)>)String(字符串)、Tuple(元组);不可以增删改做改变之后 id() 查看内存地址,改变
可变数据(3 个):List(列表)、Dictionary(字典)、Set(集合)。可以增删改增删改后用内置函数 id() 查看内存地址,不变
Number(数字)String(字符串)List(列表)Tuple(元组)Set(集合)Dictionary(字典)
作用:number:用来存储数字类型的数据,多用于运算,布尔型也属于number,用于逻辑运算,true为真,false为假string:用来存储字符串,如中文、英文等,一般用于一些描述性的文字输出list:用来存储列表,即多个数据类型任意的元素tuple:用来存储元组,一种有序的且不可更改的集合set:用来存储集合,一种无序的,且可以更改的集合dictionary:用来存储字典,一种无序的,可变的有索引的集合
内置的 type() 函数可以用来查询变量所指的对象类型
str()
int()
float()
字符类型转化
数据类型
单行:#
多行: ''' 或者\"\"\"
注释
input
+
-
*
/
%取余
**幂
//取整除,向下取整
算数
=
+=
-=
*=
/=
%=
**=
:=,不常用
赋值
==
!=
<
>
<=
>=
比较
and,与
or,或
not,非
逻辑(布尔)
按位与,都是1才是1,其他全是0
&
按位或,有1就是1
|
按位异或,不同就是1
^
按位取反,0变1,1变0
~
x<<n==x*(2**n)
左移动相应位数,高位丢弃,低位补0
<<
int除完会变成float所以只是数值上相等,type上还是不同的
x>>n==x/(2**n)
右移动相应位数,低位丢弃,高位补0
>>
位运算
or
and
**
优先级
运算符
顺序结构
python一切皆对象,所有对象都有一个布尔值,bool()
false
数值0
None
\"\
空字符串
空列表
空元组
空字典
set()
空集合
以下都为false
其他对象布尔值都为true
对象的布尔值
比较值
是否是同一个地址
is
if isinstance (当前对象,指定对象)
判断当前对象是否是指定对象的子类
isinstance
判断方法
if
单分支
if else
双分支
if elif elif (else)
多分支
if 套 if
嵌套
一个占位符:没想好if判断后执行啥,先pass占个位
pass语句
插一嘴
判断语句成立执行语句1,否则执行语句2
语句1 if 判断语句 else 语句2
三元运算
选择结构
range(stop)
range()
一般while true,也可以while+条件
while循环
for_in 循环
结束当前循环,本层
if...break
或者直接break
break跳出
结束当前循环,直接进入下次循环,本层
if...continue
或者直接continue
continue
当循环中不执行break,则执行else
for...else
break会让else中的代码不执行,continue就没这个功能
while...else
else
嵌套循环
循环结构
三大结构(顺序,选择,循环)
字符串长度为0或者1
符合标识符的字符串(只包含字符 数字 下划线)
a b c值一样,type也都是strb的值在运行之前就连接完毕了c的值是程序运行的时候通过join的方法和列表连接的,运行的时候会开辟新的存储空间,所以和a b的存储空间不一样
字符串只在编译时进行驻留,而非运行时
交互模式(cmd)
在内存中保存一份且不可变字符串的方法。(相同的字符串只保留一份)
import sysa = sys.intern(b)
相同的值可以强制驻留
pycharm对字符串进行了优化,有些不驻留的进行了强制驻留处理
因为字符串的拼接和修改比较影响性能
避免频繁重复创建销毁,提升效率节约内存
join()是先计算所有字符串的长度,再拷贝,只new一次对象,效率比+高
用str类型的join来拼接字符串,而非+
优点
驻留
找不到报valueerror
查询substr(子串)第一次出现的位置
index()
查询substr(子串)最后一次出现的位置
rindex()
找不到返回-1
find()
rfind()
返回str在start和end之间,在my_str里出现的次数
count()
检查字符串是否以指定字符串开头,返回True或False
startswith()
检查字符串是否以指定字符串结束,返回True或False
endswith()
查
所有都大写
a.upper()
所有都小写
a.lower()
大转小,小转大
a.swapcase()
第一个大写,其余小写
a.capitalize()
每个单词的,第一大写,其余小写
a.title()
大小写转换
参数第一个是宽度,第二个是填充符(默认空格)
如果宽度参数小于字符串长度,则返回原字符串
居中
左对齐
右对齐
一个参数,如果是-87654,在 - 后面填0
a.zfill(20)
右对齐,左0补齐
对齐
从左开始分割,默认从空格开始分割
放回一个列表
maxsplit是可选参数
split()
从右侧,同上
rsplit()
字符串分割为str前+str+str后三部分
partition(str)
若字符串中有换行,则按行分割,返回各行为元素的列表
splitlines()
分割
是否为合法标识符字符串(只包含字母(中文) 数字 下划线)
a.isidentifier()
是否全是空白字符(空格 换行 tab)
a.isspace()
是否全是字母(中文)
a.isalpha()
是否全是十进制数字
a.isdecimal()
只要是数字就行,中文数字,中文大写数字,罗马数字
是否全是数字
a.isnumeric()
这个就只是阿拉伯数字
是否只含数字
a.isdigit()
是否全是字母(中文)和数字
a.isalnum()
判断
第三个参数是最大替换次数,可选
a.replace('原字符串',‘替换成的字符串’,2)
替换
将列表中的元素用 * 合并成一个字符串
'*'.join(list)
元组同上
a = '*'.join('hello world')print(a)>>h*e*l*l*o* *w*o*r*l*d
单个字符当一个元素
字符串序列
join()
合并
比较规则:从第一个字符开始比较,到第一个不相同的字符
查看a的原始值
ord('a')
查看原始值为97的字符
chr(97)
比较原理:比较的是字符的原始值order value
从0到4
a[:5]
从6到最后
a[6:]
a[start : end : step]
step正从前开始,step负从后开始
切片
strip()
删除两端空白字符
其他方法
一共三位
{0:.3}
三位小数
{0:.3f}
宽10位,共三位小数
{0:10.3}
\"这个是{0}比较常用的{1}格式化\".format(\"我\
格式化(按固定格式输出)在字符串中加入变量
>>b'\\xd4\\xde\\xc3\\xc0\\xd3\\xde\\xd5\\xdf'>>b'\\xe8\\xb5\\x9e\\xe7\\xbe\\x8e\\xe6\\x84\\x9a\\xe8\\x80\\x85'
word = \"赞美愚者\"encoding1 = word.encode(encoding='GBK') # GBK编码格式 一个中文两个字节encoding2 = word.encode(encoding='utf-8') # utf-8 一个中文三个字节print(encoding1)print(encoding2)
将字符串转换成二进制数据(bytes)
编码
>>赞美愚者>>赞美愚者
decoding1 = encoding1.decode(encoding='GBK')decoding2 = encoding2.decode(encoding='utf-8')print(decoding1)print(decoding2)
将bytes数据转换成字符串
解码
编码转换
lst=[\"a\
lst=list([\"a\
创建
列表生成式
获取制定元素的索引(第一个)
lst.index(\"a\")
获取列表中index为1的元素
lst[1]
从前往后start
step为正
从后往前start
step为负
lstChild = lst[start : stop : step]
获取
in
not in
判断元素是否存在
item是可迭代对象
for item in lst:
首选
>>1>>2>>3
while
遍历
L.count('a')
统计元素个数
list.index('元素')
查询元素的索引
列表末尾添加一个元素
append()
extend()
任意位置插入一个元素
insert()
增
lst.remove(元素值)
一次删除一个,有重复的删除第一个
remove()
lst.pop(索引号)
删除指定索引的元素,不写索引默认最后一个元素
pop()
清空列表
clear()
del list[2]
根据下标删除
删除列表
del
删
lst[index]=修改后的元素
切片修改
lst[start:stop]=[........]
改
增删改查
通过id(lst)可查看还是同一个列表
key参数主要用于自主选择排序的方式,一般=某函数
lst.sort(key=function( ))
lst.sort()
创建了一个新列表
sorted(lst)
将列表倒叙
reverse()
排序
1. 列表对象有序排序2. 索引映射唯一数据3. 列表可以存储重复数据4. 任意数据类型混存5. 根据需要动态分配和回收内存
python test.py 卢卡斯>>卢卡斯
sys.argv就是一个列表,这个列表中存储着运行是传递的参数,注意全部是字符串
import sysprint(sys.argv)
给程序传递参数
列表
()可以省略
(\"元素\",“有一个元素”, 8 )
tuple((\"元素\",“有一个元素”, 8 ))
tuple(......)
一个元素的元组,一定要加逗号
(\"元素\",)
()
元组不可变,但元组中的可变数据可以改变,比如有个list元素
>>python>>good>>98
t = tuple((\"python\
元组
{......}
将列表转成集合
set([列表])
将元组转成集合
set((元组))
s1 = set(\"python\
将字符串转成集合
set(\"字符串\")
set(......)
用{}创建的是空字典
set() 空集合
s.add(一个元素)
s.update(至少一个元素)
元素不存在报keyerror
s.remove(元素)
元素不存在不报错
s.discard(元素)
s2 = s1.pop(),s2是s1中拿出的那个元素
不能加参数,随意删一个
s.pop()
清空元素
s.clear()
删除集合
del s
集合的元素为不可变类型,所以无法修改
!=
相等
s1是否是s2的子集
s1.issubset(s2)
子集
s2是否是s1的超集
s2.issuperset(s1)
超集
s1和s2是否不相交
s1.isdisjoint(s2)
不相交
集合之间的关系
s1.intersection(s2)
s1 & s2
交集
s1.union(s2)
s1 | s2
并集
s1.difference(s2)
s1 - s2
差集
s1.symmetric_difference(s2)
s1 ^ s2
对称差集(s1并s2 - s1交s2)
交并差
集合生成式(和列表差不多)
集合
列表,集合转换为元组
tuple()
可完成对list和tuple的快速去重
列表,元组转换为集合
set()
元组,集合转换为列表
list()
序列类型的类型转换(不包括字典)
from collections.abc import Iterableprint(isinstance([]font color=\"#ff0000\
判断数据是否可迭代
zip() 函数用于将可迭代的对象作为参数,将对象中对应的元素打包成一个个元组,然后返回由这些元组组成的列表
zip()
a = {\"name\
c={},空字典
items = [\"a\
字典生成式
如果键不存在,报错,keyerror
a[\"name\"]>>Lucas
[键]
如果键不存在,返回None
如果键不存在,返回默认值
a.get(\"gaga\
a.get(\"name\")
get(键)
key的判断
for key in dict.keys(): print(key)
所有键
for val in dict.values(): print(val)
所有值
每对键值输出为一个元组tuple
for item in dict.items(): print(item)
所有元素
查(键对应的值)
删除指定键值对
del a[\"name\"]
删除整个字典a
del a
清空字典a
a.clear
a[\"新键\"]=对应的值
a[\"要修改的键\"]=新值
获取字典中所有的键(key)
dict.keys()
获取字典中所有的值(value)
dict.values()
获取字典中所有的键值对(key.value)
dict.items()
视图操作
获取键keys
print(item)
获取值values
print(a[item])
print(a.get(item))
for item in a:
遍历元素
1.键值对,键不可以重复,值可以重复2.元素是无序的3.key必须是不可变对象4.动态调整内存5.消耗较大内存6.hash表计算存储位置
字典
[x for x in range(4)]
[x for x in range(4) if x % 2 ==0]
加条件
自动x和y在取值范围内排列组合
for嵌套循环
[变量 for 变量 in 可迭代对象]
列表(List Comprehension列表解析)
快速生成数据
推导式
同上,默认取到的是key
快速提取
经典python交换变量值
拆包
def 函数名([函数参数]): 函数体 [return xxx]
返回长度
len
返回最大值
max
del a或者del(a)
稍后再说
time包
用到再说
random包
部分内置函数
自定义函数记得加说明文档
a和b
形参(定义处)
a和b的实际值
实参(调用处)
形参实参
参数调用
形参实参名称可以不同
参数传递
记住python赋值不是改变对象的值而是将对象指向存储值的内存就行
如果是不可变对象,在函数体内的修改不影响实参的值
如果是可变对象,在函数体内的修改影响实参的值
参数传递时的内存
函数定义时,给形参定义默认值,调用时只有和默认值不符时传递实参
这时args是一个元组,可以进行元组的各种操作
结果是元组
个数可变的位置参数
表示调用函数时多余的未命名参数都会以元组的方式存储到args里
一个函数只能定义一个位置参数
*args(未命名参数)
结果是字典
个数可变的关键字参数
表示调用函数时多余的命名参数都会以键值对的方式存储到kwagrs
*之后的参数只能用关键字参数传递
一个函数只能定义一个关键字参数,且要放在位置参数后面
**args(**kwagrs)(命名参数)
a= 1b= 2c= 3
a= 10b= 20c= 30
a= 11b= 12c= 13
总结
参数定义
return后面的语句不会被执行,只执行第一个return
返回值和结束函数2个作用
是元组就能拆包
返回多个值时,结果为元组
返回值return
*对列表、元组、集合可以拆包,但一般都是在调用函数时用
**可以对字典进行拆包,拆包的结果是命名参数
通过星号拆包
一般情况下用来打印提示等类似的功能
无参,无返回
一般情况下像采集数据等功能会用到
无参,有返回
一般情况下对某些变量设置数据而不需结果时用此类函数
有参,无返回
大多数
有参,有返回
4种函数
# 例1 画线def line(): print('---------------'*3)def print_lines(num): for i in range(num): line() i += 1print_lines(5)
函数嵌套
函数内的
局部变量
要在函数内修改全局变量,先用global声明
函数外的
全局变量
变量的作用域
add_up = lambda 形参1,形参2:表达式
接收任何数量的参数但只能返回一个表达式的值,其默认就是返回的,不用写return
1.像普通函数一样,变量名( )
2.在其他函数实参的位置,直接定义一个lambda
使用方式
匿名函数(lambda)
阶乘函数def fac(n): if n == 1: return 1 else: res = n*fac(n-1) return res
占内存效率低,但简单易懂啊
就是函数内调用自己
有调用有终止
其实递归是一种算法,一般用来解决“树”、“图”等操作,还能解决像“汉罗塔问题”等
递归函数
函数
面向过程 VS 面向对象
不同的数据类型属于不同的类
python中一切皆对象有id(内存空间),有type(数据类型),有值
900就是int数据类型下的一个对象
类 VS 对象
一般首字母大写,其余小写
class Student: pass
类的创建
可以在外面通过Student.gender = None,加一个类属性
类属性
当通过实例对象调用方法的时候,self能够自动指向实例对象,从而拥有了操作这个对象中的属性或者方法的可能。
self
比如上面的例子中,eat方法,并没有指向name或者age,所以其实属于静态方法
静态方法之所以不需要self,是因为方法内不需要实例对象的引用
能获取构造函数定义的变量,也不可以获取类的属性。
静态方法
不能获取构造函数定义的变量,可以获取类的属性。
类方法
组成
stu = Student(初始化方法的参数)
对象名.方法名
stu.eat()
类名.方法名(类的对象)----方法定义处的self
Student.eat(stu)
调用属性
stu.name
对象的创建
删除属性
print(Student.native_pace)print(stu.native_pace)
# 直接写在类里面的变量 native_pace = '江苏'
类中方法外的变量,被该类所有对象共享
Student.cm()
@classmethod def cm(cls): print('类方法写cls')
使用类名直接访问的方法
Student.method()
@staticmethod def method(): print('静态方法不加self')
调用
类
再用B.aa就可以调用A的属性和方法了
B.新属性aa=a
类A,实例对象a=A()类B,实例对象b=B()
对象关联
self.__age = age再用stu.__age是访问不到的,但用stu._Student__age还是能访问,纯靠自觉
如果属性不希望被外部调用,可以前面加2个_
将数据(属性)和行为(方法)包装到类对象中。(转为私有属性or隐藏属性)
封装
没写父类的默认继承object
super().__init__( )
定义子类时,要在构造函数中调用父类的构造函数
子类有多个父类
子主题
如果2个子类中都继承了同个父类,当在子类中通过父类名调用时,parent被执行了2次
如果2个子类中都继承了同个父类,当在子类中通过super调用时,parent被执行了1次
关于多继承的__mro__顺序用类名.__mro__,这个魔术方法,可以查看这个类的继承顺序
支持多继承
子类只有一个父类
单继承
1.super().__init__相对于类名.__init__,在单继承上用法基本无差2.但在多继承上有区别,super方法能保证每个父类方法只会执行一次,而类名.方法()会导致方法可能被执行多次3.多继承时,用super方法,对父类传参,由于super的算法,必须把参数全部传递,否则报错,所以就要加上*args和**kwargs4.单继承时,用super方法,不用全部传参,只能传父类方法所需的参数,否则报错注:在多继承时,尽量不用super,用父类名.方法()用super虽然对于同个父类的调用可以避免重复执行,但代码阅读难度增加,不利于debug
基本概念
返回对象的描述
https://blog.csdn.net/m0_57133702/article/details/120568504
__str__()方法
所有类的父类
object类
就是在子类中重新定义父类的方法先加个super().xx()这样可以继承父类的xx()方法然后再加新的功能
如果不加super(),就继承不了父类方法
子类想输出自己独有的东西,父类没有
方法重写
继承
反正就是调用类的方法很方便
>>人向狗进行了攻击>>普通狗汪汪叫>>人向狗进行了攻击>>狼狗狂吠>>人向狗进行了攻击>>普通狗汪汪叫
class Dog(): def bark(self): print(\"普通狗汪汪叫\")class LangDog(Dog): def bark(self): print(\"狼狗狂吠\
有别于如Java的静态语言,python这种动态语言的多态就相当灵活了如果一个变量存储了某一个实例对象的引用,且通过这个变量调用指向的对象中的某个方法,此时如果变量指向的对象是子类创建的那么就调用子类中的方法,如果是父类创建的对象那么就调用父类的方法
多态
三大特征(封装,继承,多态)
常用内建属性
如果需要当前类做多个实例化,则只需要创建一个空间来存储实例对象
帮助类在内存中只开辟一个空间储存属性和方法在__init__之前
__new__(cls)
__init__
实例对象p是通过__class__找到Person这个类的,然后才能调用类中的方法
__class__
实例对象要访问实例属性,要通过这个方法
方法中的item参数是实例属性的属性名称
如果访问的是name1,会被拦截,传回指定值,如果访问name2,则可以返回传入的值
用户访问属性,传入一个参数,可以返回提前设定好的值
能够完成属性访问时进行拦截
__getattribute__
输出类的说明描述。类的说明写在类名下一行,__doc__只调用那段注释。
类名.__doc__
__doc__
module打印所在的模块(所在的py文件)class打印所在类
__module__和__class__
一般不去改
当对象在内存中被释放之前,自动触发执行
__del__
可以在__call__中添加一些功能,用Foo()()直接调用
当成函数去用,就可以传参了
把实例对象当成一个函数去使用
__call__
返回类的属性和方法,以及对应的值返回实例对象的属性,名称和值
__dict__
返回值只接受string
如果在类中定义了__str__方法,打印方法时,默认输出这个方法的返回值
__str__
字典一定要用foo['hahaha']操作才能调用这三个方法
对容器类型进行操作,获取,设置,删除对于列表,元组,字符串。foo[index],索引对于字典。foo[key],键
内建属性
gender属性只有stu1有
show()只有stu1能调用
@staticmethoddef static_func(): print('这是一个静态方法')Student.address = '深圳' # 先创建一个类属性@classmethoddef class_func(cls): print(f'这是类方法,类属性值为:{cls.address}')Student.static_func = static_funcStudent.class_func = class_funcstu2.static_func()stu1.class_func()
创建完对象后,为个别对象动态绑定一个属性(方法),该属性只有这个对象有,其他对象没有
动态绑定属性和方法
限制属性的创建1.为了限制随意给对象添加属性或者方法2.对子类不起作用,只限制当前类3.不可以卸载__init__中
__slots__特殊属性
@property def func(self): return '调用func'foo = Foo()res = foo.func
当前类中,装饰在某个方法上,使得这个方法可以像属性那样被调用用于拿到当前方法中计算的返回值被property装饰的方法不能创建除了self之外的形参
>>第一页显示第0到第9条数据>>第一页显示第10到第19条数据
'''对于京东商城中显示电脑主机的列表页面,每次请求不可能把数据库中的所有内容都显示到页面上,而是通过分页的功能局部显示,所以在向数据库中请求数据时就要显示的指定获取从第m条到第n条的所有数据 这个分页的功能包括:1.根据用户请求的当前页和总数据条数,计算出m和n2.根据m和n去数据库中请求数据'''
简单例子:
>>100>>200>>... AttributeError: 'Goods' object has no attribute 'price'. Did you mean: '_price'?
用property进行商品价格控制
>>80.0>>setter被调用>>160.0>>deleter被调用>>.... AttributeError: 'Goods' object has no attribute 'original_price'
在商城开发中设置打折价格
1.装饰器方式
>>100
类属性 = property(需要装饰的方法)
>>当前get bar被执行>>a>>当前set bar被执行 d>>当前del bar被执行>>当前字符串是对property的一个解释说明
第一个参数是方法名,调用 对象.属性 时自动触发执行方法第二个参数是方法名,调用 对象.属性 = XXX 时自动触发执行方法第三个参数是方法名,调用 del 对象.属性 时自动触发执行方法第四个参数是字符串,调用 类名.属性.__doc__ ,此参数是该属性的描述信息注:property中的参数顺序一定要按照get set del排序
案例
python2.7中常这么用,3之后很少用
2.类属性方式,创建值为property对象的类属性
property属性
test_1
>>num1是可引用内容>>100>>AttributeError:不拉不拉,test_1没num2这个属性
test_2
函数入口:写在入口下的内容只能在当前文件内运行,被引用时,入口下的内容引用不到
if__name__=='__main__':
特殊属性
new和init的传参过程
特殊方法
用到再查
特殊属性和方法
类的赋值和浅拷贝
面向对象
for
# 一般写except Exception:当前python所有错误的基类
iter()和next()
可以记住遍历的位置的对象只能往前不能后退
如果对象只有__iter__方法,是可迭代对象如果对象有__iter__和__next__方法,则是迭代器
Iterable和Iterator
1. 先定义主要类
2. 给这个类定义一个迭代器
>>11>>22>>33
3. MyList的实例对象my_list这时就可以用for循环遍历了
例
自定义迭代器
1.初始化和add方法
2.iter和next
3.实例化,调用3次add,for循环遍历
例:学生系统
多继承也可以,但项目开发中,尽量少继承,继承的执行速度比对象关联慢
注释:如果有4个类,分别在4个py文件中这4个类的迭代的方法是一模一样的写一个迭代器直接导入引用
迭代器
定义了一个生成器函数,函数返回一个生成器对象,然后就可以通过for语句进行迭代访问了。
生成器函数返回生成器的迭代器。 \"生成器的迭代器\"这个术语通常被称作\"生成器\"。要注意的是生成器就是一类特殊的迭代器。作为一个迭代器,生成器必须要定义一些方法,其中一个就是__next__()。如同迭代器一样,我们可以使用__next__()函数来获取下一个值。
概念:含yield的函数
会在yield处暂停
执行流程
>>列表推导式时间为3.2063777446746826
列表解析(列表推导式)
>>生成器表达式时间为0.0
生成器表达式
对比
列表解析:1.开辟一个内存2.开完内存创建所有值生成器表达式:1.返回的不是具体序列数据,是生成器对象2.使用next()取生成器中的值,内存中只有一个值。调用一次,产生一个值
原因
>>True>>True>>25000000>>[]
创建长序列时使用(x for x in range(100))
>>0>>接收到参数,将此时的i(即0)+10输出=10>>1
注意 i 的值,第一次取值时在yield处暂停,第二次取值继续时,先读if判断,此时 i 还未 +1
1.send方法与next方法类似2.可以向生成器传递一个参数,并在生成器中进行接受3.一般不在第一次获取值时使用,第一次获取时必须传递None print(my_iter.send(None))4.可以在程序运行的过程中对当前的函数运行过程进行操作
send()
关闭之后再取值会抛出异常
my_iter.close()print(next(my_iter))
关闭当前生成器(相当于删除或销毁)
close()
内置方法
当调用生成器函数的时候,函数只是返回了一个生成器对象,并没有执行。
当next()方法第一次被调用的时候,生成器函数才开始执行,执行到yield处暂停next()方法返回值就是yield处的参数
继续调用next()方法时,函数直接接着上一次暂停的yield处继续执行,到下一个yield出暂停如果后面没有yield就抛出StopIteration异常
return:代表整个函数结束,结束前返回值,函数中只能有一个,生成器中不可以有returnyield:不代表函数结束(只是暂停),返回一个生成器对象(可用next取到其值),函数中可以写多个yield
和return的区别
生成器内部声明了迭代器协议:__iter__ __next__,不需要自己定义
生成器
def person(): def info(): xxxxxxp = person() # 这里只引用了info(),并没有调用,所以info没有运行,此时person()这个函数还是占着内存p() # 这样就运行了info()这个函数,运行完就会释放内存
如果在一个函数中有内层函数如果内层函数没有释放,则外层函数会永远占着内存
>>内部函数的参数为: 10>>30
1.有函数嵌套,一般只嵌套一层2.内部函数引用了外部函数的参数就是当某个函数被当成对象返回时,夹带了外部变量,就形成了一个闭包。可以这样理解,闭包就是能够读取其他函数内部变量的函数。
>>1>>2>>True None None>>True>>2217856965072>>140714178485464
定义一个函数可以理解为:定义了一个全部变量,变量名就是函数名(test)这个test变量指向一个代码块,就是函数就是说test保存了一个代码块的地址,即引用
函数引用
>>6>>7>>51>>52
使用闭包修改函数中的变量nonlocal
闭包(优雅的编程技巧)
装饰器本质上是一个Python函数,它可以让其他函数在不需要做任何代码变动的前提下增加额外功能,装饰器的返回值也是一个函数对象。它经常用于有切面需求的场景,比如:插入日志、性能测试、事务处理、缓存、权限校验等场景。装饰器是解决这类问题的绝佳设计,有了装饰器,我们就可以抽离出大量与函数功能本身无关的雷同代码并继续重用。简单来讲:装饰器的作用就是为已经存在的函数或者对象添加额外的功能。
概念
1.将say_hello这个函数的引用,传递给debug函数(引用:给内存地址,不运行)
2.预读wrapper代码。预读开始
3.发现wrapper函数的返回值是say_hello函数的调用
4.返回wrapper函数的引用。预读结束
5.执行debug(),并传递一个say_hello的函数引用。开始运行
6.debug函数返回的是一个内部函数的引用
print(f'********')
print(‘hello’)
return func(),就是say_hello()
7.sayHello(),调用内部函数wrapper
这段代码的运行流程
>>[DEBUG]: enter say_hello()>>hello
初体验(现在不这么写)
1.say_hello()处,@debug,运行debug
2.将@debug下的函数传给func
3.预读wrapper,返回wrapper的引用
4.say_hello加(),实际上就是调用wrapper函数。>>打印[DEBUG]这段话
5.wrapper返回func(),就是say_hello()。>>打印hello
流程
效果一样,这是最简单的装饰器,被装饰函数无法传参
上面的debug函数其实已经是一个装饰器了,它对原函数做了包装并返回了另外一个函数,额外添加了一些功能。因为这样写实在不太优雅,在后面版本的Python中支持了@语法糖。在不修改say_hello函数原代码的基础上,加一个debug功能。
>>[DEBUG]: enter say()>>hello! lucas
被装饰函数可以传参
万能装饰器(被装饰函数可以有多个参数)
>>info: enter function say()>>hello lucas
终极装饰器(带参数的装饰器)
简单的类装饰器
>>INFO: enter function say()>>say lucas>>INFO: enter function say()>>say lll>>None
带参数的类装饰器
装饰器要求接收一个callable对象,并返回一个callable对象。所以类装饰器中,__init__接收函数,重载__call__()并返回一个函数一个装饰器可以装饰多个函数一个函数可以有多个装饰器(很少用)
类装饰器
装饰器(依赖闭包)
三器一闭
将它赋值给一个变量
拷贝它
为它增加属性
将它作为函数参数进行传递
所以可以对它做一下操作
创建一个类
代码解释
类的本质是个对象,
类是可以动态创建的
实例对象由类对象创建,所以type(实例对象),出来的是对应的类而类对象是由type创建,所以type(类对象),出来的是type。object也是类,所有类都继承于object,但其创建者是type
所有类都继承于object,所有类都是由type创建。object也是由type创建的,type也是由type创建
type函数的第二种用法(自己写函数不要让一个函数有两种完全不同的功能)
定义一个父类
定义一堆方法
将方法和父类放进子类中去
>>住在深圳的lucas同学>>lucas 深圳>>这是一个静态方法>>这是类方法 深圳
实例化后检查子类功能
使用type创建一个类
type
元类创建类,类创建实例对象
函数type实际上是一个元类。type是python在背后用来创建所有类的元类。str是用来创建字符串对象的类int是用来创建整数对象的类type是用来创建类对象的类可以通过__class__属性来看到这一点
元类本身的探究
__metaclass__
元类的主要目的是为了创建类时能够自动地改变类
自定义类
开发中用不到,用于阅读源代码
元类
一个简单的登录系统
输入两个整数算商
try正常运行,出对应异常走except
try--except
只执行一个分支
try--except--except(多个异常)
except后面跟一个元组
多个异常
try内没有异常走else
try--except--else用的不多
报不报错都要跑
try--except--else--finally
as e
捕获异常对象(异常本身信息)
用Exception
不写默认Exception
全捕捉
自定义的异常要继承Exception
例1
先定义一个异常类
在函数中主动抛出异常
调用函数
例2
str_1='d52a733i2327ha244i982d23s553b245'
通过异常捕获获得以下字符串里面的字母字符
自定义异常(用的不多)
处理异常
不加as e
打印出自定义信息
一般不这么用,在except下面加raise
raise
抛出异常
网络请求
文件读写
一般使用场景
https://docs.python.org/zh-cn/3.9/library/exceptions.html#exception-hierarchy
所有异常的基类
BaseException
不知道会有什么异常就用这个
常见异常的基类(父类)
Exception
除(or取模)0,所有数据类型
ZeroDivisionError
序列中没索引
IndexError
映射中没这个键
KeyError
未声明/初始化对象(没有属性)
NameError
语法错误
SyntaxError
传入无效参数
ValueError
常见异常类型
traceback模块
debug shift+F9
pycharm程序调试
异常处理
file_name 变量:是一个包含要访问的文件名称的字符串值。
- 读取 - 默认值。只能读取,如果文件不存在则报错。
'r'
- 追加 - 在原有内容基础上追加内容,在末尾写入,如果不存在则创建该文件。
'a'
- 写入 - 只能写入,如果文件不存在则创建该文件。
'w'
可读可写
‘w+’
- 创建 - 创建指定的文件,如果文件存在则返回错误。
'x'
- 文本 - 默认值。文本模式。
't'
- 二进制 - 二进制模式(例如图像)。
'b'
二进制格式打开一个文件,只读
'rb'
同上,只写
'wb'
同上,追加
'ab'
同上,读写
'wb+'
注意:尽量一次只用一种模式,+模式好像不太好用
access_mode 变量:指打开文件的模式,对应有只读、写入、追加等。access_mode变量值不是必需的(不带access_mode变量时,要求file_name存在,否则报异常),默认的文件访问模式为只读(r)。
buffering:(一般很少用)如果buffering的值被设为0,就不会有寄存;如果buffering的值取1,访问文件时就会寄存行;如果将buffering的值设为大于1的整数,表示这就是寄存区的缓冲大小;如果取负值,寄存区的缓冲大小就是系统默认的值。
内置函数open
E:/zoom/palegechong/图灵/基础语法/文件操作/文档/test.txt
从根文件夹开始
绝对路径
./文档/test.txt
相对于当前工作目录的路径
相对路径
路径
encoding='utf-8',设置编码
打开文件
read()
write()
读一行
readline()
放进列表,每行一个元素
readlines()
writelines()
基本文件操作
如果对文件进行了读写之后,要关闭文件流(close())因为文件读写需要使用计算机资源如果不关容易程序异常,还占系统资源
with open可以自动调用close
with open as f:
文件流操作
文件名这里写路径,不论是绝对路径还是相对路径
os模块
重命名
也是填路径
删除
普通版
fileinput读完一行释放一行内存
fileinput模块
迭代读取
StringIO函数
序列化/反序列化
json模块
前端的字典
JSON
文件操作
基础语法
python笔记
0 条评论
回复 删除
下一页