Python

一、基础语法

1.1 输出函数

1.1.1. set

含义:用来间隔多个值

格式:sep=" "

  • 默认值是一个空格
print("1","2","3",sep="|")

result:1|2|3

1.1.2. end

含义:用来设定以什么结尾

格式:end=" "

  • 默认值是换行符\n
print('123',end=" ")
print("123")

result:123 123

1.2. 数值类型

1.2.1. 布尔型

  • True相当于1,False相当于0
print(True + False)
print(True + 1)

result:1
             2

1.2.2. 复数型

格式:z = a + bj 

  • a是实部,b是虚部,j是虚数单位
a = 1 + 2j
b = 2 + 3j
print(a + b)

result:3+5j

1.3. 字符串 

1.3.1. 字符串编码转换

1.3.1.1. encode 

含义:encode编码

格式:变量名.encode()

a='hello'
a1=a.encode()
print(a1,type(a1))
a='你好'
a1=a.encode("utf-8")
print(a1,type(a1))

result:b'hello' <class 'bytes'>
            b'\xe4\xbd\xa0\xe5\xa5\xbd' <class 'bytes'>

1.3.1.2. decode

含义:decode解码

格式:变量名.decode()

a='hello'
a1=a.encode()
print(a1)
a2=a1.decode()
print(a2,type(a2))

result:b'hello'
            hello <class 'str'>

1.3.2. 字符串常见操作

1.3.2.1. 字符串拼接
a='1'
b='2'
print(a+b)

result:12

1.3.2.2. 字符串多行输出

含义:三引号多行内容输出

格式:"""string"""   

name = """Ni
ko
"""
print(name)

result:Ni
            ko

1.3.2.3. 字符串重复输出 

含义:重复输出

格式:字符*数字

print('没'*3)

result:没没没

1.3.2.4. 成员运算符
1.3.2.4.1. in

含义:如果包含的话,返回True,不包含返回False

格式:字符串 in 变量

name = 'bingbing'
print('bing' in name)
print('aing' in name)

result:True
            False

1.3.2.4.2. not in

含义:not in:如果不包含的话,返回True,包含返回False

格式:字符串 not in 变量

name = 'bingbing'
print('bing' not in name)
print('aing' not in name)

result:False
            True 

1.3.2.5. 切片

格式:[开始位置:结束位置:步长]

  • 包前不包后,步长默认1
st = 'abcdefghijk'
print(st[0:5])
print(st[0:5:2])
print(st[0:])
print(st[0::2])
print(st[:9])
print(st[:9:3])
print(st[-5:])
print(st[-5:-3])
print(st[2:-3])
print(st[:-1])
print(st[-1:])
print(st[-1:-5:-1])

result:abcde
            ace
            abcdefghijk
            acegik
            abcdefghi
            adg
            ghijk
            gh
            cdefgh
            abcdefghij
            k
            kjih

1.3.2.6. find

含义:检查某个字符串是否包含在字符串中

格式:find(子字符串,开始位置下标,结束位置下标)

  • 如果在就返回这个字符串开始位置的下标,否则就返回-1
  • 包前不包后,开始和结束位置下标可以省略
a="bingbing"
print(a.find("b"))
print(a.find("bing"))
print(a.find("b",3))
print(a.find("b",5))
print(a.find("b",3,5))
print(a.find("b",3,4))

result:0
            0
            4
           -1
            4
           -1

1.3.2.7. index

含义:检查某个子字符串是否包含在字符串中,如果在就返回这个字符串开始位置的下标

  • 没找到会报错
a="bingbing"
print(a.index("bin"))

result:0

1.3.2.8. count

含义:在子字符串中出现的次数

格式:count(子字符串,开始位置下标,结束位置下标)

  • 包前不包后
a='bingbing'
print(a.count('b'))

result:2

1.3.2.9. startswith

含义:是否以子字符串开头

格式:startswith(子字符串,开始位置下标,结束位置下标)

  • 是的话就返回True,不是的话就返回False
a='bingbing'
print(a.startswith('bing'))

result:True

1.3.2.10. endswith

含义:是否以子字符串结尾

格式:endswith(子字符串,开始位置下标,结束位置下标)

  • 是的话就返回True,不是的话就返回False
a='bingbing'
print(a.endswith('bing'))

result:True

1.3.2.11 . isupper

含义:检测字符串中所有的字符是否都为大写

格式:变量名.isupper()

  • 是的话就返回True,不是就为False
a='bingBing'
print(a.isupper())

result:False

1.3.2.12. replace

含义:替换内容

格式:replace(旧内容,新内容,替换次数)

  • 默认全部替换
a='好好学习,天天向上'
print(a.replace('天','好'))
print(a.replace('天','好',1))

result:好好学习,好好向上
            好好学习,好天向上

1.3.2.13. split

含义:指定分隔符来切分字符串

格式:split(字符,次数)

  • 可以指定次数
  • 如果字符串中不包含分割内容,就不进行分割,会作为一个整体。
a='hello,python'
print(a.split(','))
print(a.split('o'))
print(a.split('o',1))
print(a.split('a'))

result:['hello', 'python']
            ['hell', ',pyth', 'n']
            ['hell', ',python']
            ['hello,python']

1.3.2.14. capitalize

含义:第一个字符大写,其他全是小写

格式:变量名.capitalize()

a='sagapoHH'
print(a.capitalize())

result:Sagapohh

1.3.2.15. lower

含义:lower 大写字母转小写

格式:变量名.lower()

a='SAGAPOHH'
print(a.lower())

result:sagapohh

 1.3.2.16. upper 

含义:upper 小写字母转大写

格式:变量名.upper()

a='sagapohh'
print(a.upper())

result:SAGAPOHH

1.4. 格式化输出

1.4.1. 占位符

1.4.1.1. %s 

含义:%s 字符串占位符

name = "Mico"
print("name = %s" % name)

result:name = Mico

1.4.1.2. %d

含义:%d 整数占位符

age = 18
height = 180
print("height = %s,age = %d" % (height,age))

result:height = 180,age = 18 

1.4.1.3. %4d 

含义:%4d 整数占位符,数字设置位数

  • 不足前面默认补空白
  • 在数字前加0,不足用0补全
age = 1
print("age = %4d" % age)
print("age = %04d" % age)

result:age =       1
            age = 0001

1.4.1.4. %f

含义:%.f 浮点数占位符

  • 默认六位小数
  • 不足后面补0,遵循四舍五入原则
a = 1.23456
print("a = %f" % a)

result:a = 1.234560

1.4.1.5. %.4f 

含义:%.4f 数字设置小数位数

  • 遵循四舍五入原则
a = 1.23456
print("a = %.4f" % a)

result:a = 1.2346

1.4.1.6. %%
print("我是%%的%%" % ())

result:我是%的%

1.4.2. f格式化

格式:f"{表达式}"

print(f"my name is {name},age is {age}")

result:my name is Mico,age is 1

1.5. 算数运算符

1.5.1. /

含义:商

  • 一定是浮点数,除数不为0
a = 4 / 2
print(a)

result:2.0

1.5.2. //

  • 取商的整数部分,向下取整(不管四舍五入的规则,只要后面有小数,就忽略小数)
a = 4 // 3
print(a)

result:1

1.5.3. %

含义:取余数

a = 6 % 4
print(a)

result:2

1.5.4. **

含义:幂次方

  • m**n:m的n次方
a = 3
b = 2
print(b**a)

result:8

1.6. 运算符优先级

  • 幂(最高优先级) > 乘、除、取余、取整数 > 加减
print(3**2+5//2)

result:11

1.7. 输入函数 input

含义:输入函数,默认是字符串类型

格式:input()

name = input("请输入:")
print(name)

result:请输入:mico
             mico

1.8. 转义字符

1.8.1. \r

含义:\r 回车 表示将当前位置移到本行开头

  • 前面的数据就没有了
print("dsfs\rads")

result:ads

1.8.2. r'string'

含义:表示引号内部的字符默认不转义

print(r'abc\\\sda')

result:abc\\\sda

1.9. if判断

1.9.1. if语句

age = 18
if age < 20:
    print("不可以结婚")

result:不可以结婚

1.9.2. not

含义:表示相反的结果

print(not 3>9)

result:True

1.9.3. if else

a=3
b=5
print("a比b大")if a>b else print("a比b小")

result:a比b小

1.9.4. if elif else

score = 80
if 85<=score<=100:
    print('优秀')
elif 60<=score<85:
    print("及格")
else:
    print("不及格")

result:不及格 

1.10. 循环语句 while

格式:while 条件 :

i =1
while i<5 :
    print("hi")
    i+=1

result:hi
            hi
            hi
            hi

1.11. 列表

1.11.1. 列表的基本格式

格式:列表名 = [元素1,元素2,元素3]

li=[1,2,'a',4]
print(li)
print(li[0:3])
for i in li:
    print(i)

result:[1, 2, 'a', 4]
            [1, 2, 'a']
            1
            2
            a
            4

1.11.2. 列表的常见操作

1.11.2.1. 添加元素
1.11.2.1.1. append

含义:append列表元素整体添加

格式:列表名.append()

li=[1,2,'a',4]
li.append('five')
print(li)

result:[1, 2, 'a', 4, 'five']

1.11.2.1.2. extend

含义:extend分散添加

格式:列表名.extend()

  • extend只能添加可迭代对象(列表,字符串)
li=[1,2,'a',4]
li.extend('six')
print(li)

result:[1, 2, 'a', 4, 's', 'i', 'x']

1.11.2.1.3. insert

含义:在指定位置插入元素

格式:列表名.insert()

  • 指定位置如果有元素,原元素后移
li = [1,2,3]
li.insert(3,4)
print(li)
li.insert(0,-1)
print(li)

result:[1, 2, 3, 4]
            [-1, 1, 2, 3, 4]

1.11.2.2. 修改列表元素

方法:通过下标修改

格式:列表名[下标] = 值

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

result:[1, 2, 'a']

1.11.2.3. 查找列表元素

方法:通过in、not in 查找

a=[1,2,3]
print('1' in a)
print('1' not in a)

result:False
            True

1.11.2.4. 删除列表元素
1.11.2.4.1. del 

含义:删除列表元素,根据下表删除

格式:del 列表名[下标]

li=['a','b','c','d']
del li[2]
print(li)

result:['a', 'b', 'd']

1.11.2.4.2. pop

含义:默认删除最后一个元素

格式:pop 列表名[下标]

li=['a','b','c','d']
li.pop(2)
print(li)

result:['a', 'b', 'd']

1.11.2.4.3. remove

含义:删除列表元素,根据元素删除

格式:列表名.remove()

li=['a','b','c','a']
li.remove('a')
print(li)

result:['b', 'c', 'a']

1.11.2.5. 排序列表元素
1.11.2.5.1. sort 

含义:从小到大排序

格式:列表名.sort()

li = ['78','23','61','6','35']
li.sort()
print(li)

result:['23', '35', '6', '61', '78']

1.11.2.5.2. reverse

含义:倒序排序

格式:列表名.reverse()

li = ['78','23','61','6','35']
li.reverse()
print(li)

result:['35', '6', '61', '23', '78']

先sort后reverse:从小到大

li = ['78','23','61','6','35']
li.sort()
li.reverse()
print(li)

result:['78', '61', '6', '35', '23']

1.11.3. 列表推导式

1.11.3.1. [表达式 for 变量 in 列表]

格式:[表达式 for 变量 in 列表]

  • in后面可以放列表,还可以放range()、可迭代对象
li = [1,2,3,4,5]
[print(i,end="") for i in li]
print('')
[print(i,end="") for i in range(1,6)]
print('')
li=[]
[li.append(i) for i in range(1,6)]
print(li)

result:12345
            12345
            [1, 2, 3, 4, 5]

1.11.3.2. [表达式 for 变量 in 列表 if条件]

格式:[表达式 for 变量 in 列表 if条件]

在1到11中找出奇数添加到 li 列表中

li=[]
[li.append(i) for i in range(1,11) if i % 2 == 1]
print(li)

result:[1, 3, 5, 7, 9] 

1.11.4. 列表嵌套

li=[1,2,3,[4,5,6]]
print(li[3])
print(li[3][2])

result:[4, 5, 6]
             6

1.12. 元组

1.12.1. 元组的基本格式

格式:元组名 = (元素1,元素2,元素3...)

  • 不同元素也可以是不同数据类型
  • 可以定义空元组
  • 只有一个元素的时候,末尾必须加上逗号,否则返回唯一的值的数据类型
tup=(1,'a',1.3,[1,'a',1.3])
print(type(tup))
tup=()
print(type(tup))
tup=(1,)
print(type(tup))
tup=(1)
print(type(tup))

result:  <class 'tuple'>
            <class 'tuple'>
            <class 'tuple'>
            <class 'int'>

1.12.2. 元组与列表的区别

  • 元组只有一个元素末尾时必须加逗号,列表不需要
  • 元祖只支持查询操作,不支持怎删改操作
  • count、index、len、[] 跟列表的用法相同
li=[1]
print(type(li))
tup=(1,2,3,1)
print(tup[2])
print(tup.count(1))
print(tup.index(2))
print(len(tup))
print(tup[1:])

result:<class 'list'>
            3
            2
            1
            4
            (2, 3, 1)

1.12.3. 元组的应用场景

  • 函数的参数和返回值
  • 格式化输出后面的()本质上就是一个元组
  • 数据不可被修改,保护数据的安全
name ='bingbing'
age = 18
print('%s的年龄是%d' % (name,age))
info = (name,age)
print(type(info))
print('%s的年龄是%d' % info)

result:bingbing的年龄是18
            <class 'tuple'>
            bingbing的年龄是18

1.13. 字典

1.13.1. 字典的基本格式

格式:字典名 = {键1:值1,键2:值2...}

  • 字典中的键具备唯一性,键名重复前面的值会被后面的值替代
  • 字典中的值可以重复
dic = {'name':'bing','age':18}
print(type(dic))
dic1 = {'name':'bingbing','name':'susu'}
print(dic1)
dic2 = {'name1':'bingbing','name2':'bingbing'}
print(dic2)

result:<class 'dict'>
            {'name': 'susu'}
            {'name1': 'bingbing', 'name2': 'bingbing'}

1.13.2. 字典的常见操作

1.13.2.1.  查看字典元素
1.13.2.1.1. 变量名[键名]

格式:变量名[键名]

  • 不可根据下标查找元素,需要根据键名查找
dic = {'name':'bingbing','age':18}
print(dic['name'])

result:bingbing

1.13.2.1.2. 变量名.get(键名)

格式:变量名.get(键名)

  • 键名不存在返回自己设置的值,默认是None
dic = {'name':'bingbing','age':18}
print(dic.get('name'))
print(dic.get('sex'))
print(dic.get('sex','性别不存在'))

result:bingbing
            None
            性别不存在

1.13.2.2. 修改字典元素

格式:变量名[键名] = 值

dic = {'name':'bingbing','age':18}
dic['name'] = 'susu'
print(dic)

result:{'name': 'susu', 'age': 18}

1.13.2.3. 添加字典元素

格式:变量名[键名] = 值

dic = {'name':'bingbing','age':18}
dic['sex'] = '男'
print(dic)

result:{'name': 'bingbing', 'age': 18, 'sex': '男'}

1.13.2.4. 删除字典

格式:del 字典名

dic = {'name':'bingbing','age':18}
del dic
1.13.2.5. 删除字典元素

格式:del 字典名[键名]

dic = {'name':'bingbing','age':18}
del dic['name']
print(dic)

result:{'age': 18}

1.13.2.6. clear

含义:清空整个字典里面的东西,但保留了这个字典

格式:字典名.clear()

dic = {'name':'bingbing','age':18}
dic.clear()
print(dic)

result:{}

1.13.2.7. pop

含义:删除指定键值对

格式:字典名.pop()

dic = {'name':'bingbing','age':18}
dic.pop('name')
print(dic)

result:{'age': 18}

1.13.2.8. popitem

含义:删除键值对

格式:字典名.popitem()

  • 3.7版本以前随机删除一个键值对,3.7版本之后删除最后一个元素
dic = {'name':'bingbing','age':18}
dic.popitem()
print(dic)

result:{'name': 'bingbing'}

1.13.2.9. len

含义:求长度

格式:len(变量名)

dic = {'name':'bingbing','age':18}
tup = (1,2,'a')
li = [1,2,3,4]
str = 'hello'
print(len(dic),len(tup),len(li),len(str))

result:2 3 4 5

1.13.2.10. keys

含义:返回字典里面包含的所有键名

格式:变量名.keys()

  • 可以用for循环取出
dic = {'name':'bingbing','age':18}
a= dic.keys()
print(type(a))
print(dic.keys())
for i in a:
    print(i,end=' ')

result:<class 'dict_keys'>
            dict_keys(['name', 'age'])
            name age 

1.13.2.11. values

含义:返回字典里面包含的所有值

格式:变量名.values()

  • 可以用for循环取出
dic = {'name':'bingbing','age':18}
a= dic.values()
print(type(a))
print(dic.values())
for i in a:
    print(i,end=' ')

result:<class 'dict_values'>
            dict_values(['bingbing', 18])
            bingbing 18 

1.13.2.12. item

含义:返回字典里包含的所有键值对,键值对以元组形式返回

格式:变量名.items()

  • 可以用for循环取出
dic = {'name':'bingbing','age':18}
a= dic.items()
print(type(a))
print(dic.items())
for i in a:
    print(i,end=' ')
print()
print(type(i))

result:<class 'dict_items'>
            dict_items([('name', 'bingbing'), ('age', 18)])
            ('name', 'bingbing') ('age', 18) 
            <class 'tuple'>

1.14. 集合

1.14.1. 集合的基本格式

格式:集合名 = {元素1,元素2.,元素3...}

s1 = {1,2,3}
print(type(s1))
print(s1)

result:<class 'set'>
            {1, 2, 3}

1.14.2. 空集合的定义

格式:变量名 = set()

s1 = {}
print(type(s1))
s1 = set()
print(type(s1))

result:<class 'dict'>
            <class 'set'>

1.14.3. 集合具有无序性

  • 每次运行的结果都不一样
s1 = {'a','b','c','d','e'}
print(s1)

result:{'d', 'b', 'a', 'e', 'c'}

result:{'b', 'c', 'd', 'a', 'e'}

result:{'d', 'e', 'c', 'b', 'a'}

  • 集合数字运行结果一样,并且从小到大排列
s1 = {2,4,9,1,6}
print(s1)

result:{1, 2, 4, 6, 9} 

result:{1, 2, 4, 6, 9} 

result:{1, 2, 4, 6, 9} 

1.14.4. 集合无序的实现方法涉及hash表(了解)

  • 每次运行结果不同:python中string字符串型的hash值不同,那么在hash表中的位置也不同,                                  所以才有集合的无序性

注:因此不能查询、修改集合中的值(都不知道修改哪一个),只能添加、删除

print(hash('a'))

result:6186969021618527376

result:1374242042952206087

result:6186969021618527376

  • 每次运行结果相同:python中int整型的hash值相同,那么在hash表中的位置也相同,所以才                                  顺序不会发生改变
print(hash(1))

result:1

result:1

result:1

1.14.5. 集合具有唯一性

含义:可以自动去除

s1 = {1,1,3,7,7,9,4}
print(s1)

result:{1, 3, 4, 7, 9}

1.14.6. 集合的基本操作

1.14.6.1. add

含义:集合的添加

格式:集合名.add(元素)

  • add添加的是一个整体,一次只能添加一个元素(元组可以作为一个元素)
s1 = {1,2,3,4}
s1.add(5)
s1.add((7,8))
print(s1)

result:{1, 2, 3, 4, 5, (7, 8)}

1.14.6.2. update

含义:把传入的元素拆分,一个个放进集合当中

格式:集合名.update(元素)

  • 元素必须是能够被for循环的可迭代对象
s1 = {1,2,3,4}
s1.update('56')
s1.update([7,8])
s1.update((9,10))
s1.update({11,12})
s1.update({'name':'mico'},{'age':'18'})
print(s1)

result:{1, 2, 3, 4, '6', 'name', 7, 8, 9, 10, 11, 12, 'age', '5'}

1.14.6.3. remove

含义:删除集合元素,元素没有则会报错

格式:变量名.remove(元素)

s1 = {1,2,3,4}
s1.remove(1)
print(s1)

result:{2, 3, 4}

1.14.6.4. pop

含义:集合删除

格式:变量名.pop()

s1 = {'a','b','c','d'}
print(s1)
s1.pop()
print(s1)

result:{'c', 'b', 'a', 'd'}
            {'b', 'a', 'd'}

1.14.6.5. discard

含义:选择要删除的元素,有的会删除,没有则不会发生任何改变

格式:变量名.discard(元素)

s1 = {1,2,3,4}
s1.discard(4)
print(s1)
s1.discard(5)
print(s1)

result:{1, 2, 3}
            {1, 2, 3}

1.14.7. 交集

格式:a & b

  • 没有交集返回空集合
a = {1,2,3,4}
b = {3,4}
print(a & b)
a = {1,2,3,4}
b = {5,6}
print(a & b)

result:{3, 4}
             set()

1.14.8. 并集

格式:a | b

a = {1,2,3,4}
b = {3,4,5,6}
print(a | b)

result:{1, 2, 3, 4, 5, 6}

1.15. 类型转换

1.15.1. int()

含义:转换为一个整型

格式:int()

  • 浮点型强转整形会去掉小数点及后面的数值,只保留整数部分
  • 只能转换由数字组成的字符串
a = 1.2
b = int(a)
print(b,type(b))
c = '123'
d = int(c)
print(d,type(d))

result:1 <class 'int'>
            123 <class 'int'>

1.15.2. float()

含义:转换为一个浮点型

格式:float()

  • 整型转换为浮点型,会自动添加一位小数
  • 只能转换由数字组成的字符串
a = 1
b = float(a)
print(b,type(b))
c = '123'
d = float(c)
print(d,type(d))

result:1.0 <class 'float'>
            123.0 <class 'float'>

1.15.3. str()

含义:转换为一个字符串型

格式:str()

  • 任何类型都可以转换成字符串类型
  • float转换成str会取出末位为0的小数部分
num = 123
str_num = str(num)
print(str_num,type(str_num))
li = [1,2,3]
str_li = str(li)
print(str_li,type(str_li))
fl = 1.80
str_fl = str(fl)
print(str_fl,type(str_fl))

result:123 <class 'str'>
             [1, 2, 3] <class 'str'>
             1.8 <class 'str'>

1.15.4. eval

含义:执行一个字符串表达式,并返回表达式的值

格式:eval('表达式')

  • 整型与字符串不可以相加
  • 可以实现list、dict、tuple、str之间的转换
  • 不够安全,容易被恶意修改数据,不建议使用
st = '10+10'
eval_st = eval(st)
print(eval_st,type(eval_st))
#实现字符串与列表转换
str_li = '[[1,2],[3,4],[5,6]]'
eval_li = eval(str_li)
print(eval_li,type(eval_li))
#实现字符串与元组转换
str_tup = "(1,2,'a')"
eval_tup = eval(str_tup)
print(eval_tup,type(eval_tup))
#实现字符串与字典转换
str_dict = "{'name':'bing','age':18}"
eval_dict = eval(str_dict)
print(eval_dict,type(eval_dict))

result:20 <class 'int'>
            [[1, 2], [3, 4], [5, 6]] <class 'list'>
            (1, 2, 'a') <class 'tuple'>
            {'name': 'bing', 'age': 18} <class 'dict'>

1.15.5. list

含义:将可迭代对象转换成列表

格式:list(变量名)

  • 支持转换为list的类型:str、tuple、dict、set
  • 字典转换成列表,会取键名作为列表的值
#字符串转列表
st = '123'
list_st = list(st)
print(list_st,type(list_st))
#元组转列表
tup = (1,2,'a')
list_tup = list(tup)
print(list_tup,type(list_tup))
#集合转列表
se = {'a','b','c','b'}
list_set = list(se)
print(list_set,type(list_set))
#字典转列表
dic = {'name':'bing','age':18}
list_dic = list(dic)
print(list_dic,type(list_dic))

result:['1', '2', '3'] <class 'list'>
            [1, 2, 'a'] <class 'list'>
            ['b', 'c', 'a'] <class 'list'>
            ['name', 'age'] <class 'list'>

1.16. 深浅拷贝

1.16.1. id

含义:查看内存地址

格式:id(变量名)

st = 'abc'
print(id(st))

result:2342672860808

1.16.2. 赋值

  • 等于完全共享资源,一个值改变会完全被另一个值共享
li1=[1,2,3]
li2 = li1
li2.append(4)
print(li1)
print(li2)
print('str1地址:',id(li1))
print('str2地址:',id(li2))

result:[1, 2, 3, 4]
            [1, 2, 3, 4]
            str1地址: 1689620828104
            str2地址: 1689620828104

1.16.3. 浅拷贝(可变对象)

含义:会创建新的对象,拷贝第一层的数据

格式:copy.copy(变量名)

  • 嵌套层会指向原来的内存地址
#会创建新的对象,拷贝第一层的数据
li1=[1,2,3,[4,5]]
li2 = copy.copy(li1)
li2.append(4)
print(li1)
print(li2)
print('str1地址:',id(li1))
print('str2地址:',id(li2))

#嵌套层会指向原来的内存地址
li2[3].append(6)
print(li1)
print(li2)
print('str1[3]地址',id(li1[3]))
print('str1[3]地址',id(li2[3]))

result:[1, 2, 3, [4, 5]]
            [1, 2, 3, [4, 5], 4]
            str1地址: 1689626021128
            str2地址: 1689626090632
            [1, 2, 3, [4, 5, 6]]
            [1, 2, 3, [4, 5, 6], 4]
            str1[3]地址 1689626090568
            str1[3]地址 1689626090568

1.16.4. 深拷贝(可变对象)

含义:外层的对象和内部的元素都拷贝了一遍

格式:copy.deepcopy(变量名)

li1 = [1,2,3,[4,5,6]]
li2 = copy.deepcopy(li1)
li2[3].append(7)
li2.append(8)
print(li1,'     ',id(li1),id(li1[3]))
print(li2,id(li2),id(li2[3]))

result:[1, 2, 3, [4, 5, 6]]         1627738016776 1627736428296
            [1, 2, 3, [4, 5, 6, 7], 8] 1627737951688 1627738016712

1.16.5. 可变类型

含义:变量对应的值可以修改,但是内存地址不会发生改变

  • 常见的可变类型:list、dict、set

1.16.6. 不可变类型

含义:存储空间保存的数据不可以被修改,如果被修改就会生成一个新的值从而分配新的内存空间

  • 常见的不可变类型:数值类型(int、bool、float、complex)、字符串、元组

1.17. 函数基础

1.17.1. 函数

定义:def 函数名():
                 函数体
调用:函数名():

1.17.2. 返回值

1.17.2.1. return
  • 会给函数的执行者返回值
  • 函数中遇到return,表示此函数结束,不继续执行
  • return返回多个值,以元组的形式返回给调用者
  • 没有返回值,默认None
def buy():
    return '西瓜',2
    return 20
print(buy())

result:('西瓜', 2)

1.17.2.2. return和print的区别
  • return表示此函数结束,print会一直执行
  • return是返回计算值,print是打印结果

1.17.3. 函数参数

1.17.3.1. 参数的基本格式

定义:def 函数名(形参a,形参b):
           函数体
           ...(如a = 1 b = 2)
调用:函数名(实参1,实参2)

1.17.3.2. 必备参数(位置参数)

含义:传递和定义参数的顺序及个数必须一致

1.17.3.3. 默认参数

含义:为参数提供默认值,调用函数时可不传该默认参数的值

  • 所有的必备参数(位置参数)必须出现在默认参数前,包括函数定义和调用
def function(a = 1,b=2):
    print(a,b)
function()
function(200)

result:1 2
             200 2   
         

1.17.3.4. 可变参数  

含义:传入的值的数量是可以改变的,可以传入多个,也可以不传

格式:def 函数名(*args)

  • 以元组的形式接收
def func(*args):
    print(args)
    print(type(args))
func('niko','simple','monesy')

result:('niko', 'simple', 'monesy')
             <class 'tuple'>

1.17.3.5. 关键字参数

含义:可以扩展函数的功能

格式:def func(**kwargs)

def func(**kwargs):
    print(kwargs)
    print(type(kwargs))
func(name='niko',age=18)

result:{'name': 'niko', 'age': 18}
             <class 'dict'>

1.17.4. 函数嵌套

含义:在函数中调用函数

def study():
    print('study')
def course():
    study()
    print('math')
study()
course()

result:study
            study
            math

1.17.5. 嵌套定义

含义:在一个函数中定义另外一个函数

def course():
    print('python')
    def study():
        print('English')
    study()
course()

result:python
            English

1.17.6. global

含义:在函数内部修改为全局变量的值

格式:global 变量名,变量名,...

def study():
    global name
    name = 'python'
    print(f"study:{name}")
study()
print(name)

result:study:python
            python

1.17.7. nonlocal

含义:用来声明外层的局部变量,只对上一级变量进行修改

格式:nonlocal 变量名,变量名,...

  • 只能在嵌套函数中使用
def outer1():
    a = 1
    def inner1():
        a = 2
        def inner2():
            nonlocal a
            a = 3
            print('inner2:',a)
        inner2()
        print('inner1:',a)
    inner1()
    print('outer1:',a)
outer1()

result:inner2: 3
            inner1: 3
            outer1: 1

1.17.8. lambda

定义:函数名 = lambda 形参 :返回值(表达式)

调用:结果 = 函数名(实参)

add = lambda a,b : a + b
print(add(1,2))

result:3

1.17.9. lambda的参数形式

  • 无参数:返回的就是返回值
  • 必备参数:返回传入参数
  • 默认参数:默认参数必须放非默认值后面,多个参数返回值要用元组
  • 可变参数:以元组的形式接收
  • 关键字参数:以字典的形式接收
#无参
Wushen = lambda : "Wushen"
print(Wushen())
#必备参数
Essential_parameters = lambda name: name
print(Essential_parameters('Niko'))
#默认参数
Default_parameters = lambda name,age = 18 : (name,age)
print(Default_parameters('Niko'))
print(Default_parameters('Niko',20))
#可变参数
Variable_parameters = lambda *args : args
print(Variable_parameters('Niko','Simple'))
#关键字参数
Keyword_parameters = lambda **kwargs : kwargs
print(Keyword_parameters(name='Niko',age='18'))

result:Wushen
            Niko
            ('Niko', 18)
            ('Niko', 20)
            ('Niko', 'Simple')
            {'name': 'Niko', 'age': '18'}

1.17.10. lambda结合if

  • 只能实现简单的逻辑,如果逻辑复杂且代码量较大,不建议使用lambda,降低代码的可读性,为后期的代码维护增加成本
combine = lambda a,b:'a比b大' if a>b else 'a比b小'
print(combine(5,6))

result:a比b小

1.17.11. 内置函数

1.17.11.1. 查看内置函数

格式:dir(builtins)

  • 大写字母开头一般是内置常量名,小写字母开头一般是内置函数名
print(dir(builtins))

result:['ArithmeticError', 'AssertionError', 'AttributeError', 'BaseException', 'BlockingIOError',                    'BrokenPipeError', 'BufferError', 'BytesWarning', 'ChildProcessError',                                                'ConnectionAbortedError', 'ConnectionError', 'ConnectionRefusedError',                                          'ConnectionResetError', 'DeprecationWarning', 'EOFError', 'Ellipsis', 'EnvironmentError',                'Exception', 'False', 'FileExistsError', 'FileNotFoundError', 'FloatingPointError',                                'FutureWarning', 'GeneratorExit', 'IOError', 'ImportError', 'ImportWarning',                                        'IndentationError', 'IndexError', 'InterruptedError', 'IsADirectoryError', 'KeyError',                              'KeyboardInterrupt', 'LookupError', 'MemoryError', 'ModuleNotFoundError', 'NameError',                'None', 'NotADirectoryError', 'NotImplemented', 'NotImplementedError', 'OSError',                          'OverflowError', 'PendingDeprecationWarning', 'PermissionError', 'ProcessLookupError',                'RecursionError', 'ReferenceError', 'ResourceWarning', 'RuntimeError', 'RuntimeWarning',              'StopAsyncIteration', 'StopIteration', 'SyntaxError', 'SyntaxWarning', 'SystemError',                          'SystemExit', 'TabError', 'TimeoutError', 'True', 'TypeError', 'UnboundLocalError',                              'UnicodeDecodeError', 'UnicodeEncodeError', 'UnicodeError', 'UnicodeTranslateError',                  'UnicodeWarning', 'UserWarning', 'ValueError', 'Warning', 'WindowsError',                                        'ZeroDivisionError', '__build_class__', '__debug__', '__doc__', '__import__', '__loader__',              '__name__', '__package__', '__spec__', 'abs', 'all', 'any', 'ascii', 'bin', 'bool', 'breakpoint',                  'bytearray', 'bytes', 'callable', 'chr', 'classmethod', 'compile', 'complex', 'copyright', 'credits',              'delattr', 'dict', 'dir', 'divmod', 'enumerate', 'eval', 'exec', 'exit', 'filter', 'float', 'format',                            'frozenset', 'getattr', 'globals', 'hasattr', 'hash', 'help', 'hex', 'id', 'input', 'int', 'isinstance',                    'issubclass', 'iter', 'len', 'license', 'list', 'locals', 'map', 'max', 'memoryview', 'min', 'next',                      'object', 'oct', 'open', 'ord', 'pow', 'print', 'property', 'quit', 'range', 'repr', 'reversed', 'round',                'set', 'setattr', 'slice', 'sorted', 'staticmethod', 'str', 'sum', 'super', 'tuple', 'type', 'vars', 'zip']

1.17.11.2. abs

含义:返回绝对值

格式:abs()

print(abs(-12))

result:12

1.17.11.3. sum

含义:求和

格式:sum()

  • sum要放可迭代对象,如列表、元组、集合
  • 字符串不可以进行相加
print(sum([1,2,3]))
print(sum((1,2,3)))
print(sum({1,2,3}))

result:6
            6
            6

1.17.11.4. min

含义:最小值

  • 可以放可迭代对象
  • 传入了绝对值函数,则参数就会先求绝对值再取结果
print(min(1,2,3))
print(min(-7,-8,-9,key=abs))

result:1
            -7

1.17.11.5. max

含义:最大值

  • 可以放可迭代对象
  • 传入了绝对值函数,则参数就会先求绝对值再取结果
print(max(1,2,3))
print(max(1,2,-4,key=abs))

result:3
            -4

1.17.11.6. zip

含义:将可迭代对象作为参数,将对象中对应的元素打包成一个个元组

格式:zip()

  • 可以通过for循环取出
  • 如果元素个数不一致,就按照长度最短的返回
  • 可以转换成列表打印
li =[1,2,3]
tup = ('a','b')
print(type(zip(li,tup)))
print(zip(li,tup))
for i in zip(li,tup):
    print(i)
print(list(zip(li,tup)))

result:<class 'zip'>
            <zip object at 0x000002A634D87AC8>
            (1, 'a')
            (2, 'b')
            [(1, 'a'), (2, 'b')]

1.17.11.7. map

含义:可以对可迭代对象中的每一个元素进行映射,分别去执行

格式:map(func,iter1)

  • func--自己定义的函数,iter1--要放进去的可迭代对象
  • 可以通过for循环取出
  • 可以转换成列表打印
funa = lambda x : x + 5
li = [1,2,3]
mp = map(funa,li)
print(type(mp))
print(mp)
for i in mp:
    print(i)
print(list(map(funa,li)))

result:<class 'map'>
            <map object at 0x000001E2D64F1860>
            6
            7
            8
            [6, 7, 8]

1.17.11.8. reduce

含义:先把对象中的两个元素取出,计算出一个值然后保存着,接下来把计算值跟第三个元素进               行计算

格式:reduce(function,sequence)

  • function--函数:必须有两个参数的函数,sequence--序列:可迭代对象
li = [1,2,3,4]
funa = lambda x,y : x + 2 * y
re = reduce(funa,li) # 1+2*2=5,5+2*3=11,11+2*4=19
print(re)

result:19

1.17.12. 拆包

含义:对于函数中的多个返回数据,去掉元组,列表或者字典直接获取里面的数据的过程

  • 要求元组内的个数与接收的变量个数相同,对象内有多少个数据就需要定义多少个变量接收
  • 先把单独的取完,其它剩下的全部交给带*的变量
tup = (1,2,3)
a,b,c = tup
print(a,b,c)
#方法二
a,*b = tup
print(a,b)

result:1 2 3
            1 [2, 3]

二、异常、模块和包

2.1. 异常

2.1.1. 常见异常种类

  • NameError:使用一个还未被赋值的变量
  • SyntaxError:代码不符合python语法规定
  • IndexError:下标/索引超出范围
  • ZeroDivisionError:除数为0
  • keyError:字典里不存在这个键
  • IOError:输入/输出操作失败,基本上是无法打开文件(比如你要读的文件不存在)
  • AttributeError:对象没有这个属性
  • ValueError:传入的值有错误
  • TypeError:类型错误,传入的类型不匹配
  • ImportError:无法引入模块或包;基本上是路径错误或名称错误
  • IndentationError:缩进错误;代码没有正确对齐

2.1.2. 异常处理(捕获异常)

2.1.2.1. try except:

格式:try:
                      可能引发异常现象的代码(检测的代码块)
               except 异常类型(可写可不写):
                      出现异常现象的处理代码

  • 可以声明捕获异常类型,但是遇到其他异常类型依然会报错,无法捕获异常
  • 当要捕获多个异常类型时,可把要捕获的异常类型的名字放到except后,并以元组的形式编写
  • Exception万能异常,可以捕获任意异常类型
  • as相当于取别名,可以打印出异常信息
try:
    print(abc)
except (NameError,SyntaxError):
    print('异常1')
try:
    print(abc)
except Exception:
    print('异常2')
try:
    print(abc)
except Exception as e:
    print('异常3')
    print(e)

result:异常1
            异常2
            异常3
            name 'abc' is not defined

2.1.2.2. try except else:

 格式:try:
                     可能引发异常现象的代码
                except:
                     出现异常现象的处理代码
                else:
                     没有捕获到异常执行的代码

try:
    print('abc')
except Exception:
    print('异常')
else:
    print('这里是else')

result:abc
            这里是else

2.1.2.3. try except else finally:

 格式:try:
                     可能引发异常现象的代码
                except:
                     现异常现象的处理代码
                else:
                     没有捕获到异常执行的代码
                finally:
                     try代码块结束后运行的代码

  • finally不管怎样都会被执行
  • 可以单独使用try...finally...,也可以配合except等使用

2.1.3. raise

含义:自定义异常信息

格式:raise Exception('xxx'),xxx--异常信息

def funa():
    pwd = input('输入密码:')
    length = len(pwd)
    if len(pwd) >= 6:
        return '密码输入成功'
    raise Exception('密码长度小于6位')
try:
    print(funa())
except Exception as e:
    print(e)
print(123)

result:输入密码:123
            密码长度小于6位
            123

2.2. 模块

2.2.1. 模块的定义

含义:一个py文件就是一个模块,即导入一个模块本质上就是执行一个py文件

  • 内置模块:random、time、os、logging,直接导入即可使用
  • 第三方模块:cmd窗口pip install 模块名
  • 自定义模块:自己在项目中定义的模块

注意:自定义模块命名要遵循标识符规定以及变量的命名规范,并且不要与内置模块起冲突,否则将导致模块功能无法使用

2.2.2. 导入模块

2.2.2.1. 导入指定模块

格式:import 模块名

调用:模块名.功能名

#创建test.py
print('这是test')
name = 'Niko'
def funa():
    print('这是funa')
#在主模块导入自定义的test模块,调用其中的功能
import test
print(test.name)
test.funa()

result:这是test
            Niko
            这是funa

2.2.2.2. 从模块中导入指定的部分

格式:from 模块名 import 功能1,功能2...

调用:功能名

  • 调用功能直接输入功能即可,不需要添加模块名
  • 没有导入就会报错
from test import name,funa
funa()
print(name)

result:这是test
            这是funa
            Niko

2.2.2.3. 把模块中的所有内容全部导入

格式:from 模块名 import *

调用:功能名

from test import *
funa()
print(name)

result:这是test
            这是funa
            Niko

2.2.2.4. 给模块起别名

格式:import 模块名 as 别名 

调用:别名.功能名 , 功能名

import test as t
print(t.name)
t.funa()

result:这是test
            Niko
            这是funa

2.2.2.5. 给功能起别名

格式:from 模块名 import 功能 as 别名

调用:功能名

from test import funa as f,name as n
f()
print(n)

result:这是test
            这是funa
            Niko

2.2.3. 内置全局变量__name__

2.2.3.1.  if __name__ == "__main__":

含义:用来控制py文件在不同的应用场景执行不同的逻辑

格式:if __name__ == "__main__":

  • 文件在当前程序执行(即自己执行自己):__name__ == "__main__":
#在test.py文件中
print('这是test')
name = 'Niko'
def funa():
    print('这是funa')
if __name__ == '__main__':
    print('这是main')

result:这是test
            这是main

  • 文件被当做模块被其他文件导入则不会执行main中的代码
#在all.py文件中
import test
test.funa()

result:这是test
            这是funa

2.2.3.2. if __name__ == '模块名':

格式:if __name__ == '模块名':

  • 文件被当做模块被其他文件导入:__name__ == '模块名':
#在test.py文件中
print('这是test1')
name = 'Niko'
def funa():
    print('这是funa')
if __name__ == 'test':
    print('这是test2')

result:这是test1

  •  文件被当做模块被其他文件导入则会执行模块中的代码
#在all.py文件中
import test
test.funa()

result:这是test1
            这是test2
            这是funa

2.3. 包 

2.3.1. 包的定义

含义:就是项目结构中的文件夹/目录,将有联系的模块放到同一个文件夹下,并且在这个文件夹               中创建一个名字为__init__.py文件,那么这个文件夹就称之为包,有效避免模块名称冲突               问题,让结构更清晰

  • 包的本质依然是模块,包又可以包含包

2.3.2. 导包

格式:import 包名

  • 当导包时会自动执行__init__.py文件
  • 不建议在__init__.py文件中写大量代码
#创建pack_01包,在包中创建register.py文件,在register.py文件中
def funa():
    print('这是注册函数')
#在__init__.py文件中
print('这是init')
#在all.py文件中
import pack_01

运行all.py文件

result:这是init

2.3.4. 导包中的模块

格式:from 包名 import 模块名

调用:模块名.功能名

#创建pack_01包,在包中创建register.py文件,在register.py文件中
def funa():
    print('这是注册函数')
#在__init__.py文件中
print('这是init')
在all.py文件中
from pack_01 import register
register.funa()

运行all.py文件

result:这是init
            这是注册函数

  • 将导入模块放入__init__.py文件中
#创建pack_01包,在包中创建register.py文件,在register.py文件中
def funa():
    print('这是注册函数')
#在__init__.py文件中
print('这是init')
from pack_01 import register
register.register()
在all.py文件中
import pack_01

result:这是init
            这是注册函数 

2.3.4. __all__

含义:本质上是一个列表,列表里的元素就代表要导入的模块,可以控制要引入的东西

格式:__all__ = ['模块名'](在__init__.py文件中)

          from 包名 import * (在all.py文件中)

#创建pack_01包,在包中创建register.py文件,在register.py文件中
def funa():
    print('这是注册函数')
#在__init__.py文件中
print('这是init')
__all__ = ['register']
在all.py文件中
from pack_01 import register
register.register()

result:这是init
            这是注册函数 

三、闭包

3.1. 递归函数

条件:

  1. 必须有一个明确的结束条件
  2. 每进行更深一次的递归,问题规模相比上次递归都要有所减少
  3. 相邻两次重复之间有紧密的联系
#进行数值累加,1+2+3+...+n
def add(n):
    if n == 1:
        return 1
    return n + add(n - 1)
print(add(10))

result:55

#斐波那契数列,1,1,2,3,5,8,13...
def Fibonacci(n):
    if n == 1:
        return 1
    if n == 2:
        return 1
    return Fibonacci(n-2) + Fibonacci(n-1)
print(Fibonacci(7))

result:13

3.2. 闭包

含义:在嵌套函数的前提下,内部函数使用了外部函数的变量,而且外部函数返回了内部函数,               我们就把使用了外部函数变量的内部函数称为闭包。

调用:函数名()()

def outer():
    n = 10
    def inner():
        print(n)
    return inner
print(outer())#返回的是内部函数的内存地址
print(type(outer()))
outer()()

result:<function outer.<locals>.inner at 0x0000020218D03BF8>
            <class 'function'>
            10

def outer(m):
    n = 10
    def inner(o):
        print(n+m+o)
    return inner
outer(20)(20)

result:50

3.3. 函数引用

  • test也只不过是一个函数名,里面存了这个函数所在位置的引用
def test():
    print(123)
print(id(test))
te = test
print(id(te))

result:2201195582736
            2201195582736

四. 装饰器

4.1. 装饰器

含义:本质是一个闭包函数,它可以让其他函数在不需要做任何代码变动的前提下增加额外功                   能,装饰器的返回值也是一个函数对象

#被装饰函数1
def send1():
    print('发送消息1')
#被装饰函数2
def send2():
    print('发送消息2')
#装饰器函数
def all(fn):
    def login():
        print('登录')
        fn()
    return login
all(send1)()
all(send2)()

result:登录
            发送消息1
            登录
            发送消息2

4.2. 语法糖

格式:@装饰器名称

  • 在被装饰函数前加
  • 装饰器名称后面不要加上(),前者是引用,后者是调用函数,返回该函数要返回的值
def outer(fn):
        def inner():
            print('登录')
            fn()
        return inner
#被装饰函数
@outer
def send():
    print('发送消息')
send()

result:登录
            发送消息

4.3. 多个装饰器

  • 多个装饰器的装饰过程,离函数最近的装饰器先装饰,然后外面的装饰器再进行装饰,由内到外的装饰过程 
def deco1(fn):
    def inner():
        return '开头1'+fn()+'结尾1'
    return inner
def deco2(fn):
    def inner():
        return '开头2'+fn()+'结尾2'
    return inner
@deco1
@deco2
def test():
    return '多拉贡'
print(test())

result:开头1开头2多拉贡结尾2结尾1

五、面向对象基础

5.1. 面相对象与面相过程

面相过程:先分析出解决问题的步骤,再把步骤拆成一个个方法,是没有对象去调用的,通过一                      个个方法的执行解决问题

面向对象:将编程当成是一个事物(对象),对外界来说,事物是直接使用的,不用去管内部的情                        况,而编程就是设置事物能做什么事情

面相对象的三大特征:封装、继承、多态

5.2. 类

5.2.1. 类的定义

类:一系列具有相同属性和行为的事物的统称,不是真是存在的事物

对象:类的具体实现,是类创建出来的真实纯在的事物,面相对象思想的核心

5.2.2. 类的三要素

1.类名

2.属性:对象的特征描述,用来说明是什么样子的  

3.方法:对象具有的功能(行为),用来说明能够做什么

5.2.3. 定义类

格式:class 类名:

           代码块

class Washer:
    height = 100
print(Washer.height)
Washer.weight = 50
print(Washer.weight)

result:100
             50

5.3. 对象

5.3.1. 创建对象

格式:对象名 = 类名()

  • 创建对象的过程也叫实例化对象
  • 可以实例化多个对象
class Washer:
    height = 500 #类属性
wa1 = Washer()
wa2 = Washer()
print(type(wa1))
print(wa1)
print(wa2)

result:<class '__main__.Washer'>
            <__main__.Washer object at 0x00000243CFF12908>
            <__main__.Washer object at 0x00000243CFF1A160>

5.3.2. 实例方法

含义:由对象调用,至少有一个self参数,执行实例方法的时候,自动将调用该方法的对象赋值给             self

  • self参数是类中的实例方法必须具备的
  • self表示当前调用该方法的对象,当对象调用实例方法时,python会自动将对象本身的引用作为参数,传递到实例方法的第一个参数self里面
class Washer:
    height = 500 #类属性
    def wash(self): #类方法,self参数是类中的实例方法必须具备的
        print('洗衣服')
        print(self) #self表示当前调用该方法的对象
wa = Washer()
print(wa)
wa.wash() #对象调用类方法

result:<__main__.Washer object at 0x0000023F2A7F1978>
            洗衣服
            <__main__.Washer object at 0x0000023F2A7F1978>

5.3.3. 实例属性

格式:self.属性名

  • 类属性属于类,是公共的,大家都可以访问,实例属性属于对象的,是私有的
  • 只能由对象名访问,不能由类名访问
  • 一个对象新增的实例属性,其他对象依然是没有这个属性的
class Person:
    name = 'Niko' #类属性
    def introduce(self): #类方法,self参数是类中的实例方法必须具备的
        print('实例方法')
        print(f"{Person.name}的年龄是{self.age}")
pe = Person()
pe.age = 18 #实例属性
pe.introduce()

result:实例方法
            Niko的年龄是18

5.4. 构造函数

含义:通常用来做属性初始化或者赋值操作

格式:__init__()

  • 在类实例化对象的时候,会自动调用__init()__的方法
class Person:
    def __init__(self):
        print('__init__')
pe = Person()

result:__init__

  • 在实例化对象的时候传参
class Person:
    def __init__(self,name,age,height):
        self.name = name
        self.age = age
        self.height = height
    def play(self):
        print(f"{self.name}在打王者荣耀")
    def introduce(self):
        print(f"{self.name}的年龄是{self.age},身高是{self.height}cm")
pe1 = Person('Niko',18,180)
pe1.play()
pe1.introduce()
pe2 = Person('Simple',28,170)
pe2.play()
pe2.introduce()

result:Niko在打王者荣耀
            Niko的年龄是18,身高是180cm
            Simple在打王者荣耀
            Simple的年龄是28,身高是170cm

5.5. 析构函数

含义:删除对象的时候,解释器会默认调用__del__()方法

格式:__del__()

  • 正常运行时,不会调用__del__(),对象执行结束之后,系统会自动调用__del__()
class Person:
    def __init__(self):
        print("init")
    def __del__(self):
        print("del")
pe = Person()
print('最后一行代码')

result:init
            最后一行代码
            del

  • del p语句执行时,内存会被立即回收,会调用对象本身的__del__()方法
class Person:
    def __init__(self):
        print("init")
    def __del__(self):
        print("del")
pe = Person()
del pe
print('最后一行代码')

result:init
            del
            最后一行代码

六、封装

6.1. 隐藏属性、方法

6.1.1. 隐藏属性

含义:隐藏对象中一些不希望被外部所访问到的属性或者方法

格式:在属性名前面加上两个__

  • 隐藏属性(私有权限):只允许在类的内部使用,无法通过对象访问
class Person:
    name = 'Nike'
    __age = 18
    def introcuce(self):
        self.__age = 28
        print(f"{self.name}的年龄是{self.__age}")
pe = Person()
pe.introcuce()

result:Nike的年龄是28

  •  隐藏属性实际上是将名字修改为:_类名__属性名
class Person:
    name = 'Nike'
    __age = 18
    def introcuce(self):
        print(f"{self.name}的年龄是{self.__age}")
pe = Person()
pe._Person__age = 38
pe.introcuce()

result:38

6.1.2. 隐藏方法

格式:在方法名前面加上两个__

  •  隐藏方法(私有权限):只允许在类的内部使用,无法通过对象访问
class Person:
    def __play(self):
        print("玩手机")
    def funa(self):
        print('Niko')
        Person.__play(self) #在实例方法中调用私有方法 不推荐
        self.__play() # 推荐使用,更简便
pe = Person()
pe.funa()

result:Niko
            玩手机
            玩手机

  • 隐藏方法实际上是将名字修改为:_类名__方法名
class Person:
    def __play(self):
        print("玩手机")
    def funa(self):
        print('Niko')
pe = Person()
pe._Person__play()

result:玩手机

6.2. 私有属性、方法

6.2.1. 私有属性

格式:在属性名前面加上一个_

class Person:
    name = 'Niko'
    _age = 18
    __sex = '男'
pe = Person()
print(pe._age)

result:18

6.2.1. 私有方法

格式:在方法名前面加上一个_

class Girl:
    def _buy(self):
        print("shopping")
girl = Girl()
girl._buy()

result:shopping

6.3. 普通、私有、隐藏属性\方法的区别

普通属性/方法:xxx

  • 如果是类中定义的,则类可以在任意地方使用

私有属性/方法:_xxx

  • 单下划线开头,如果定义在类中,外部可以使用,子类也可以继承,但是在另一个py文件中通过from xxx import * 导入时,无法导入,一般是为了避免与Python关键字冲突而采用的命名方法

隐藏属性方法:__xxx

  • 双下划线开头,如果定义在类中,无法在外部直接访问,子类不会继承,要访问只能通过间接的方式,另一个py文件中通过from xxx import *导入的时候,也无法导入,这种命名一般是Python的魔术方法或属性,都是有特殊含义或者功能的,自己不要轻易定义

七、继承

7.1. 继承的定义

含义:就是让类和类之间转变为父子关系,子类默认继承父类的属性和方法

格式:class 类名(父类名)

           代码块

7.2. 单继承

7.2.1. 单继承的定义

含义:子类可以继承父类的属性和方法,就算子类自己没有,也可以使用父类

  • pass是占位符,类下面不写任何东西,会自动跳过
class Person():
    def eat(self):
        print('吃饭')
    def sleep(self):
        print('睡觉')
class Girl(Person):
    pass #pass是站位符,可以直接跳过
class Boy(Person):
    pass
girl = Girl()
girl.eat()
girl.sleep()
boy = Boy()
boy.eat()
boy.sleep()

result:吃饭
            睡觉
            吃饭
            睡觉

7.2.2. 继承的传递(多重继承)

含义:C类继承与B类,B类继承与A类,C类具有A、B类的属性和方法

class Father():
    def eat(self):
        print('吃饭')
class Son(Father):
    def sleep(self):
        print('睡觉')
class Grandson(Son):
    pass
son = Son()
son.sleep()
son.eat()

result:睡觉
            吃饭

7.2.3. 方法的重写

含义:如果从父类继承的方法不能满足子类的需求,可以在子类中重写父类的方法,这个过程称               为方法的覆盖,也称方法的重写

7.2.3.1. 方法一

格式:父类名.方法名(self)

class Father():
    def money(self):
        print('继承100万')
class Son(Father):
    def money(self):
        Father.money(self)
        print('赚100万')
son = Son()
son.money()

result:继承100万
             赚100万

7.2.3.2. 方法二(推荐)

格式:super().方法名()

  • super在python里面是一个特殊的类,super()是使用super类创建出来的对象,可以调用父类中的方法
class Father():
    def money(self):
        print('继承100万')
class Son(Father):
    def money(self):
        super().money()
        print('赚100万')
son = Son()
son.money()

result:继承100万
             赚100万

7.2.3.3. 方法三

格式:super(子类名,self).方法名

class Father():
    def money(self):
        print('继承100万')
class Son(Father):
    def money(self):
        super(Son,self).money()
        print('赚100万')
son = Son()
son.money()

result:继承100万
             赚100万

7.3. 新式类写法

7.3.1. 第一种(经典类)

格式:class A:

  • 经典类:不由任意内置类型派生出来的类
  • 派生类:子类有不同于父类的属性或者方法

7.3.2. 第二种(经典类)

格式:class A():

7.3.3. 第三种(新式类)

格式:class A(object):

  • 新式类:继承了object类或者该类的子类都是新式类
  • object——对象,python为所有对象提供的基类(顶级父类),提供了内置属性与方法,dir()查看
  • python3中如果一个类没有继承任何类,则默认继承object类,因为python3都是新式类
print(dir(object))

result:['__class__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__',                            '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__',                  '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__',                                  '__sizeof__', '__str__', '__subclasshook__']

7.4. 多继承

7.4.1. 多继承的定义

含义:子类可以拥有多个父类,并且具有所有父类的属性和方法

class Father(object):
    def eat(self):
        print('eat')
class Mother(object):
    def drink(self):
        print('drink')
class Son(Father,Mother):
    pass
son = Son()
son.eat()
son.drink()

result:eat
            drink

7.4.2. 不同的父类存在同名的方法

  • 有多个父类的属性和方法,如果多个父类具有同名方法的时候,调用就近原则,括号内哪一个最近,优先调用哪一个类的方法
class Father(object):
    def eat(self):
        print('apple')
class Mother(object):
    def eat(self):
        print('banana')
class Son(Father,Mother):
    pass
son = Son()
son.eat()

result:apple

7.4.3. 方法的搜索顺序

含义:用来查看方法的搜索顺序

格式:类名().__mro_

print(Son.__mro__)

result:(<class '__main__.Son'>, <class '__main__.Father'>, <class '__main__.Mother'>, <class               'object'>)

7.4.4. 多继承的弊端

  • 容易引发冲突
  • 会导致代码设计的复杂度增加

八、多态

8.1. 多态的定义

含义:指同一种行为具有不同的表现形式

  • 不关注对象的类型,关注对象具有的行为,也就是对象的实例方法是否同名
  • 多态的好处可以增加代码的外部调用灵活度,让代码更加通用,兼容性比较强
  • 不同的子类对象,调用相同的父类方法,会产生不同的执行结果
class Animal(object):
    """父类:动物类"""
    def shout(self):
        print('动物叫')
class Cat(Animal):
    """子类一:猫类"""
    def shout(self):
        print("猫叫")
class Dog(Animal):
    """子类二:狗类"""
    def shout(self):
        print('狗叫')
dog = Dog()
dog.shout()
cat = Cat()
cat.shout()

result:狗叫
            猫叫

8.2. 多态性

含义:定义一个统一的接口,一个接口多种实现

class Animal(object):
    def eat(self):
        print('进食')
class Pig(Animal):
    def eat(self):
        print("吃饲料")
class Dog(Animal):
    def eat(self):
        print('吃狗粮')
def test(obj):
    obj.eat()
animal = Animal()
pig = Pig()
dog = Dog()
test(animal)
test(pig)
test(dog)

result:进食
            吃饲料
            吃狗粮

九、静态方法

格式:class 类名:

           @staticmethod

           def 方法名(形参):

                 方法体

调用:类名.方法名(实参)

           对象名.方法名(实参)

  • 使用@staticmethod来进行修饰,静态方法没有self,cls参数的限制
  • 静态方法与类无关,可以被转化成函数使用
  • 静态方法既可以使用对象访问,也可以使用类访问
  • 取消不必要的参数传递,有利于减少不必要的内存占用和性能消耗
class Person(object):
    @staticmethod
    def study(name):
        print(f"{name}学习")
Person.study('Niko')
person = Person()
person.study('Niko')

result:Niko学习
            Niko学习

十、类方法

含义:使用装饰器@classmethod来标识为类方法,对于类方法,第一个参数必须是类对象,一般             是以cls作为第一个参数

格式:class 类名:

           @classmethod

           def 方法名(cls):

                 方法体

  • cls代表类对象本身,类本质上就是一个对象
  • 当方法中需要使用到类对象(如访问私有类属性等),定义类方法
  • 类方法一般是配合类属性使用
  • 在调用时不需要传递cls
class Person(object):
    name = "Niko"
    @classmethod
    def sleep(cls):
        print(cls)
        print(cls.name)
print(Person)
Person.sleep()

result:<class '__main__.Person'>
            <class '__main__.Person'>
            Niko

十一、三大方法总结

在类中定义方法有三种:

  1. 实例方法:里面有个self参数,代表对象本身,方法内部可以访问实例属性,通过self.实例属性名来访问实例属性,也可以通过类名.类属性名来访问类属性。
  2. 静态方法:@staticmethod,没有形参的限制,不需要访问实例属性和类属性,如果要访问类属性,通过类名.类属性名访问,不能访问实例属性。
  3. 类方法:@classmethod,只能访问类属性,通过cls.类属性名来访问类属性

十二、单例模式

12.1. __new__()

含义:在内存中为对象分配空间,返回对象的引用

  • 一个对象的实例化过程:首先执行__new__(),如果没有写__new__(),默认调用object里面的__new__(),返回一个实例对象,这个实例对象的引用作为第一个参数也就是self参数,self代表对象本身,再去调用__init__(),对、对象进行一个初始化
  • object基类提供的内置的静态方法
  • 重写__new__()一定要return,super().__new__(cls),否则python解释器得不到分配空间的对象引用,就不会调用__init__()
class Test(object):
    def __init__(self):
        print('self:',self) #self代表对象本身,跟te是一个东西
    #new方法是object里面默认的方法,他是有自己的作用的,现在重写了一个print
    #相当于是改变了他的功能
    def __new__(cls, *args, **kwargs): #cls代表类本身
        print('cls: ',cls)
        # 对父类进行扩展   super().方法名()
        res = super().__new__(cls)
        print('res:',res)
        #方法重写,res里面保存的是实例对象的引用
        #__new__()是静态方法,形参里面有cls,实参就必须传cls
        return res
te = Test()
print('te:  ',te)
print('Test:',Test)

result:cls:  <class '__main__.Test'>
            res: <__main__.Test object at 0x0000014DB3275F60>
            self: <__main__.Test object at 0x0000014DB3275F60>
            te:   <__main__.Test object at 0x0000014DB3275F60>
            Test: <class '__main__.Test'>

12.2. __new__()与__init__()区别

  1. __new__()是创建对象,__init__()是初始化对象
  2. __new__()是返回对象引用,__init__()定义实例属性
  3. __new__()是类级别的方法,__init__()是实例级别的方法

12.3. 单例模式的定义

含义:一种常用的软件设计模式,该模式的主要目的是确保某一个类只有一个实例存在。当你希               望在整个系统中,某个类只能出现一个实例时,单例模式就能派上用场。

  • 优点:可以节省内存空间,减少了不必要的资源浪费
  • 缺点:多线程访问的时候容易引发线程安全问题

12.4. 单例模式的实现

含义:对象的内存地址都是一样的,只有一个对象

  1. 通过@classmethod
  2. 通过装饰器实现
  3. 通过重写__new__()
  4. 通过导入模块实现

12.4.1. 通过重写__new__()实现单例模式

设计流程

  1. 定义一个类属性,初始值为None,用来记录单例对象的引用
  2. 重写__new__()方法
  3. 进行判断,如果类属性是None,把__new__()返回的对象引用保存进去
  4. 返回类属性中记录的对象引用
class Singleton(object):
    obj = None
    def __new__(cls, *args, **kwargs):
        pass
        if cls.obj == None:
            cls.obj = super().__new__(cls)
        return cls.obj
    def __init__(self):
        pass
s1 = Singleton()
print("s1:",s1)
s2 = Singleton()
print("s2:",s2)

result:s1: <__main__.Singleton object at 0x000001EDC9FD8A90>
            s2: <__main__.Singleton object at 0x000001EDC9FD8A90>

12.4.2. 通过导入模块实现

模块就是天然的单例模式

# 创建test.py文件,在test.py文件中
class Test(object):
    def test(self):
        pass
te = Test()
#在主文件中
from test import te as te01
from test import te as te02
print(te01,id(te01))
print(te02,id(te02))

result:<test.Test object at 0x0000024D14D840F0> 2530085454064
            <test.Test object at 0x0000024D14D840F0> 2530085454064

12.5. 单例模式的应用场景

  1. 回收站(只能打开一个回收站)
  2. 音乐播放器(一个音乐播放软件负责音乐播放的对象只有一个
  3. 开发游戏软件(场景管理器)     
  4. 数据库配置、数据库连接池的设计

十三、魔法方法&魔法属性

含义:在Python中,__xx__()的函数叫做魔法方法,指的是具有特殊功能的函数

  1. __new__():在内存中为对象分配空间并返回对象的引用
  2. __init__():初始化对象或给属性赋值(构造函数)
  3. __doc__:类的描述信息
  4. __module__:表示当前操作对象所在模块
  5. __class__:表示当前操作对象所在的类
  6. __str__():对象的描述信息
  7. __del__():删除对象(析构函数)
  8. __call__():使一个实例对象成为一个可调用对象
  9. __dict__:返回对象具有的属性和方法

13.1. __doc__

含义:类的描述信息,属于魔法属性

  • 只能使用多行注释,单行注释无效
class Person(object):
    """人类---类的描述信息""" #只能使用多行注释,单行注释无效
    pass
print(Person.__doc__)

result:人类---类的描述信息

13.2. __module__

含义:表示当前操作对象所在模块

#在main.py文件中
class Person(object):
    """人类---类的描述信息""" #只能使用多行注释,单行注释无效
    pass
pe = Person()
print(pe.__module__)

result:__main__

13.3. __class__

含义:表示当前操作对象所在的类

class Person(object):
    """人类---类的描述信息""" #只能使用多行注释,单行注释无效
    pass
pe = Person()
print(pe.__class__)

result:<class '__main__.Person'>

13.4. __str__()

含义:如果类中定义了此方法,那么在打印对象时,默认输出该方法的返回值,也就是打印方法               中return的数据

  • __str__()必须返回一个字符串
class Person(object):
    def __str__(self):
        return 'str'
pe = Person()
print(pe)

result:str

13.5. __call__()

含义:使一个实例对象成为一个可调用对象,就像函数那样可以调用

  • 可调用对象:函数、内置函数和类都是可调用对象,凡是可以把一对()应用到某个对象身上都可以称为可调用对象
  • callable():判断一个对象是否是可调用对象
  • 调用一个可调用的实例对象,其实就是在调用它的__call__()方法
class Person(object):
    pass
pe = Person()
print(callable(pe))
def test():
    print('test')
print(callable(test))

result:False

            True

class Person(object):
    def __call__(self, *args, **kwargs):
        print('call')
    def test(self):
        print('test')
pe = Person()
pe() #调用一个可调用的实例对象,其实就是在调用它的__call__()方法
print(callable(pe))

result:call
            True

13.6. __dict__

含义:返回对象具有的属性和方法

class Person(object):
    obj1 = None
    def test(self):
        print('test')
pe = Person
print(pe.__dict__)

result:{'__module__': '__main__', 'obj1': None, 'test': <function Person.test at                                             0x0000019F5163E510>, '__dict__': <attribute '__dict__' of 'Person' objects>,                                 '__weakref__':                     <attribute '__weakref__' of 'Person' objects>, '__doc__':                       None}

 十四、文件

14.1. 文件对象的方法

  • open():创建一个file对象,默认是以只读模式打开的
  • read(n):读取文件内容
  • write():将指定内容写入文件
  •  close():关闭软件

14.2. 文件属性

  • 文件名.name:返回要打开的文件的文件名,可以包含文件的具体路径
  • 文件名.mode:返回文件的访问模式
  • 文件名.closed:检测文件是否关闭,关闭就返回True
f = open('test.txt')
print(f.name)
print(f.mode)
print(f.closed)
f.close() #文件不关闭,会一直占用系统资源
print(f.closed)

result:test.txt
            r
            False
            True

14.3. 文件读写

14.3.1. read()

含义:读取文件内容

  • n表示从文件中读取的数据的长度,没有传n值或负值就默认一次性读取文件的所有内容
#在test.txt文件中写入Hello World!!
f = open('test.txt')
print(f.read(2))
print(f.read())
f.close()

result:He
            llo World!!

打开桌面的test.txt文件

#在桌面的text.txt文件中内容是:HelloWorld!!!
f = open(r'C:\Users\Sagapohh\Desktop\test.txt',encoding='utf-8')
print(f.read(2))
print(f.read())
print(f.name)
f.close()

result:He
            llo World!!!
            C:\Users\Sagapohh\Desktop\test.txt

14.3.2. readline()

含义:一次读取一行内容,方法执行完,会把文件指针移到下一行,准备再次读取

# 在text.txt文件中的内容
# Hello World 1
# Hello World 2
# Hello World 3
f = open('test.txt')
while True:
    text = f.readline()
    if  not text:
        break
    print(text)
f.close()

result:Hello World 1

            Hello World 2

            Hello World 3

14.3.3. readlines()

含义:按照行的方式一次性读取全部内容

  • 返回的是一个列表,每一行的数据就是列表中的一个元素
f = open('test.txt')
text = f.readlines()
print(text)
for i in text:
    print(i)
f.close()

result:['Hello Word 1\n', 'Hello Word 2\n', 'Hello Word 3\n']
            Hello World 1

            Hello World 2

            Hello World 3

14.4. 访问模式

  • r:只读模式,文件必须存在,不存在就会报错
  • w:只写模式,文件存在就会先清空文件内容,再写入添加内容,不存在就创建新文件
  • +:表示可以同时读写某个文件(会影响文件的读写效率,开发过程中多数是只读、只写)
  • r+:可读写文件,文件不存在就会报错
  • w+:先写再读,文件存在就重新编辑文件,不存在就创建新文件
  • a:追加是,不存在就创建新文件进行写入,存在则在原有的内容的基础上追加新的内容

14.5. 文件定位

tell():显示文件内当前位置,即文件指针当前位置

seek(offset,where):移动文件读取指针到指定位置

offset:偏移量,表示要移动的字节数

where:起始位置,表示移动字节的参考位置,默认是0,0代表文件开头,1代表当前位置,2代                 表文件结尾

  • 文件内容写入后指针在结尾,文件读取从指针后开始读取
  • 文件指针:标记从哪个位置开始读取数据
f = open('test.txt','w+')
f.write('Hello World!')
pos1 = f.tell()
print('pos:',pos1)
f.seek(0,0)
pos2 = f.tell()
print('pos:',pos2)
print(f.read())
f.close()

result:pos: 12
            pos: 0
            Hello World!

14.6. 编码格式

14.6.1. with open

含义:代码执行完,系统会自动调用f.close(),可以省略文件关闭步骤

with open('test.txt','w') as f:
    f.write('aaa')
print(f.closed)

result:True

14.6.2. encoding

  • file对象的encoding参数的默认值与平台有关,比如windows上默认字符编码为GBK
  • encoding表示编码集,根据文件的实际保存编码进行获取获取数据,对于我们而言,使用更多的是utf-8
with open('test.txt','w+',encoding='utf-8') as f:
    f.write('我是Niko')
    f.seek(0,0)
    print(f.read())

result:我是Niko

14.7. 读取图片

  • rb:以字节来读取图片
  • wb:以字节写入图片
with open(r'G:\图片\1.jpg','rb') as f1:
    img = f1.read()
with open(r'E:\python-projects\1.jpg','wb') as f2:
    f2.write(img)

result:在我们的项目中就会出现我们添加进来的照片

14.8. 目录操作

条件:需要导入模块--import os

14.8.1. os.rename()

含义:文件重命名

os.rename('test.txt','123.txt')

14.8.2. os.remove()

含义:删除文件

os.remove('123.txt')

14.8.3. os.mkdir()

含义:创建文件夹

os.mkdir('test')

14.8.4. os.rmdir()

含义:删除文件夹

os.rmdir('test')

14.8.5. os.getcwd()

含义:获取当前目录

print(os.getcwd())

result:E:\python-projects

14.8.6. os.listdir()

含义:获取目录列表

  • os.listdir('../')--返回上一级列表
print(os.listdir())

result:['.idea', '1.jpg', 'bbs_login.feature', 'emails', 'main.py', 'test.py', '__pycache__']

十五、可迭代对象、迭代器、生成器

15.1. 可迭代对象

15.1.1. 可迭代对象的定义

含义:可迭代对象Iterable--能被for循环依次从对象中把一个个元素取出来的过程

数据类型:str、list、tuple、dict、set等

15.1.2. 可迭代对象的条件

  1. 对象实现了__iter__()方法
  2. __iter__()方法返回了迭代器对象

15.1.3. for循环工作原理

  1. 通过__iter__()获取可迭代对象的迭代器
  2. 对获取到的迭代器不断调用__next__()方法来获取下一个值并将其赋值给临时变量i

15.1.4. isinstance():

含义:判断一个对象是否是可迭代对象或者是一个已知的数据类型

格式:isinstance(o,t)

  • o:对象,t:类型,可以是直接或间接类名、基本类型或元组
from collections.abc import Iterable
st = '123'
print(isinstance(123,Iterable))
print(isinstance(st,(int,str)))

result:False
            True

15.2. 迭代器

15.2.1. 迭代器的定义

含义:是一个可以记住遍历位置的对象,在上次停留的位置继续做一些事情

15.2.1. iter()、next()

迭代器中有两个函数一个是iter(),一个是next()

iter():获取可迭代对象的迭代器

next():一个个去取元素,取完元素后会引发一个异常

  • iter()调用对象的__iter__(),并把__iter__()方法的返回结果作为自己的返回值
  • next()调用对象的__next__(),一个个取元素
  • 所有元素都取完了,__next__()将引发StopIteration异常
li = [1,2,3]
li2 = iter(li) #创建迭代器对象
print(li2)
print(next(li2))#获取下一条数据
print(next(li2))
print(next(li2))
print(next(li2))#取完元素后,再使用next()会引发StopIteration异常

result:<list_iterator object at 0x000001C67D358AC8>
            1
            2
            3
            Traceback (most recent call last):
            File "E:\python-projects\main.py", line 12, in <module>
            print(next(li2))#取完元素后,再使用next()会引发StopIteration异常
            StopIteration

  • dir():查看对象的属性和方法
  • 通过dir()可以发现li1中有'__iter__',没有'__next__',而li2有'__next__'
li = [1,2,3]
print('li1:',dir(li))#li中没有__next__()方法
li2 = li.__iter__()
print('li2:',dir(li2))#li2中有__next__()方法
print(li2)
print(li2.__next__())
print(li2.__next__())
print(li2.__next__())
print(li2.__next__())

result:li1: ['__add__', '__class__', '__contains__', '__delattr__', '__delitem__', '__dir__',                                  '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__',                    '__hash__', '__iadd__', '__imul__', '__init__', '__init_subclass__', '__iter__', '__le__',                      '__len__', '__lt__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__',                          '__repr__', '__reversed__', '__rmul__', '__setattr__', '__setitem__', '__sizeof__',                              '__str__', '__subclasshook__', 'append', 'clear', 'copy', 'count', 'extend', 'index', 'insert',                    'pop', 'remove', 'reverse', 'sort']
            li2: ['__class__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__',                              '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__iter__',                            '__le__', '__length_hint__', '__lt__', '__ne__', '__new__', '__next__', '__reduce__',                          '__reduce_ex__', '__repr__', '__setattr__', '__setstate__', '__sizeof__', '__str__',                            '__subclasshook__']
                  <list_iterator object at 0x000002A026CD5908>
                  1
                  2
                  3
                  Traceback (most recent call last):
                  File "E:\python-projects\main.py", line 9, in <module>
                  print(li2.__next__())
                  StopIteration

15.2.2. 可迭代对象iterable和迭代器iterator

  • 凡是可以作用于for循环的都属于可迭代对象
  • 凡是可以作用于next()的都是迭代器
from collections.abc import Iterable, Iterator
name = 'Niko'
print(isinstance(name,Iterable))
print(isinstance(name,Iterator))
name2 = iter(name)#将name转换成迭代器对象
print(isinstance(name2,Iterable))
print(isinstance(name2,Iterator))
#迭代器对象一定是可迭代对象

result:True
            False
            True
            True

15.2.3. 迭代器协议

对象必须提供一个next方法,执行该方法要么就返回迭代中的下一项,要么就引发StopIteration异常,来终止迭代

15.2.4. 自定义迭代器类

  • 满足两个条件:iter()、next()
class Person(object):
    def __init__(self):
        self.num = 0
    def __iter__(self):
        return self #返回的是当前迭代器类的实例对象
    def __next__(self):
        if self.num == 10:
           raise StopIteration('终止迭代,数据已经被取完')
        self.num += 1
        return self.num
pe = Person()
for i in pe:
    print(i)

result:1
             2
             3
             4
             5
             6
             7
             8
             9
            10

15.3. 生成器

15.3.1. 生成器的定义

含义:Python中一边循环一边计算的机制,叫做生成器

格式:(表达式 for 变量 in 列表)

li = (i*5 for i in range(5))
print(li)
for i in li:
    print(i)
print(next(li))

result:<generator object <genexpr> at 0x00000174BB6D90C0>
            0
            5
           10
           15
           20
           Traceback (most recent call last):
           File "E:\python-projects\main.py", line 10, in <module>
           print(next(li))
           StopIteration

15.3.2. 生成器函数

含义:pyhton中,使用了yield关键字的函数就称之为生成器函数

yield的作用:

  • 类似于return,将指定值或者多个值返回给调用者
  • yield语句一次返回一个结果,在每个结果中间,挂起函数,执行next(),再重新从挂起点继续往下执行        
def gen():
    yield 'a'#返回一个'a',并暂停函数,在此处挂起,下一次再从此处恢复运行
    yield 'b'
    yield 'c'
gen_01 = gen()
print(gen_01)
for i in gen_01:
    print(i)

result:<generator object gen at 0x00000240928D90C0>
             a
             b
             c

def gen(n):
    li = []
    a = 0
    while a < n:
        li.append(a)
        yield a
        a += 1
    print('li:',li)
print(gen(5))
for i in gen(5):
    print(i)

result:<generator object gen at 0x00000263F76090C0>
            0
            1
            2
            3
            4
            li: [0, 1, 2, 3, 4]

def test():
    yield 'a'
    yield 'b'
    yield 'c'
print(test())
print(next(test()))
print(next(test()))
te = test()
print(next(te))
print(next(te))
print(next(te))

result:<generator object test at 0x0000023CF6F890C0>
            a
            a
            a
            b
            c

15.3.3. 三者关系

可迭代对象:指实现了python迭代协议,可以通过for...in...循环遍历的对象,比如list、dict、str...、迭代器、生成器

迭代器:可以记住自己遍历位置的对象,直观体现就是可以使用next()函数返回值,迭代器只能往前,不能往后,当遍历完毕之后,next()会抛出异常

生成器:是特殊的迭代器,需要注意的是迭代器并不一定是生成器,他是python提供的通过简便的方法写出迭代器的一种手段

包含关系:可迭代对象 > 迭代器 > 生成器

十六、线程

16.1. 线程的定义

含义:是cpu调度的基本单位

  • 每一个进程至少都会有一个线程,这个线程通常就是我们所说的主线程
  • 线程之间执行是无序的
  • 线程执行由cpu调度决定的
  • 线程同时进行,存在资源竞争

16.2. 线程语法结构

  • threading模块提供了Thread类代表进程对象
16.2.1. Thread参数

target:执行的目标任务名,即子进程要执行的任务

args:以元组的形式传参

kwagrs:以字典的形式传参

16.2.2. 常用的方法

1. start():开启子进程

2. join():主进程等待子进程执行结束

3. getName():获取线程名

4. setName():修改线程名

16.3. 线程之间共享资源(全局变量)

import time
from threading import Thread
li = []
def wdata():
    for i in range(5):
        li.append(i)
        time.sleep(0.2)
    print('写入的数据:',li)
def rdata():
    print('读取的数据:',li)
if __name__ == '__main__':
    #创建子线程
    t1 = Thread(target=wdata)
    t2 = Thread(target=rdata)
    t1.start()
    t2.start()

result:读取的数据: [0]
            写入的数据: [0, 1, 2, 3, 4] 

16.4. 防止线程同步

防止线程同步两种方式:join和互斥锁

16.4.1. join()

含义:阻塞线程,等待任务结束

import time
from threading import Thread

li = []
def wdata():
    for i in range(5):
        li.append(i)
        time.sleep(1)
    print('写入的数据:',li)
def rdata():
    print('读取的数据:',li)
if __name__ == '__main__':
    #创建子线程
    t1 = Thread(target=wdata)
    t2 = Thread(target=rdata)
    t1.start()
    t1.join()#阻塞线程,等待t1任务执行结束
    t2.start()
    t2.join()

result:写入的数据: [0, 1, 2, 3, 4]
            读取的数据: [0, 1, 2, 3, 4] 

16.4.2. 互斥锁

含义:对共享数据进行锁定,保证多个线程访问共享数据不会出现数据错误问题,保证同一时刻只能有一个线程去操作。

创建互斥锁:变量名 = Lock()

格式:变量名.acquire() 上锁

           变量名.release() 释放锁

  • 互斥锁是多个线程一起去抢,抢到锁的线程先执行
from threading import Thread, Lock

a = 0
b = 1000000
lock = Lock()
def add():
    lock.acquire()
    for i in range(b):
        global a
        a += 1
    print('第一次:',a)
    lock.release()
def add2():
    lock.acquire()
    for i in range(b):
        global a
        a += 1
    print('第二次:',a)
    lock.release()
if __name__ == '__main__':
    first = Thread(target=add)
    secon = Thread(target=add2)
    first.start()
    secon.start()

result:第一次: 1000000
            第二次: 2000000

16.5. 多线程

含义:同时运行多个线程

格式:threading.Thread

  • 多线程可以完成多任务
  • 一个进程默认有一个线程,进程里面可以创建多个线程,线程是依附在进程里面的,没有进程就没有线程
import threading
import time
def sing():
    print('唱歌start')
    time.sleep(2)
    print('唱歌end')
def dance():
    print('跳舞start')
    time.sleep(2)
    print('跳舞end')
if __name__ == '__main__':
    t1 = threading.Thread(target=sing)
    print(t1)
    t2 = threading.Thread(target=dance)
    t1.start()
    t2.start()

result:<Thread(Thread-1, initial)>
            唱歌start
            跳舞start
            跳舞end
            唱歌end

16.6. 守护线程

含义:主线程执行结束,子线程也会跟着结束

格式:setDaemon(True)

  • 放在start()前面
import threading
import time
def sing():
    print('唱歌start')
    time.sleep(2)
    print('唱歌end')
def dance():
    print('跳舞start')
    time.sleep(2)
    print('跳舞end')
if __name__ == '__main__':
    t1 = threading.Thread(target=sing)
    print(t1)
    t2 = threading.Thread(target=dance)
    #守护进程,必须放在start()前面:主线程执行结束,子线程也会跟着结束
    t1.setDaemon(True)
    t2.setDaemon(True)
    t1.start()
    t2.start()
    #阻塞主线程join():暂停的作用,等子线程执行结束后,主线程才会继续执行,必须放在start()后面
    t1.join()#
    t2.join()
    print('完美谢幕,本次表演结束')

result:<Thread(Thread-1, initial)>
            唱歌start
            跳舞start
            跳舞end
            唱歌end
            完美谢幕,本次表演结束

16.7. getName()、setName

import threading
import time
def sing(name):
    print(f'{name}唱歌start')
    time.sleep(2)
    print(f'{name}唱歌end')
def dance(name):
    print(f'{name}跳舞start')
    time.sleep(2)
    print(f'{name}跳舞end')
if __name__ == '__main__':
    t1 = threading.Thread(target=sing,args=('Niko',))
    print(t1)
    t2 = threading.Thread(target=dance,args=('Simple',))
    #守护进程,必须放在start()前面:主线程执行结束,子线程也会跟着结束
    t1.setDaemon(True)
    t2.setDaemon(True)
    t1.start()
    t2.start()
    #阻塞主线程join():暂停的作用,等子线程执行结束后,主线程才会继续执行,必须放在start()后面
    t1.join()#
    t2.join()
    print(t1.getName())
    print(t2.getName())
    t1.setName('线程1')
    t2.setName('线程2')
    print(t1.getName())
    print(t2.getName())
    print('完美谢幕,本次表演结束')

result:<Thread(Thread-1, initial)>
            Niko唱歌start
            Simple跳舞start
            Niko唱歌end
            Simple跳舞end
            Thread-1
            Thread-2
            线程1
            线程2
            完美谢幕,本次表演结束

十七、进程

17.1. 进程的定义

含义:是操作系统进行资源分配和调度的基本单位,是操作系统结构的基础

  • 一个正在运行的程序或者软件就是一个进程
  • 进程里面可以创建多个线程,多线程也可以完成多任务

17.2. 进程的状态

  1. 就绪状态:运行的条件都已满足,正在等待cpu运行
  2. 执行状态:cpu正在执行其功能
  3. 等待(阻塞)状态:等某些条件满足,如一个程序sleep了,此时就处于等待状态

17.3. 进程语法结构

  • multiprocessing模块提供了Process类代表进程对象
17.3.1. Process参数

target:执行的目标任务名,即子进程要执行的任务

args:以元组的形式传参

kwagrs:以字典的形式传参

17.3.2. 常用的方法

1. start():开启子进程

2. is alive():判断子进程是否还存活着,存活着返回True,死亡返回False

3. join():主进程等待子进程执行结束

17.3.3. 常用的属性

name:当前进程的别名,默认Process-N

pid:当前进程的进程编号

17.3.4. start()、target、name、pid
  • 程序默认执行主进程,自己创建的才是子进程
  • 父进程id相同,因为他们都是处于同一个py文件下面,这个py文件有一个主进程,所以父进程的id就是py文件的主进程的id
import os
from multiprocessing import Process

def sing():
    print(f'sing父进程编号:{os.getppid()}')#os.getppid():获取当前父进程编号
    print(f'sing子进程编号:{os.getpid()}')#os.getpid():获取当前进程编号
    print('唱歌')
def dance():
    print(f'dance父进程编号:{os.getppid()}')  # os.getppid():获取当前父进程编号
    print(f'dance子进程编号:{os.getpid()}')  # os.getpid():获取当前进程编号
    print('跳舞')
if __name__ == '__main__':
    s1 = Process(target=sing,name='进程1')
    d1 = Process(target=dance,name='进程2')
    s1.start()
    d1.start()
    s1.name='进程一'
    d1.name='进程二'
    print('sing子进程名:',s1.name)
    print('dance子进程名:',d1.name)
    print('sing子进程编号:',s1.pid)
    print('dance子进程编号:',d1.pid)
    print('主进程pid:',os.getpid())
    print('主进程的父进程pid:',os.getppid())

result:sing子进程名: 进程一
            dance子进程名: 进程二
            sing子进程编号: 8508
            dance子进程编号: 4296
            主进程pid: 16240
            主进程的父进程pid: 12836
            sing父进程编号:16240
            sing子进程编号:8508
            唱歌
            dance父进程编号:16240
            dance子进程编号:4296
            跳舞 

  • 主进程的父进程就是pycharm软件的进程号,在cmd中输入命令:tasklist,找pycharm看到进程号

17.3.5. is_alive()、join()、args
  • 写在主进程中判断存活状态的时候需要加入join阻塞一下
  • 元组的形式传一个参数时需要加逗号
from multiprocessing import Process
def eat(name):
    print(f'{name}吃饭')
def sleep(name):
    print(f'{name}睡觉')
if __name__ == '__main__':
    p1 = Process(target=eat,args=('Niko',))
    p2 = Process(target=sleep,args=('Simple',))
    p1.start()
    p1.join()
    p2.start()
    p2.join()
    print(p1.is_alive())
    print(p2.is_alive())

result:Niko吃饭
            Simple睡觉
            False
            False

17.4. 进程间不共享全局变量

17.4.1. if __name__ == "__main__"

  • 防止别人导入文件的时候执行main里面的方法
  • 防止windows系统递归创建子进程

17.4.2.  进程间不共享全局变量

from multiprocessing import Process
li = []
def wdata():
    for i in range(5):
        li.append(i)
    print('写入的数据:',li)
def rdata():
    print('读取的数据:',li)
if __name__ == '__main__':
    p1 = Process(target=wdata)
    p2 = Process(target=rdata)
    p1.start()
    p1.join()
    p2.start()

result:写入的数据: [0, 1, 2, 3, 4]
            读取的数据: []

17.5. 进程之间的通信

Queue(队列)

  • q.put():放入数据
  • q.get():取出数据
  • q.empty():判断队列是否为空
  • q.qsize():返回当前队列包含的消息数量
  • q.full():判断队列是否满了

初始化一个队列对象

from queue import Queue
q = Queue(3)#最多可以接收三条消息,没写或者是负值就代表没有上限,直到内存的尽头
q.put('Niko')
q.put('Simple')
print('判断队列是否满了:',q.full())
q.put('monesy')
print('判断队列是否满了:',q.full())
print(q.get())#获取队列的一条消息,然后将其从队列中移除
print(q.get())
print('判断队列是否为空:',q.empty())
print('返回当前队列包含的消息数量:',q.qsize())
print('判断队列是否满了:',q.full())
print(q.get())
print('判断队列是否为空:',q.empty())
print('返回当前队列包含的消息数量:',q.qsize())

result:判断队列是否满了: False
            判断队列是否满了: True
            Niko
            Simple
            判断队列是否为空: False
            返回当前队列包含的消息数量: 1
            判断队列是否满了: False
            monesy
            判断队列是否为空: True
            返回当前队列包含的消息数量: 0

from multiprocessing import Process,Queue
def wdata(q1):
    for i in range(5):
        q1.put(i)
        print(f'{i}已经被放入')
def rdata(q2):
    while True:
        if q2.empty():
            break
        else:
            print('取出数据:',q2.get())
if __name__ == '__main__':
    q = Queue()
    p1 = Process(target=wdata,args=(q,))
    p2 = Process(target=rdata,args=(q,))
    p1.start()
    p1.join()
    p2.start()

result:0已经被放入
            1已经被放入
            2已经被放入
            3已经被放入
            4已经被放入
            取出数据: 0
            取出数据: 1
            取出数据: 2
            取出数据: 3
            取出数据: 4

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值