Python的学习

由于本人因不能手搓脚本而感到自卑

此篇用来记录本人的python学习进度

希望能在寒假结束前把python学完

一起加油吧OWO

持续更新ing

Day1梦的开始

输出hello world 

print("hello world!")

入门概念

字面量:代码中,被写下来的固定的,称为字面量

(字符串,整数,浮点数。。。。)

注释:

单行注释:# (python中#后面加个空格(规范))

多行注释:""" """"(三个双引号中间的都是注释的内容),一般用于

  1. 整个python代码文件
  2. 方法
""""
本代码写着玩的
"""
print("hello world!")
print("111")# 输出

变量:

变量名 = 变量值

money = 100
print("钱包还有",money)
print(money - 10)
money = money - 10
print("还剩",money,"在钱包")

数据类型:(入门)

type()

输出类型信息,可以赋值给一个变量

print(type(money))
name = type(money)
print(name)

查看的是变量存储的数据的类型,因为,变量无类型,但是它存储的数据有

注意:字符串变量:我们会说一个字符串存储在一个变量里面,变量是没有类型的(python中)

数据类型转换:

int()

float()

str()任意都可以转字符串

都是有结果的,因此我们可以用变量来接受/print直接打印

转字符串

num_string = str(1110)
print(num_string,type(num_string))
# 整数转浮点数
num1 = float(int(10))
print(num1,type(num1))
# 浮点数转整数
num2 = int(float(10.43))
print(num2,type(num2))# 输出10
num3 = int(float(10.63))
print(num2,type(num3))# 输出10

由浮点数转换成整数时会丢失精度(小数部分)

标识符:

1.什么是标识符

①变量的名字

②方法的名字

③类的名字

内容限制:

英文(大小写敏感),中文(不推荐),数字(不能用在开头),下划线

不能使用关键字:

if   false  。。。。。

命名规范:

变量名:见名知意,下划线命名法(不同单词分割),英文字母全小写

类名:

方法名:

运算符:

算数运算符:

+,-,×,/除,//取整除,%取余,**指数。

print("11 / 5 = ",11 / 5)
print("11 // 5 = ",11 // 5)
print("9 % 2 = ",9 % 2)
print("2 ** 2 = ",2 ** 2)

字符串拓展:

字符串的定义:

1.单引号定义法:

2.双引号

3.三引号(和多行注释一样支持换行,使用变量接收时为字符串,不使用变量接收,多行注释)

name_1 = '张三'
name_2 = "李四"
name_3 = """王五"""
print(name_1,name_2,name_3)

如果定义的字符串本身,是包含单引号,双引号自身呢?

单引号里面可以含有双引号

双引号内可以含有单引号

可以使用转义字符\来将引号解除效果,变成普通字符串

name_1 = '"张三"'
name_2 = "'李四'"
name_3 = """'王五'"""
print(name_1,name_2,name_3)
name_1 = '\"张三'
name_2 = "\'李四\'"
name_3 = "\"'王五'\""
print(name_1,name_2,name_3)

字符串的拼接:

+(和Java一样)

name = "李太白"
print("人生得意须尽欢" + "莫使金樽空对月")
print("我名字是" + name)

字符串只能和字符串拼接(但是我们强转)

tel = 121321321312
print("我的电话是"+str(tel))

字符串格式化1:

占位

拼接字符串
class_num = 57
avg_salary = 16781
message = "Python大数据,北京%s期,工资:%s" % (class_num,avg_salary)
print(message)

%占位,s是代表以字符串的形式传递进来

数字和字符串:
class_num = 57
avg_salary = 16781
message = "Python大数据,北京%s期,工资:%s" % (class_num,avg_salary)
print(message)

%d:整型

%f:浮点型

name = "传智播客"
setup_year = 2006
stock_price = 19.99
message = "%s,成立于%d年,今天的股价是%.2f" % (name,setup_year,stock_price)
print(message)

格式化的精度控制:

m.n:

m:控制宽度,宽度小于自身不生效,在数字前面加空格

n:控制精度,会进行四舍五入

name = "传智播客"
setup_year = 2006
stock_price = 19.99
message = "%s,成立于%d年,今天的股价是%.1f" % (name,setup_year,stock_price)
print(message)

(四舍五入(大于5))

m:

name = "传智播客"
setup_year = 2006
stock_price = 19.99
message = "%s,成立于%d年,今天的股价是%7.1f" % (name,setup_year,stock_price)
print(message)

20.0是4位于是前面要加3位(先精度后宽度)

字符串格式化方式2:

快速写法:

f"内容{变量}"

name = "传智播客"
setup_year = 2006
stock_price = 9.99
message = f"{name}在{setup_year}年诞生,股票价格为:{stock_price}"
print(message)

表达式的格式化:

表达式:一条具有明确执行结果的代码语句

在无需使用变量进行数据存储的时候,可以直接格式化表达式,简化代码

print("1 * 1的结果为:%d" % (1 * 1) )
print(f"1 * 2的结果是:{(1 * 2)}")
print("字符串在python中的类型是: %s" % (type('dadadadad')))

input语句(函数):

键盘录入

print("告诉我你的名字")
name = input()
print(f"我的名字是{name}")

但是在python中这个print是多余的,我们可以直接在input中输入

name = input("Who are you?\n")
print(f"我的名字是{name}")

但是input语句无论你写入的是什么类型的数据,它都会当作是字符串(可以进行强转===)

DAY2

布尔类型:真假(bool)

True:1

False:0

比较运算符:

==

!=

>

<

>=

<=

bool_1 = True
bool_2 = False
print(f"bool_1的变量内容:{bool_1},类型是:{type(bool_2)}")
print(f"bool_2的:{bool_2}")

判断语句:

if基本格式:

if 要判断的条件:

    条件成立时,要做的事情

int(age) = input("请输入你的年龄\n")
  • 在 Python 中,int(age) 是一个表达式,它的作用是把 age 变量的值转换为整数。
  • 但赋值语句的左边必须是一个变量(比如 age),不能是表达式。
"""age = float(input("请输入你的年龄\n"))
if age >= 18:
    print("你已经成年了")
else:
    print("你还是未成年")
print("时间有点快")"""
age = input("请输入你的年龄\n")
if float(age) >= 18:
    print("你已经成年了")
else:
    print("你还是未成年")
print("时间有点快")

多条件的判断:

if 条件1:

    应作的事情

elif 条件2: 

    应作的事情

elif 条件3:

    应做的事情

else:

    所有条件不符合时做的事情

age = int(input())
if age > 18:
    print("你已经成年了")
elif age == 18:
    print("你刚刚成年,成年快乐")
else:
    print("你还是未成年")

elif语句可以写多个

判断是互斥且有顺序的,只有所有的elif都不满足,才会运行else语句

else可以省略不写(不满足条件就不执行)

嵌套判断语句

空格缩进

python中是通过空格缩进来决定语句之间的关系

num_1 = int(input("请输入一个整数"))
if num_1 > 0:
    print("这个数字是正数")
    if num_1 > 50:
        print("这个数字大于50")
    else:
        print("这个数字小于50")
else:
    print("这个数字是负数")

DAY3循环语句

while

语法:

while 条件:                 (这个条件可以是比较或者是布尔类型,总之结果要是true

条件满足时,做的事情1

条件满足时,做的事情2

条件满足时,做的事情3

           ................

num_1 = int(input("输入一个整数"))
while num_1 < 100:
    print("Hello World")
    num_1 += 1

注意:

python中没有自增/自减符号

1-100的合

num_1 = 1
num_2 = 0
while num_1 <= 100:
    num_2 += num_1
    num_1 += 1
print(num_2)

while的嵌套:

主要就是注意缩进

i = 1
while i <= 100:
    print(f"今天是我像小美表白的第{i}天。。。")
    i += 1
    j = 1
    while j <= 10:
        print(f"这是我送出去的第{j}朵玫瑰花")
        j += 1
    print("小美我喜欢你")
print(f"到了{i-1}天我们在一起了")

不换行:

print("hello")
print("world")
print("hello " , end = '')
print("world" , end = '')

制表符:\t

打印99乘法表
# 打印99乘法表
i = 1
while i <= 9:
    j = 1
    while j <= i:
        print(f"{j} * {i} = {i * j}\t ", end='')
        j += 1
    i += 1
    print()

for(轮询,遍历循环)

语法:

for 临时变量 in 待处理数据集:

    循环满足条件时执行的代码

name = "dwadadadawda"
for x in name:
    print(x)

与while循环的区别:

for循环无法定义循环条件(只能从一个数据集中不断取出数据,因此理论上无法无限for循环)

数数一串字符串中有几个a:

word = "day same gogogo aaa abc fi a"
num = 0
for char in word:
    if char == "a":
        num += 1
print(f"有{num}个a")

变量的作用域:

for i in range(10):
    print(i)
print(i)
#可以输出但是规范上不建议

darange 语句:

帮助我们构建一个数字序列

range的用法

for num in range(100): #生成[0-100)含左不含右"""
    print(num)
for num in range(50,100):#生成【num1-num2)也是含左不含右
    print(num)
for num in range(100,1000,100):#step = 100
    print(num)

待处理的数据集严格意义上被称为序列类型

序列类型:其内容可以被一个个依次取出的一种类型,包括:

  • 字符串
  • 列表
  • 元组
  • 等等

循环中断:break   和    continue

continue:

跳出本次循环

for i in range(10):
    if i ==6:
        continue
    print(i)

break:

直接跳出循环

for i in range(10):
    if i ==6:
        break
    print(i)

DAY4函数

函数:

是组织好的可重复使用的,用来实现特定功能的代码段

#输出长度
name = "we are the world"
length = len(name)
print(length)

函数的定义:

def 函数名(传入参数):

      函数体

      return 返回值

def print1():
    print("hello world")

print1()

注意:

①参数如果不需要,可以省略

②返回值不需要,可以省略

③函数必须先定义后使用

函数的参数:

函数的传入参数:在函数进行计算的时候,接受外部(调用时)提供的数据

def add(x,y):
    result = x + y
    return result
print(add(1,2))

x,y为形参

调用函数的1,2称为实参,为我们使用的参数值

传入参数的数量是不受限制的。

  • 可以不使用参数
  • 也可以仅使用任意N个参数

函数的返回值:

函数运行后的结果

def 函数(参数......):

         函数体

        return 返回值

变量 = 函数(参数)

注意:当函数体遇到return时就停止运行,return后面的代码就不执行了

def add(x,y):
    result = x + y
    return result
num = add(5,67)
print(num)

None类型:

无返回值的函数,实际上就是返回了:None这个字面量

①.我们不写return返回值时,就返回None

②.我们可以主动return None

def print1():
    print("hello world")

result = print1()
print(f"无返回值的函数的结果是{result}")
print(f"其数据类型是{result}")

#hello world
#无返回值的函数的结果是None
#其数据类型是None

None作为一个特殊的字面量,用于表示:空、无意义,有很多应用场景。

  • 用在函数无返回值上
  • 用在if判断上(None等同于False)
  • 一般用于函数中主动返回None,配合if判断做相关处理
  • 用于声明无内容的变量上
  • 定义变量,但暂时不需要变量有具体值,可以用None来代替
  • name = None#暂时不赋予变量具体的值
def check_age(age):
    if age >= 18:
        return "SUCCESS"
    else:
        return None
result = check_age(16)
if not result:
    print("未成年")

注意:在python中

  • Python 无单独的!取反运算符,逻辑布尔取反用 **not关键字 **(最常用);
  • 整数二进制按位取反用 **~符号 **(数值操作,新手少用);
  • !在 Python 中仅和=组合为!=,表示不等于判断

函数的说明文档:

辅助理解函数的作用

用多行注释写在函数体之前

def add(x,y):
    """
    add函数可以接受两个参数,进行2数的相加
    :param x: 形参x表示相加的其中一个数
    :param y: 形参y表示相加的另一个数
    :return: 返回值是2数相加的结果
    """
    result = x + y
    print(f"两数相加的结果是:{result}")
    return result

函数的嵌套调用:

在一个函数中又调用了另一个函数

def func_b():
    print("func_b")
def func_a():
        print("func_a")
        func_b()
        print("232323232323")
func_a()

a函数里调用b函数

函数中的变量的作用域:

变量的作用域指的是变量的作用范围

局部变量:

定义在函数体内部的变量,即只在函数体内部生效

当函数调用完之后

局部变量会被销毁

全局变量:

在函数体内体外都能够发挥作用的变量

#在函数内修改全局变量
num = 200
def test_a():
    print(f"test_a:{num}")


def test_b():
    num = 500
    print(f"test_b:{num}")
test_a()
test_b()
print(num)

原因是因为,函数内部的num变量我们就将其看作一个新的局部变量了(因此这个函数内部的num与函数外的没有关系)

我们应该如何在函数内去修改函数外的全局变量呢?

global关键字

#在函数内修改全局变量
num = 200
def test_a():
    print(f"test_a:{num}")


def test_b():
    global num#global关键字声明其为全局变量
    num = 500
    print(f"test_b:{num}")
test_a()
test_b()
print(num)

DAY5数据容器

了解数据容器:

一个变量,能够存储多份数据

一种可以容纳多份数据的数据类型,容纳的每一份数据称之为一个元素,每一个元素,可以是任意类型,如字符串、数字、布尔。

list(列表):

列表一次可以存储多个数据

语法:

字面量[元素1,元素2,元素3,。。。。。]

#定义变量

变量名称 = [元素1,元素2.。。。。]

#定义空列表

变量名称 = []

变量名称 = list()

元素:

列表中的每一个数据,称之为元素,元素类型不受限 

  • 以【】作为标识
  • 列表内每一个元素之间用,分隔开
name_list = ["vbfbfbfdbdf","cast","dadwdadsa"]
print(name_list)
print(type(name_list))

#列表的嵌套
my_list = [[1,2,3],[4,5,6]]
print(my_list)
print(type(my_list))

列表的下标(索引):

按照下表索引,获取对应位置的元素

可以从左向右(0),也可以从右向左(-1)

name_list = ['Tom','dadada','cscs']
print(name_list[2])
print(name_list[-1])
print(name_list[1])
print(name_list[-2])
print(name_list[0])
print(name_list[-3])

列表的嵌套

my_list = [["Tom","Lily","Rose"],["Jack","Donk","danking"]]
print(my_list)
print(my_list[0][2])
print(my_list[1][1])

注意:用索引取数据,不要超过范围

常用操作:

方法介绍:

函数是一个封装的代码单元,可以提供特定的功能

在python中,如果将函数定义为class(类)的成员,那么函数会称之为:方法

方法和函数只是写的位置不一样,使用的格式不一样

函数的使用: num = add(1,2)

方法的使用:student = Student()

                    num = student.add(1,2)

列表的查询功能:

语法:列表.index(元素)

my_list = [["Tom","Lily","Rose"],["Jack","Donk","danking"]]
print(my_list)
print(my_list.index(["Tom","Lily","Rose"]))

如果查询的元素不存在,会报错

修改特定位置(索引)的元素值:

语法:列表[下标] = 值

my_list = ["Tom","Lily","Rose"]
print(my_list)
my_list[0] = "Jack"
print(my_list)
插入元素:

语法:列表.insert(下标,元素),在指定的下标位置,插入指定的元素

my_list = ["Tom","Lily","Rose"]
print(my_list)
my_list.insert(1,"marry")
print(my_list)
元素的追加(添加)

1.追加一个元素

语法:列表.append(元素),将指定元素,追加到列表的尾部

my_list = ["Tom","Lily","Rose"]
print(my_list)
print(my_list.append("MIKE"))
print(my_list)

2.如果我们追加一批元素

语法:列表.extend(其他数据容器),将其它数据容器的内容取出,一次追加到列表尾部

my_list = ["Tom","Lily","Rose"]
print(my_list)
my_list.extend(["Tom","Lily","Rose"])
print(my_list)

my_list = ["Tom","Lily","Rose"]
print(my_list)
my_list.extend(["Tom","Lily","Rose"])
print(my_list)
my_new_list = ["Tom","Lily","Rose"]
my_list.extend(my_new_list)
print(my_list)

元素删除:(下标)

语法1:del 列表[下标]

语法2:列表.pop(下标)//pop方法可以有返回值,并且可以有一个变量去接收

my_list = [1, 2, 3]
del my_list[2]
print(my_list)
num = my_list.pop(1)
print(my_list)
print(num)
删除第一个匹配项:

语法:列表.remove(元素)

(只能删除一个)

my_list = [1, 2, 3,2,32,4343,2,4]
print(my_list)
my_list.remove(2)
print(my_list)

列表清空:

语法:列表.clear()

my_list = [1, 2, 3,2,32,4343,2,4]
print(my_list)
my_list.remove(2)
print(my_list)
my_list.clear()
print(my_list)

统计某元素在列表内的数量:

语法:列表.count(元素)

my_list = [1, 2, 3,2,32,4343,2,4]
print(my_list.count(2))
统计列表内总共有多少元素:

语法:len(列表)

my_list = [1,23,343,234,12,345]
count = len(my_list)
print(count)
总结:

常用功能的练习:
#有一个列表记录学生的年龄[21,25,21,23,22,20]
#1.定义这个列表并且用变量来接收它
age_list = [21,25,21,23,22,20]
#2.追加一个数字31,到列表尾部
age_list.append(31)
print(age_list)
#3.追加一个新列表[29,33,30],到列表的尾部
new_list = [29,33,30]
age_list.extend(new_list)
print(age_list)
#4.取出第一个元素(21)
print(age_list[0])
#5.取出最后一个元素(30),可以使用负数索引
print(age_list[len(age_list)-1])
print(age_list[-1])
#6.查找元素31,在列表中的下标位置
x = 0
for i in age_list:
    if i == 31:
        print(f"元素31所在的位置是{x}")
    else:
        x += 1
index = age_list.index(31)
print(index)
#我忘记index了

DAY6LIST列表的遍历:

将容器中的元素依次取出进行处理的行为,称之为:遍历、迭代

1.while循环的遍历

 语法:

index = 0

while index < len(列表):

           元素 = 列表[index]

          对元素处理

         index += 1

#while循环
my_list = [1,2321,54,68,23,65,1,5647]
index = 0
while index < len(my_list):
    element = my_list[index]
    print(element,end = ' ')
    index += 1
print("\n")
#for循环
index = 0
for element in my_list:
    print(element,end = ' ')
    index += 1

while循环和for循环,都是循环语句,但细节不同:

  • 在循环控制上:
  • while循环可以自定循环的条件,并且自行控制
  • for循环不可以自定循环,但可以一个个从容器内取出数据
  •  在无限循环上:
  • while循环可以通过条件控制做到无限循环
  • for循环理论上不可以,因为被遍历的容器容量不是无限的
  • 在使用场景上:
  • while循环适用于任何想要循环的场景
  • for循环适用于,遍历数据容器的场景或简单的固定次数循环场景

2.元组:

如果想要传递的信息,不想被篡改,列表就不合适了

元组和列表一样,都是可以分装多个、不同类型的元素在内。

但不同点:

元组一旦定义完成,就不可修改 

(元组就是一个只读的list)

定义元组:

定义元组使用小括号,且使用都好隔开各个数据,数据可以是不同的数据类型。

#定义元组字面量

(元素1,元素2,元素3.。。。。。)

#定义元组变量

变量名称 = (元素,元素,。。。。。。。,元素)

#定义空元组

变量名称 = () #方式1

变量名称 = tuple() #方式2

my_tuple = ("1","dada","Hello",1,True)
print(my_tuple)

注意:

如果元组里面只有一个字符串内容,在内容后面要加个,

t1 = ("hello")
print(type(t1))
t2 = ("hello",)
print(type(t2))

如果不加逗号就不是元组类型

元组的嵌套:

t5 = ((1,2,3),(3,4,5))
print(type(t5))

用下标去取元素:(和list一样)

t5 = ((1,2,3),(3,4,5))
num = t5[1][2]
print(num)

操作:(元组不可修改)

t6 = (12,32,534534,75647,786,12,32,12,54,12)
print(t6.index(12))
print(t6.count(12))
print(len(t6))
index = 0
while index < len(t6):
    print(t6[index],end = ' ')
    index += 1
print("\n")
for i in t6:
    print(i,end = ' ')

修改元组内容:

t6[0] = 1000
print(t6)

TypeError: 'tuple' object does not support item assignment

元组内容不支持修改

特例:

我们可以修改元组内部的list的内容

因为list没有发生改变,改变的只是list内部的内容

t6 = (232,432,["dada","2354534"])
t6[2][1] = 1
print(t6)

字符串的定义和操作:

字符串也算是容器

每一个字符都是一个容器的元素

并且可以使用下标

my_str = "hello world"
print(my_str[0])
print(my_str[-11])
#都可以取到h

字符串和元组一样都是无法修改的容器

字符串的替换:replace:

功能:替换字符串中的「指定子串」,不是替换整个字符串!

注意:

不是修改字符串本身,而是我们得到了一个新的字符串

(相当于会返回一个字符串(因为字符串不能修改)

my_str = "hello world"
new_str = my_str.replace("hello","你好")
print(my_str)
print(new_str)

只替换我们需要替换的部分

字符串的分割:split

语法:字符串.split(分割符字符串)

功能:按照指定的分割符字符串,将字符串划分为多个字符串,并存入列表对象

注意:字符串本身不变,而是得到了一个列表对象

my_str = "hello world hi da daw2ef"
my_str_list = my_str.split(" ")
print(my_str_list)

字符串的规整操作strip

去前后空格,以及回车符

语法:字符串.strip()

去除前后指定的字符串

语法:字符串.strip(字符串)

my_str = "  hello world hi da daw2ef   "
new_str = my_str.strip()
print(new_str)
my_str1 = "  hello world hi da daw2ef   "
my_str2 = "hello"
new_str = my_str1.strip(my_str2)
print(new_str)
my_str3 = "hello world hi da daw2ef   "
new_str = my_str3.strip(my_str2)
print(new_str)

说白了就是从前或者从后开始匹配然后去除,当遇到第一个匹配不到的字符时就停止

因为 my_str2 = "hello"strip() 会把它拆解成字符集合 {'h','e','l','o'}(重复的 l 会自动去重)。

统计字符串中某个字符串出现的次数:count

统计字符串的长度:len

字符串的遍历:while循环和for循环

这三个函数和前面的用法一模一样就不进行代码展示了

总结:

字符串的特点:

  • 只可以存储字符串
  • 长度任意(取决于内存大小)
  • 支持下标索引
  • 允许重复字符串存在
  • 不可以修改(增加或删除元素)
  • 支持for循环

练习:

#给定一个字符串:"we are all in the gutter,but some of us are looking at the stars"
#统计有多少个t
my_str = "we are all in the gutter,but some of us are looking at the stars"
print(f"t一共有{my_str.count("t")}个")
#将字符串空格全部替换为"|"
new_str = my_str.replace(" ","|")
print(new_str)
#按照|进行分割得到列表
new_str2 = my_str.split("|")
print(new_str2)

DAY7:数据容器(序列)的切片操作

序列:

内容连续,有序,可使用下标索引的一类数据容器

列表、元组、字符串,均可以视为序列

操作:

切片:

从一个序列中,取出一个子序列

语法:序列[起始下标:结束下标:步长]

表示从序列中,从指定位置开始,依次取出元素,到指定位置结束,得到一个新序列

结束下标是不包含,如果留空则到结尾 ,起始和结束都不写,表示从头到尾,步长为1可以省略

步长:

  • 步长为1,一个一个取元素
  • 2,每次跳过一个元素取 
  • 步长为N,每次跳过N-1个元素取
  • 步长为负数,表示反向取(注意,起始下标和结束下标也要反向标记)

注意:

切片的操作不会影响序列本身,而是会得到一个新的序列(元组和字符串都是不支持修改的)

#对list进行切片,从1开始,4结束,步长为1
my_list = [0,1,2,3,4,5,6,7,8,9]
my_new_list = my_list[1:4]#结束的开区间,步长默认为1所以可以不写
print(my_new_list)


#对tuple进行切片,从头开始,到最后结束,步长为1
my_tuple = (1,2,3,4,5,6,7,8,9)#元组是小括号
my_new_tuple = my_tuple[:]#起始和结束为空时就自动从头到末尾,步长为1可以省略
print(my_new_tuple)


#对str进行切片,从头开始,到最后结束,步长为2
my_str = "dwfeshbtdgrdgdgdgdrg"
my_new_str = my_str[::2]
print(my_new_str)


#对str进行切片,从头开始,到最后结束,步长为-1
my_str1 = "1dadadadsxaxaxaxa65"
my_new_str1 = my_str1[::-1]#等同于将序列反转了
print(my_new_str1)


#对列表进行切片,从3开始,到1结束,步长为-1
my_list = [1,2,3,4,5,6,7,8,9]
my_new_list = my_list[3:1:-1]
print(my_new_list)


#对元组进行切片,从头开始,到位结束,步长为-2
my_tuple = (1,2,3,4,5,6,7,8,9)
my_new_tuple = my_tuple[::-2]
print(my_new_tuple)

总结:

  1. 起始和结束为空时就自动从头到末尾(结束是开区间)
  2. 步长为1可以省略
  3. 步长为-1,等同于将序列反转了
  4. 从头开始,末尾结束直接省略开头和结尾

案例:

#案例需求:ogogog,}!FTC!OLLEH{galf,yppah倒序过来,取出flag
str = "ogogog,}!FTC!OLLEH{galf,yppah"
str1 = str[::-1]
print(str1)
str2 = str1.split(",")#逗号会把原来的str变成被逗号分割的不同str
print(str2[1])

 集合:

我们已经学习了列表、元组、字符串三个数据容器了

为什么要学习集合呢?

1、列表可修改、支持重复元素且有序

2、元组、字符串不可修改、支持重复元素且有序

集合:

特点

自带去重处理且内容无序

列表:[]

元组:()

字符串:""

集合:{}

语法:

#定义集合字面量

{元素,元素,................,元素}

#定义集合变量

变量名称 ={元素,元素,................,元素}

#定义空集合‘

变量名称 = set()

my_set = {212,3213,5435,7657,7657,7657,212,True,"7657",True}
print(my_set)
print(type(my_set))



集合的常见操作:

1、因为集合是无序的,因此不支持下标索引访问

修改:

  • 添加元素:add()
  • 移除元素:remove(元素)
  • 随机取出一个元素pop()
  • 清空集合:clear()
  • 取2个集合的差集:集合1.difference(集合2),功能:取出集合1有但是集合2中没有的元素(会得到一个新的集合,集合1和集合2不变)
  • 消除2个集合的差集:集合1.difference_update(集合2)在集合1中消除和集合2中相同的元素(集合1会发生变化,集合2不会发生变化)
  • 2个集合并为1个集合:集合1.union(集合2)(原来的2个集合都不变,直接返回一个新的集合)
  • 统计集合元素的数量:len(集合)
  • 集合的遍历:for循环(while不可用)

练习:

#我们有如下的列表
my_list = ['a',"dadw","w","dadwa","dadwa",23232]
#定义一个空集合
my_set = set()
#通过for循环遍历列表
for element in my_list:
    my_set.add(element)

print(my_set)

字典:

需要通过学生的姓名来检索学生的成绩

使用字典最为合适

定义:

字典的定义,同样是使用{},不过存储的元素是一个个的:键值对

#定义字典字面量

{key: value,key: value,...........}

#定义字典变量

my_dict = {key: value,key: value,...........}

#定义空字典

my_dict = {}#方式1

my_dict = dict()#方式2

#定义字典
my_dict = {"小王":99,"小花":88,"小绿":22}
#定义空的字典
my_dict2 = {}#定义空字典时需要set(),因为{}被字典占用了
my_dict3 = dict()
print(my_dict)
#定义重复key的字典
my_dict4 = {"小王":99,"小花":88,"小绿":22,"小王":54}
print(my_dict4)

后面的key会把前面的key覆盖掉

因为python的字典不允许重复

字典可以通过key值来获取对应的value

my_dict = {"小王":99,"小花":88,"小绿":22}
score = my_dict["小王"]
print(score)

字典的嵌套:

  1. 字典的key和value可以是任意数据类型(key不可为字典)

那么就表示字典是可以嵌套的 

stu_score_dict = {
    "小王":{
        "语文":77,
        "数学":88
    },"小红":{
        "语文":79,
        "数学":98
    },"小黄":{
        "语文":66,
        "数学":22
    }
}
print(stu_score_dict)
#如何获取信息
score = stu_score_dict["小王"]["语文"]
print(score)

字典的常用操作:

1.新增元素:

语法:

字典[key] = value,结果:字典被修改,新增了元素

2、更新元素

语法:

字典[key] = value , 结果:字典被修改,元素被更新

字典key不可以重复,所以对已存在的key执行上述操作,就是更新value值

3、删除元素:

语法:

字典:pop(key),结果:获得指定key的value,同时字典被修改,指定key的数据被修改

4、清空字典:

语法:

字典.clear()

5、获取全部的key

语法:

字典.keys()      结果:得到字典中的全部key

6、遍历字典

语法:

for循环

7、统计字典内的元素数量

语法:

len(字典)

my_dict = {"小周":323,"小李":88,"小黄":99}
#新增元素
my_dict["小张"] = 87
print(my_dict)
#更新元素
my_dict["小周"] = 33
print(my_dict)
#删除元素
score = my_dict.pop("小周")
print(my_dict)
#清空元素
my_dict.clear()
print(my_dict)
#获得全部的key
my_dict = {"小周":323,"小李":88,"小黄":99}
temp = my_dict.keys()
print(temp)
#遍历字典
#方式1
for key in my_dict.keys():
    print(f"字典的key是{key}")
    print(f"字典的value值是{my_dict[key]}")
#方式2
for key in my_dict.keys():
    print(f"字典的key是{key}")
    print(f"字典的value值是{my_dict[key]}")
#统计字典内的元素数量
print(len(my_dict))

注意:

对value的修改和添加就是对重复值的覆盖

小练习:

com_dict = {
    "小王":{
        "部门":"科技部",
        "工资":3000,
        "级别":1
    },
    "小周":{
        "部门":"市场部",
        "工资":5000,
        "级别":2
    },
    "小李": {
        "部门": "市场部",
        "工资": 7000,
        "级别": 3
    },
    "小张":{
        "部门": "科技部",
        "工资": 4000,
        "级别": 1
    },
    "小刘": {
        "部门": "市技部",
        "工资": 6000,
        "级别": 2
    }
}
print(com_dict)
for k in com_dict.keys():
    if com_dict[k]["级别"] == 1:
        com_dict1 = com_dict[k]
        com_dict1["工资"] += 1000
        com_dict1["级别"] += 1

print(com_dict)

注意:

我们在遍历时,可以先将最外层的字典赋值给一个变量,这样我们就可以直接传第二个key‘给这个变量了

容器总结:

1、是否支持下标索引:

支持:列表、元组、字符串

不支持:集合、字典

2、是否支持元素重复

支持:列表、元组、字符串

不支持:集合、字典

3、是否可以修改

支持:列表、集合、字典

不支持:元组、字符串

数据容器的通用操作:

len(容器):元素的个数

max(容器):元素的最大值

min(容器):元素的最小值

my_list = [1,2,3,4,5,6,7,8,9]
my_tuple = (1,2,3,4,5,6,7,8,9)
my_str = "dadadadw"
my_set = {1,2,3,4,5,6,7,8,9}
my_dict = {
    "key1":1,
    "key2":2,
    "key3":3,
    "key4":4,
    "key5":5
}
#len元素个数
print(len(my_list))
print(len(my_tuple))
print(len(my_str))
print(len(my_set))
print(len(my_dict))
#max最大元素
print(max(my_list))
print(max(my_tuple))
print(max(my_str))
print(max(my_set))
print(max(my_dict))
#min最小元素
print(min(my_list))
print(min(my_tuple))
print(min(my_str))
print(min(my_set))
print(min(my_dict))
#容器转列表
print(list(my_list))
print(list(my_tuple))
print(list(my_str))
print(list(my_set))
print(list(my_dict))
#容器转元组
print(tuple(my_list))
print(tuple(my_tuple))
print(tuple(my_set))
print(tuple(my_dict))
#转字符串
print(str(my_list))
print(str(my_tuple))
print(str(my_set))
print(str(my_dict))
#转换成集合
print(set(my_list))
print(set(my_tuple))
print(set(my_set))
print(set(my_dict))
#对容器进行排序
print(sorted(my_list))
print(sorted(my_list,reverse=True))

排序:

sorted(my_list,reverse=True)

reverse默认值是false,默认情况下是从小到大

改为true之后就是从大到小

字符串的大小比较原理:

ASCII码表

实际上就是比较ASCII码表

a:97

A:65

字符串是按位比较,就是一位位进行比对,只要有一位大,那么整体大

DAY8函数多返回值

注意:

执行第一个return之后就退出函数了

返回多个值:

return多个值

  1. 按照返回值的顺序,写对应顺序的多个变量接受
  2. 变量之间用逗号隔开
  3. 支持不同类型的数据return
def test_return():
    return 1,2,"dadada"
x,y,z = test_return()
print(x,y,z)


函数的多种传参方式:

位置参数:

调用函数时根据函数定义的参数位置来传递参数

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

def user_info(name,age,gender):
    print(f"您的名字是{name},年龄是{age},性别是{gender}")
user_info("TOM",67,"男")

关键字参数:

函数调用时通过“键 = 值”的形式传递参数

可以让函数更加清晰、容易使用,同时也清楚了参数的顺序需求

def user_info(name,age,gender):
    print(f"您的名字是{name},年龄是{age},性别是{gender}")
user_info("TOM",67,"男")
#关键字传参可以不按照固定的顺序
user_info(name = "tom",gender = "男",age = 87)
#可以和位置参数混用,位置参数必须在前面,且匹配参数顺序
user_info("TON",gender = "男",age = 33)
#关键字传参可以不按照固定的顺序
#可以和位置参数混用,位置参数必须在前面,且匹配参数顺序

缺省参数:

缺省参数也叫默认参数,用于定义函数,为参数提供默认值,调用函数时可不传该默认参数的值

(注意:所有位置参数必须出现在默认参数前,包括函数定义和调用)

作用:

当调用函数时没有传递参数,就会使用默认是用缺省参数对应的值

def user_info(name,age,gender = "男"):
   print(f"您的名字是{name},年龄是{age},性别是{gender}")
user_info("TONM",232)

这个默认值也可以通过手动传入来进行覆盖

设置默认值必须在最后

不定长参数(可变参数):

位置传递的不定长:

传进的所有参数都会被args变量手机,他会根据传入参数的位置合并为一个元组(tuple),args是元组类型,这就是位置传递

def user_info(*args):
   print(args)
user_info(1,2,3,4,5)
关键字传递:

参数是“键=值”形式的情况下,所有的键值都会被kwargs接受,同时会根据键值组成字典

def user_indo(**kwargs):
    print(kwargs)
user_indo(name = "小王",age = 20,id = 111)

匿名函数:

在之前的函数学习中,我们所使用的函数,都是接受数据作为参数传入

其实,我们也可以将函数本身作为参数传入另一个函数中

def test_func(compute):
    result = compute(1,2)
    print(result)
def compute(x,y):
    return x+y
test_func(compute)

这个代码中也可以不传

def test_func():
    result = compute(1,2)
    print(result)
def compute(x,y):
    return x+y
test_func()

我们之前的是数据确定,计算逻辑不确定

现在是数据不确定,但是逻辑是确定的

这是计算逻辑的传递,而不是数据的传递。

lambda匿名函数:

  • def关键字,可以定义带有名称的函数
  • lambda关键字,可以定义匿名函数(无名称)

有名称的函数,可以基于名称重复使用

无名称的匿名函数,只能临时使用一次

语法:

lambda 传入参数:函数体(一行代码)

  • lambda是关键字,表示定义匿名函数
  • 传入参数表示匿名函数的形式参数,如:x,y表示接受2个形式参数
  • 函数体,就是函数的执行逻辑,要注意:只能写一行,无法写多行代码
def test_func(com):
    result = com(1,2)
    print(result)
def compute(x,y):
    return x+y
test_func(lambda x,y : x +y)

lambda函数就是直接返回return

DAY9文件的操作

1、文件编码以及常见的编码

计算机只能识别0和1,那我们的文本计算机是怎么识别并且存储在硬盘中的呢?

使用编码技术将内容翻译成0和1存入

 可用的编码技术:

  • UTF-8:全球比较通用
  • GBK:中文
  • Big5:繁体字
  • .。。

不同的编码也就是不同的密码本

2、文件的读取

文件的操作:打开、关闭、读、写

打开文件:

open(naem,mode,encoding)打开函数

name:是要打开的 目标文件名号的字符串(具体路径)

mode:设置打开文件的模式(访问模式):只读、写入、追加等等。

encoding:编码格式(UTF-8)

相关的方法:

文件对象.read(num)

num表示要从文件中读取的数据的长度(单位是字节),如果没有传入num,那么就表示读取文件的所有数据

readlines()方法:

可以按照行的方式把整个文件中的内容进行一次性读取,并且返回的是一个列表,其中每一行的数据为一个元素

如果我们多次调用read函数那么我们下一次调用read函数会从上一次的结尾进行读取

文件读取的时候其实是有一个指针的

readline()方法:一次读取一行内容

for循环读取文件每一行

for line in 文件的对象:

         print..........

close()关闭文件对象

关闭文件对象,也就是关闭对文件的占用

如果不调用close,同时程序没有停止运行,那么整个文件将一直被python程序占用

with open 语法操作文件

在执行完语句之后,可以自动关闭文件

import time
#打开文件
f = open("D:/test.txt","r",encoding="utf-8")
print(type(f))
#读取文件-read()
# print(f.read())#读取全部内容
# print(f.read(10))#读取十个字节
#读取文件-readLines()
# line_list = f.readlines()#读取的文件的全部行,然后封装在列表中
# print(f"lines的对象的类型是{type(line_list)}")
# print(line_list)
#读取文件-readline()
# print(f.readline())
#for循环读取文件行
for line in f:
    print(line)
#文件的关闭
f.close()
#with open 语法操作文件
with open("D:/test.txt","r",encoding="utf-8") as f:
    for line in f:
        print(line)
time.sleep(36000)

练习:

统计hello出现的次数

#方式1直接读取全部内容
f = open("D:/test.txt","r",encoding="utf-8")
print(f.read().count("hello"))#直接统计
f.close()
#方式2一行一行的读取
with open("D:/test.txt","r",encoding="utf-8") as f:
  count = 0
  for line in f:
    line = line.strip()#直接去除开头或结尾的空格或者换行符
    words = line.split(" ")
    for word in words:
        if word == "hello":
            count += 1
print(count)

文件的写入操作:

write方法

f.write("hello ,world")

1、打开文件 ‘w'

2、文件写入

3、内容刷新

直接调用write方法,内容并未真正写入文件,而是会积攒在程序的内存中,称之为缓冲区

避免频繁的操作硬盘,导致效率下降

f = open("D:/TXT.txt","w",encoding= "UTF-8")
#f.write("hello,world")#内容写入到内存中
#f.flush()#将内存中积攒的内容,写入到硬盘中的文件中
#f.close()#close方法,内置了flush功能
#打开一个存在的文件
f.write("是不是前面的内容被覆盖了")
f.close()

注意:

如果文件不存在,它会创建文件,之后将内容写入,如果文件已经存在,就会清空原有内容,然后再写入内容(相当于将原本内容覆盖了)

追加写入操作:

将打开文件时的“w”该换成“a“就行了

(a就是add)

注意:

如果文件不存在,就会创建然后写入,如果文件存在,就会再后面追加

f = open("D:/HELLP.txt","a",encoding="utf-8")
f.write("hello world")
f.write("hello world")
f.write("hello world")
f.close()

如果我们想要换行写入

f = open("D:/HELLP.txt","a",encoding="utf-8")
f.write("hello world")
f.write("\nhello world")
f.write("hello world")
f.close()

如果是这样:

f = open("D:/HELLP.txt","a",encoding="utf-8")
f.write("hello world\n")
f.write("\nhello world")
f.write("hello world")
f.close()

DAY10python异常、模块、包

 当检测到一个错误时,python解释器就无法继续执行了,反而出现了一些错误的提示,这就是所谓的异常,也就是bug

为什么要捕获异常?

对可能出现的异常,进行提前准备,当真正出现异常的时候,可以有后续手段。

基本语法:

try:

可能出现错误的代码

except:

如果出现异常时执行的代码

try:
    f = open("D:/abc.txt","r",encoding="utf-8")
except:
    print("出现异常了,因为文件不存在,我将open的模式,改为w模式去打开")
    f = open("D:/abc.txt","w",encoding="utf-8")

捕获指定异常:

基本语法:

try:

print(name)

except NameError as e:

print(‘name变量名未定义错误’)

#捕获指定的异常
try:
    print(name)
except NameError as e:
    print("出现了变量未定义的异常")
    print(e)

我们可以用as设置对象渠道,进行直接打印(可以把e当作一个变量)

捕获多个异常:

语法:

try:

print(1/0)

except(NameError,ZeroDivisionError):

print('.....')

通过写入一个元组,用逗号隔开

#捕获多个异常
try:
    print(name)
    print(1/0)
except (NameError, ZeroDivisionError):
    print("出现了变量未定义 或者 除以0的异常错误")

捕获全部异常:

try:
    print(name)
    print(1/0)
except Exception as e:
    print("出现异常了")
try:
    print(name)
    print(1/0)
except:
    print("出现异常了")

这两种写法是一样的(Exception是顶级异常)

异常else:

else是表示如果没有异常要执行的代码。

try:
    print("hello world")
except Exception as e:
    print("出现异常了")
else:
    print("没有异常")

可以写也可以不写

异常的finally:

finally表示的是无论是否异常都要执行的代码,例如关闭文件。

try:
    print("hello world")
except Exception as e:
    print("出现异常了")
else:
    print("没有异常")
finally:
    print("hello world pro max")
try:
    f = open("D:/123.txt","r",encoding="utf-8")
except Exception as e:
    f = open("D:/123.txt","w",encoding="utf-8")
else:
    print("没有异常")
finally:
    f.close()

异常的传递:

 异常是具有传递性的

def func01():
    print("这是func01的开始")
    num = 1 / 0
    print("这是func01函数的结束")
def func02():
    print("这是func02的开始")
    func01()
    print("这是func02函数的结束")

def main():
    try:
        func02()
    except Exception as e:
        print(f"出现异常了,异常的信息是{e}")

main()

python的模块:

什么是python的模块:

python模块(Module),是一个python文件,以.py结尾,模块能定义函数,类和变量,模块里也能包含可执行的代码。

模块的作用:

可以帮助我们快速实现一些功能,一个模块就是一个工具包

语法:

[from 模块名] import [模块 | 类 | 变量 | 函数 | *] [as 别名]

(【】内表示可选内容)

常用的组合形式:

  • import 模块名
  • from 模块名 import 类、变量、方法等
  • from 模块名 import *
  • import 模块名 as 别名
  • from 模块名 import 功能名 as 别名

import模块名:

基本语法:

import 模块名

import 模块名1,模块名2

模块名.功能名()

#使用import导入time模块使用sleep功能(函数)
import time#导入python内置的time模块
print("你好")
time.sleep(5)#time内部的sleep功能
print("hello world")

通过.就可以使用模块内部的全部功能(类、函数、变量)

from 模块名 import 功能名

基本语法:

from 模块名 import 功能名

功能名()

from time import sleep
print("hello world")
sleep(5)
print("hello world agin")

from 模块名 import *

基本语法:

from 模块名 import *

功能名()

from time import *
sleep(5)

和第一种的效果相同,只不过写法不一样

as别名定义

基本语法:

#模块定义别名

import 模块名 as 别名

#功能定义别名

form 模块名  import 功能 as 别名

import time as t
t.sleep(1)
from time import sleep as sl
sl(5)

就是为了改名字,防止有写模块及其功能的名字太长不便使用

自定义模块

注意:

每个python文件都可以作为一个模块,模块名就是文件的名称,也就是说定义模块名必须符合标识符的命名规则

import my_module1
my_module1.test(676,54)

必须要在同一个文件夹下

导入不同模块下的同名功能,后面的会覆盖前面的

def test(a,b):
    print(a+b)

if __name__ == '__main__':
    test(1, 2)

这种情况下我们既保留了测试的函数,又在调用模块的时候不会执行测试函数

(__name__叫做内置变量,当我们运行时,内置变量就会变成__main__然后if的判断就会变成true于是执行test,在from的时候内置变量不会被赋值也就不会执行)

__all__变量:

如果一个模块文件中有_all_变量,当使用from时候就只能导入这个列表中的元素

__all__ = ["test_A"]
def test_A():
    print("test_A")
def test_B():
    print("test_B")

我们写*的时候是把所有的都导入进来,但是当我们写了__all__之后,我们能导入进来哪些会受到

__all__控制,我们手动导入不受影响

python包:

自定义包:

如果我们python的模块太多了,就可能会造成一定的混乱,如何管理?

通过python包来管理(文件夹)

什么是python包:

从物理上看:

包就是一个文件夹,该文件夹下包含了一个__init__.py文件,该文件可用于包含多个模块文件

(有__init__.py文件就是包,没有就是普通的文件夹

从逻辑上看:

包的本质依然是模块

方式一:

import 包名.模块名

包名.模块名.目标

import my_package.my_module1
import my_package.my_module2
my_package.my_module1.info_print1()
my_package.my_module2.info_print()
方式二:

from 包名(模块名) import 模块(功能)

from my_package import my_module1
from my_package import my_module2
my_module1.info_print1()
my_module2.info_print()
from my_package.my_module1 import info_print1
from my_package.my_module2 import info_print
info_print1()
info_print()

然后这个时候我们的__all__ = [模块]就可以写在那个自动生成的模块里了

从来控制import *的功能

如何安装第三方包:

第三方包就是非python官方的包,需要我们手动导入

pip程序:

pip install(默认连接的是国外的)

连接国内的:

pip install -i https://pypi.tuna.tsinghua.edu.cn/simple 包的名称

检验我们是否安装成功

DAY11:python基础综合案例:数据可视化——折线图可视化

JSON:

什么是json?

json是一种轻量级的数据交互格式。可以按照json指定的格式去组织和封装数据

json本质上是一个带有特定格式的字符串

主要功能:json就是一种在各个编程语言中流通的数据格式,负责不同编程语言中的数据传递和交互。

(不同语言之间的中转站)

是python的字典或者是列表(嵌套字典)

dumps(data):把python数据转换为json数据

loads(data):把json数据转换为python数据

import json
#准备列表,列表中每一个元素都是字典,将其转换为json
data = [{"name":"张三","age":13},{"name":"王五","age":16},{"name":"李四","age":19}]
json_str = json.dumps(data)
print(json_str)
print(type(json_str))

我们发现中文内容被编码了

import json
#准备列表,列表中每一个元素都是字典,将其转换为json
data = [{"name":"张三","age":13},{"name":"王五","age":16},{"name":"李四","age":19}]
json_str = json.dumps(data,ensure_ascii=False)
print(json_str)
print(type(json_str))
ensure_ascii=False

就可以使中文正常输出了(我们不用ascii码去转换它,而是直接的输出)

import json
#准备列表,列表中每一个元素都是字典,将其转换为json
data = [{"name":"张三","age":13},{"name":"王五","age":16},{"name":"李四","age":19}]
json_str = json.dumps(data,ensure_ascii=False)
print(json_str)
print(type(json_str))
s = '[{"name":"张三","age":13},{"name":"王五","age":16},{"name":"李四","age":19}]'
l = json.loads(s)
print(l)
print(type(l))

这个是转换成列表

JSON 格式规范:JSON 数据的最外层必须是单个值(要么是 {} 包裹的对象,要么是 [] 包裹的数组,不能是多个对象直接用逗号拼接)。一个列表或者是一个字典

import json
#准备列表,列表中每一个元素都是字典,将其转换为json
data = [{"name":"张三","age":13},{"name":"王五","age":16},{"name":"李四","age":19}]
json_str = json.dumps(data,ensure_ascii=False)
print(json_str)
print(type(json_str))
s = '[{"name":"张三","age":13},{"name":"王五","age":16},{"name":"李四","age":19}]'
l = json.loads(s)
print(l)
print(type(l))
s = '{"name":"张三","age":13}'
d = json.loads(s)
print(d)
print(type(d))

pyecharts模块介绍

帮助做出数据可视化效果图

pyecharts - A Python Echarts Plotting Library built with love.

中文简介 - Document

基础折线图:

#导包,导入Line功能构建折线图对象
from pyecharts.charts import Line
#得到折线图对象
line = Line()
#添加x轴的数据
line.add_xaxis(["中国","美国","英国"])
#添加y轴的数据
line.add_yaxis("GDP",[30,20,10])
#生成图表
line.render()

全局配置选项:

set_global_opts方法

系列配置选项:
数据处理:

JSON在线编辑器-懒人工具|www.ab173.com

DAY12对象

对象

1、设计类

#设计一个类(类比生活中的设计一张登记表)
class Student:
    name = None#记录学生姓名
    gender = None#记录学生的性别
    nationality = None#记录学生的国籍
    native_place = None#记录学生的籍贯
    age = None#记录学生的年龄

2、创建对象

#创建一个对象(打印一张登记表)
stu_1 = Student()

3、对象属性赋值

#对象属性进行赋值
stu_1.name = "小张"
stu_1.gender = "男"
stu_1.nationality = "中国"
stu_1.native_place = "山东"
stu_1.age = 18

4.获取对象中的数据

#获取对象中记录的信息
print(stu_1.name)
print(stu_1.gender)
print(stu_1.nationality)
print(stu_1.native_place)
print(stu_1.age)


成员变量

类的定义和使用:

我们可以用类去封装属性,并基于类创建出一个个的对象来使用。

类的使用语法:

class 类名称:

                    类的属性(成员变量)

                   类的行为(成员方法)

创建类对象的语法

对象  = 类名称()

方法:类内部的函数

成员方法语法:

def 方法名(self,形参1,。。。。。。。,形参N):

       方法体

self:

  •       它用来表示类对象自身的意思
  • 当我们使用类对象调用方法的时候,self会自动被python传入
  • 在方法内部,想要访问类的成员变量,必须使用self   

注意:

想要访问成员属性,必须使用self中国关键字

#定义一个带有成员方法的类
class Student:
    name = None#学生的姓名

    def say_hi(self):
        print(f"大家好!我是{self.name},请大家多多关照")

    def say_hi2(self,msg):
        print(f"大家好!我是{self.name},{msg}请大家多多关照")

stu = Student()
stu.name = "小李"
stu.say_hi2("hhh")
stu1 = Student()
stu1.name = "小林"
stu1.say_hi2("aaaaaaaa")

类和对象:


面向对象编程:

类只是一种程序内的“设计图纸”,需要基于图纸生产实体(对象),才能正常工作

class Clock:
    id = None
    price = None
    def ring(self):
        import winsound
        print(f"id = {self.id}, price = {self.price}")
        winsound.Beep(68,3000)
clock1 = Clock()
clock1.id = 121212
clock1.price = 1111111
clock1.ring()

(代码的声音很友好,不必害怕)

构造方法:

python类可以使用:__init__()方法,称之为构造方法

可以实现:

  • 在创建类对象(构造类)的时候,会自动执行
  • 在创建类对象(构造类)的时候,将传入参数自动传递给__init__方法使用
class Student:
    #下面三行可以省略
    name = None
    age = None
    tel = None
    def __init__(self,name,age,tel):
        self.name = name
        self.age = age
        self.tel = tel
        print(f"Student创建了一个对象名字是{name},年龄是{age},电话号码是{tel}")

stu1 = Student("小明",77,13812676898)
class Student:

    def __init__(self,name,age,tel):
        self.name = name
        self.age = age
        self.tel = tel
        print(f"Student创建了一个对象名字是{name},年龄是{age},电话号码是{tel}")

stu1 = Student("小明",77,13812676898)

其他内置方法:(魔术方法)

__init__构造方法,是python类内置方法之一

这些内置的类方法,各自有各自特殊的功能,这些内置方法我们称之为:魔术方法

__str__:字符串方法

当对象需要被转换为字符串之时,会输出如上结果(内存地址)

class Student:
    def __init__(self,name,age):
        self.name = name
        self.age = age

        # __str__魔术方法
    def __str__(self):
        return f"Student类对象,name:{self.name},age:{self.age}"

student = Student("小周",44)
print(student)#不写str魔术方法结果<__main__.Student object at 0x00000214C4E7F620>
print(str(student))#不写str魔术方法结果<__main__.Student object at 0x00000214C4E7F620>
#Student类对象,name:小周,age:44
#Student类对象,name:小周,age:44

__lt_:小于、大于符号比较

class Student:
    def __init__(self,name,age):
        self.name = name
        self.age = age

        # __str__魔术方法
    def __str__(self):
        return f"Student类对象,name:{self.name},age:{self.age}"

    # __lt__魔术方法
    def __lt__(self, other):
        return self.age < other.age

student = Student("小周",66)
student1 = Student("大明",33)

print(student < student1)#False
print(student > student1)#True

__le__:小于等于、大于等于符号比较

class Student:
    def __init__(self,name,age):
        self.name = name
        self.age = age

        # __str__魔术方法
    def __str__(self):
        return f"Student类对象,name:{self.name},age:{self.age}"

    # __lt__魔术方法
    def __lt__(self, other):
        return self.age < other.age
    #__le__魔术方法
    def __le__(self, other):
        return self.age <= other.age

student = Student("小周",66)
student1 = Student("大明",33)

print(student <= student1)#False
print(student >= student1)#True

__eq__: ==符号比较

class Student:
    def __init__(self,name,age):
        self.name = name
        self.age = age

        # __str__魔术方法
    def __str__(self):
        return f"Student类对象,name:{self.name},age:{self.age}"

    # __lt__魔术方法
    def __lt__(self, other):
        return self.age < other.age
    #__le__魔术方法
    def __le__(self, other):
        return self.age <= other.age
    #__eq__魔术方法
    def __eq__(self, other):
        return self.age == other.age

student = Student("小周",66)
student1 = Student("大明",33)

print(student <= student1)#False
print(student >= student1)#True
print(student == student1)#False(默认比较内存地址)

面向对象的三大特性:

封装:

私有成员:

既然现实事物有不公开的属性和行为,那么作为现实世界在程序中映射的类,也应该支持

定义私有成员方法的方式:

  • 私有成员变量:变量名以__开头(2个下划线)
  • 私有成员方法:方法名以__开头(2个下划线)
class Phone:
    __current_voltage = None#当前手机运行电压
    def __keep_single_core(self):
        print("让cpu单核模式运行")

phone = Phone()
phone.__keep_single_core()
print(__current_voltage)

通过对象来调用私有的方法,私有的变量都会报错

类的对象不能使用,但是类中的其他成员可以使用

class Phone:
    __current_voltage = 5#当前手机运行电压
    def __keep_single_core(self):
        print("让cpu单核模式运行")
    def call_by_5g(self):
        if self.__current_voltage >= 1:
            print("5g通话开启")
        else:
            self.__keep_single_core()

phone = Phone()
phone.call_by_5g()

继承:

继承就是把之前老的类里面的功能继续拿来用

在定义类的时候把老的类放在括号里

语法:

class 类名(父类名):

         类内容体

被继承的类:父类

继承别人的类:子类

单继承:

一个子类继承单个父类

class Phone:
    IMEI = None #序列号
    producer = "XM"
    def call_by_4g(self):
        print("支持4g通话了")


class Phone2022(Phone):
    face_id = "10001"
    def call_by_5g(self):
        print("2022年新功能支持5g")

phone = Phone2022()
print(phone.producer)
phone.call_by_4g()
phone.call_by_5g()
多继承:

一个子类继承多个父类

语法:

class 类名(父类1,父类2,父类3.。。。。):

          类的内容

class Phone:
    IMEI = None #序列号
    producer = "XM"
    def call_by_4g(self):
        print("支持4g通话了")
class NFCReader:
    nfc_type = "第五代"
    producer = "xm"
    def read_card(self):
        print("NFC读卡")
    def write_card(self):
        print("NFC写卡")

class RemoteControl:
    rc_type = "红外遥控"
    def control(self):
        print("红外遥控开启了")


class MyPhone(Phone,NFCReader,RemoteControl):
     pass#表示空的


phone = MyPhone()
phone.call_by_4g()
phone.read_card()
phone.write_card()
phone.control()

注意:

输出同名属性时,左边的优先(谁先来的谁优先级高)

复写和使用父类成员:

复写:

子类继承父类的成员属性和成员方法之后,如果对其“不满意”,那么可以进行复写/

即:在子类中重新定义重名的属性或方法

class Phone:
    IMEI = None
    producer = "xm"
    def call_by_5g(self):
        print("5g")

class MyPhone(Phone):
    producer = "dm"
    def call_by_5g(self):
        print("cpu单核")
        print("5g")
        
myPhone = MyPhone()
myPhone.call_by_5g()
print(myPhone.producer)

调用父类的成员:

方式1:

父类名.成员变量

父类名.成员方法(self)

方式2:

super().成员变量

super().成员方法()

class Phone:
    IMEI = None
    producer = "xm"
    def call_by_5g(self):
        print("5g")

class MyPhone(Phone):
    producer = "dm"
    def call_by_5g(self):
        print("cpu单核")
        #super().call_by_5g()
        Phone.call_by_5g(self)

myPhone = MyPhone()
myPhone.call_by_5g()
print(myPhone.producer)
类型注解:

为什么内置模块的方法可以提示类型

自己定义的就不行

因为pycharm无法通过代码确定应该传入什么类型

在代码中涉及数据交互的地方,提供数据类型的注解(显式的说明)

功能:
  • 帮助第三方IDE工具对代码进行类型推断,协助做代码提示
  • 帮助开发者自身对变量进行类型注释
支持:
  • 变量的类型注解
  • 函数(方法)形参列表和返回值的类型注解

注意:

类型注解仅仅是个备注,写错了也不会影响代码的运行

变量的类型注解:

语法:

变量:类型

#基础数据类型注解
var_1: int = 10
var_2: str = 'hello'
var_3: bool = True
类对象类型注解
class Student:
    pass
stu: Student = Student()
#基础容器类型注解
my_list:list = [1,2,3]
my_tuple: tuple = (1,"dadada",True)
my_dict: dict = {'a':1,'b':2,'c':3}
#容器类型详细注解
my_list:list[int] = [1,2,3]
my_tuple: tuple[int,str,bool] = (1,"dadada",True)
my_dict: dict[str,int] = {'a':1,'b':2,'c':3}
#在注释中进行类型注解
var_1 = random.randint(1,10) #type: int
var_2 = json.loads('{"a":1,"b":2,"c":3}')  #type:dict[str,int]
def func():
    return 10
var_3 = func() #type:int
函数(方法)的类型注解-形参注解:

语法:

def 函数方法名(形参名:类型,形参名:类型):

      pass

#对形参进行类型注解
def add(x: int,y: int):
    return x+y

add(1,2)

函数(方法)的类型注解-返回值注解:

语法:

def  函数方法名(形参:类型,。。。。。,形参:类型)->返回值类型:

       pass

#对返回值注解
def func(data:list) -> list:
    return data

都是建议性的不是强制性的

Union类型:

语法:

Union[类型,。。。。。。。类型]

可以定义联合类型注解 

from typing import Union
my_list: list[Union[int,str]] = [1,2,"dadad","dadadv"]
def func(data:Union[int,str]) -> Union[int,str]:
    pass
func()

多态:

多种状态,即完成某个行为时,使用不同的对象会得到不同的状态

  • 以父类做定义声明
  • 以子类做实际工作
  • 用以获得同一行为,不同状态
class Animal:
    def speak(self):
        pass

class Dog(Animal):
    def speak(self):
        print("汪汪汪")

class Cat(Animal):
    def speak(self):
        print("喵喵喵")

def make_noise(animal:Animal):
    animal.speak()
dog = Dog()
cat = Cat()

make_noise(dog)
make_noise(cat)

父类方法pass的含义:

  • 父类来确定有哪些方法
  • 具体的方法实现,由子类自行决定

这种写法,就叫做抽象类(也称为接口

抽象类:含有抽象方法的类就叫做抽象类

抽象方法:方法体是空实现的(pass)称之为抽象方法 

抽象类:

提出标准,具体怎么做要子类去实现

DAY13

SQL入门和实战:

数据库:

库-表-数据

sql语言就是一种对数据库、数据进行操作、管理、查询的工具。

MySQL安装:

MySQL :: MySQL Downloads

MySQL的入门使用:
  • show databases ;查看有哪些数据库
  • use 数据库名 使用某个数据库
  • show tables 查看数据库内有哪些表
  • exit退出MySQL的命令行环境

使用MySQL图形化工具

DBeaver Community | Free Open-Source Database Management Tool​​​​​​

DAY14:

SQL基础与DDL:

SQL:结构化查询语言,用于访问和处理数据库的标准的计算机语言

就是操作数据库的工具

SQL的特点:

  • 大小写不敏感
  • SQL语句以分号结尾(可以多行书写,最后有分号就行)
  • SQL支持注释:单行注释:-- 注释内容(--后面要有个空格)      单行注释:# 注释内容(#后面可以不加空格,推荐加上)     多行注释:/* 注释内容*/

数据定义:DDL-库管理:

查看数据库:

show databases;

使用数据库:

use 数据库;

创建数据库:

create database 数据库名称 [charset utf8];(中括号的意思就是可写也可以不写,默认就为utf8)

删除数据库:

drop database 数据库名称;

查看当前使用的数据库:

select database();

DDL-表管理:

查看有哪些表:

show tables;

注意:

要先选择数据库

删除表:

drop table 表名称;

drop table if exits 表名称;

创建表:

create table 表名称(

       列名称   列类型,

       列名称   列类型,

       。。。。。。。

);

列表类型有:

  • int    整数
  • float  浮点数
  • varchar(长度)   文本,长度为数字,做最大长度限制
  • date         日期类型
  • timestamp    时间戳类型

SQL-DML

数据操作语言:

插入insert

insert into 表[(列1,列2,。。。。。,列N)] values(值1,值2,。。。。。,值N)

【(值1,值2 ,值。。。。。值N),。。。。。,(值1,值2,。。。。。,值N)】

当给表内所有的列传值时,可以不写各个列,直接写值,但是顺序要对应

删除delete

delete from 表名称 [where 条件判断]

条件判断:

  • = <  >  <=  >=  !=

更新update

update 表名 set 列 = 值 [where 条件判断];

SQL-DQL:

数据查询:

select 字段列表 |* from 表

过滤:

select 字段列表|* from 表 where 条件判断

分组聚合查询:

先按照某项要求分组,然后统计每个组内的人数

语法:

select 字段 | 聚合函数 from 表 [where 条件 ] group by 列

聚合函数:

  • sum求和
  • avg 求平均值
  • min求最小值
  • max求最大值
  • count 求数量(数条)

非聚合函数中group by后面出现谁,前面select才能有谁

排序和分页:

结果排序

select 列|聚合函数|* from 表

where 。。。

group by 。。。

order by 。。。(列) [asc|desc]

limit n[,m]

n:限制几条

n,m:从第n条开始,取m条

asc:升序(默认)

desc:降序 

python来操作MYSQL:

from pymysql import Connection
#构建到MySQL数据库的连接
conn = Connection(
    host='localhost',#主机名(IP)
    port=3306,#端口
    user='root',#账户
    password="mysql"#密码
)
print(conn.get_host_info())
print(conn.get_server_info())
#执行非查询性质的sql
cursor = conn.cursor() #获取游标对象
#选择数据库
conn.select_db('sys')
#执行操作(通过游标对象)
#cursor.execute("create table if not exists py_student(id int);")
#执行sql
cursor.execute('select * from student')
result = cursor.fetchall()
print(result)

DAY15:python的一些高阶技巧

闭包:

在函数嵌套的前提下,内部函数使用了外部函数的变量,并且外部函数返回了内部函数,我们把这个使用外部函数变量的内部函数称为闭包。(这样某些全局变量就不会被篡改了)

#简单闭包
def outer(logo):

    def inner(msg):
        print(f"{logo}{msg}{logo}")

    return inner

fn1 = outer("你好")
fn1("小明")

 让fn1=outer的返回值inner函数,fn1就相当于inner函数,使用fn1传参就只会调用inner,不改变logo,如果想改变,就只能通过改变inner的执行语句来改变

在内部函数中修改外部函数的值:

正常情况下,我们在内部函数里面想直接对外部函数的值赋值时是不被允许的

#使用nonlocal关键字修改外部函数的值
def outer(num1):
    def inner(num2):
        nonlocal num1
        num1 += num2
        print(num1)
    return inner

fn = outer(10)
fn(20)
fn(20)
fn(20)

ATM小案例方便理解:

#使用闭包实现ATM小案例
def account_creat(initial_amount = 0):#这里就是我们的余额
    def atm(num,deposit = True):
        nonlocal initial_amount
        if deposit:
            initial_amount += num
            print(f"存款:+{num},余额还剩{initial_amount}")
        else:
            initial_amount -= num
            print(f"存款:-{num},余额还剩{initial_amount}")
    return atm

atm = account_creat()
atm(500)
atm(100,False)

这个闭包的目的,

准确的说: 是为避免在"本次"函数执行中, 有外部模块修改amount

优点:

  • 无需定义全局变量即可实现通过函数,持续的访问、修改某个值
  • 闭包使用的变量的所用于在函数内,难以被错误的调用而修改

缺点:

  • 由于内部函数持续引用外部函数的值,所以会导致这一部分内存空间不被释放,一直占用内存

三、关键差异:闭包 vs 类对象

  1. 语法形态
    • 闭包:本质是函数嵌套 + 变量捕获 + 返回内层函数,最终是一个 “函数”。
    • 对象:是类的实例,本质是数据(属性)+ 方法(行为)的集合
  2. 状态管理
    • 闭包:只能捕获外层函数的变量,状态封装在函数作用域里。
    • 对象:可以定义多个属性(self.xxx),状态封装在实例命名空间里,更灵活。
  3. 功能边界
    • 闭包:通常只提供单一功能(示例中只有 print 这一个行为)。
    • 对象:可以定义多个方法,实现复杂的多行为逻辑。
  4. 设计思想
    • 闭包:函数式编程思想,强调 “函数作为一等公民”,用函数封装状态和行为。
    • 对象:面向对象编程思想,强调 “封装、继承、多态”,用类抽象事物。

四、核心差异:为什么不能完全取代?

我们用 “场景适配性” 来拆解,你会更清楚两者的不可替代性:

维度闭包(函数式)类(面向对象)
代码轻量化实现简单逻辑时,几行代码就能完成(如示例)必须定义类__init__、方法,代码量翻倍
临时 / 一次性逻辑用完即弃,无需定义 “类” 这个 “模板”即使只用一次,也需先定义类,冗余且没必要
函数作为返回值天生支持:外层函数返回内层函数,可直接调用需返回对象 + 调用方法,多一层 “对象” 的包裹
闭包的 “隐藏状态”状态(logo)隐藏在函数作用域,外部不可见状态(如self.logo)是对象属性,可被修改
适用场景简单的状态封装、函数装饰器、回调函数复杂的多属

装饰器

装饰器其实也是一种闭包,其功能就是在不破坏目标函数原有的代码和功能的前提下,为目标函数增加新功能。

装饰器的一般写法(闭包)

def sleep():
    import random
    import time
    print("睡眠中")
    time.sleep(random.randint(1,5))

#装饰器的一般写法
def outer(func):
    def inner():
        print("睡着了")
        func()
        print("起床了")

    return inner

fn1 = outer(sleep)
fn1()

装饰器的语法糖写法:

#装饰器的语法糖写法
def outer(func):
    def inner():
        print("我睡觉了")
        func()
        print("我起床了")

    return inner

@outer
def sleep():
    import time
    import random
    print("睡眠中")
    time.sleep(random.randint(1, 7))

sleep()

当我们使用语法糖写法的时候,我们在目标函数的前面增加一个@outer,再后面调用这个目标函数的时候其功能就会发生变化

设计模式:

最常见、最经典的设计模式,就是我们所学习的面向对象。

单例模式:

定义:保证一个类只有一个实例,并提供一个访问它的全局访问点

适用场景: 当一个类只能有一个实例,而客户可以从一个众所周知的访问点访问它 

我们正常情况下创建两个对象是完全不同的两个对象(由图中输出的地址可以看出)

class StrTools():
    pass


strTools = StrTools()
from str_tools_py import strTools

s1 = strTools
s2 = strTools
print(s1)
print(s2)

当我们使用单例模式时,无论创建多少个对象最终都是一个相同的对象

(由图中的地址可见)

好处:

  • 节省内存
  • 节省创建对象的开销

工厂模式:

当需要大量创建一个类的实例的时候,可以使用工厂模式。

即,从原生的使用类的构造去创建对象的形式

迁移到,基于工厂提供的方法去创建对象的形式。

class Person:
    pass
class Worker(Person):
    pass
class Student(Person):
    pass
class Teacher(Person):
    pass

class PersonFactory:
    def get_person(self,p_type):
        if p_type == 'w':
            return Worker()
        elif p_type == 's':
            return Student()
        else:
            return Teacher()

person = PersonFactory()
worker = person.get_person('w')
student = person.get_person('s')
teacher = person.get_person('t')

在 Python 中,实例方法也就是你定义在类里的普通方法)的第一个参数必须是 self(这个名字只是约定俗成,你也可以用其他名字,但强烈不建议),它的核心作用是:

  • 指向当前类的实例对象本身
  • 让方法能够访问和操作该实例的属性、调用该实例的其他方法

当类的名字发生变化时,如果想之前的写法需要一个一个改名称,但如果是工厂模式下,只需要改一下实例方法

多线程:

进程、线程和并性执行:

进程:就是一个程序,运行在系统之上,那么便称这个程序为一个运行进程,并且分配进程id方便系统管理

线程:线程是归属于进程的,一个进程可以开启多个线程,执行不同的工作,是进程的实际工作最小单位

操作系统中可以运行多个进程,即多任务运行

一个进程内可以运行多个线程,即多线程运行

注意:

进程之间的内存是隔离的,即不同的进程拥有各自的内存空间。

线程之间是内存共享的,线程是属于进程的,一个进程内的多个线程之间是共享这个进程所拥有的内存空间的。

并行执行:

并行执行的是指的是同一时间做不同的工作。

进程之间是并行执行的,操作系统可以同时运行好多程序,这些程序都是在并行执行。

除了进程外,线程其实也可以并行执行:

一个程序在同一时间做两件/更多的事情,我们就称之为:多线程并行执行

并发:

指多个线程对应的多条指令被快速轮回的执行

并行:

指同一时刻有多条指令在多个处理器上同步执行

多线程编程:

threading模块

 

import time
import threading
def sing():
    while True:
        print("我在唱歌,啦啦啦啦")
        time.sleep(1)

def dance():
    while True:
        print("我在跳舞,呱呱呱")
        time.sleep(1)

if __name__ == '__main__':
    #创建一个唱歌的线程
    sing_thread = threading.Thread(target=sing)
    #创建一个跳舞的线程
    dance_thread = threading.Thread(target=dance)
    sing_thread.start()
    dance_thread.start()

网络编程

Socket:

socket(简称 套接字)是进程之间通信一个工具,好比现实生活中的插座,所有的家用电器要想工作都是基于插座进行

进程之间想要进行网络通信需要socket

Socket服务端:等待其他进程的连接、可接受发来的消息、可以回复消息

Socket客户端:主动连接服务端、可以发送消息、可以接收回复

Socket服务端编程:

import socket
 #创建Socket对象
socket_server = socket.socket()
#绑定IP地址和端口
socket_server.bind(("localhost", 8888))#bind要传入的是一个元组
#监听端口
socket_server.listen(1)#listen方法内接受一个整数传参,表示接受的链接数量
#等待客户端的链接
# result:tuple = socket_server.accept()
# conn = result[0]#客户端和服务端的链接对象
# address = result[1]#客户端的地址信息
conn, addr = socket_server.accept()
#accept方法返回的是二元元组(链接对象,客户端地址信息)
#可以通过变量1,变量2 = socket_server.accept()的形式,直接接受二元元组的两个元素
#accept()方法,是阻塞方法,等待客户端的链接,如果没有链接,就卡在这一行,不向下执行
print(f"接受到了客户端的链接,客户端的信息是:{addr}")
#接受客户端的信息,要使用客户端和服务端的本次链接对象,而非socket_server对象
while True:
    data:str = conn.recv(1024).decode("utf-8")
    #recv接受的参数是缓冲区大小,一般用1024
    #recv方法的返回值是一个字节数组,即bytes对象,不是字符串,可以通过decode方法来编码,将字节数组转化成字符串对象
    print(f"客户端发来的消息是:{data}")
    #发送回复信息
    msg = input("请输入你要回复客户端的消息")
    if msg == "exit":
        break
    #encode可以将字符串编码成字节数组对象
    conn.send(msg.encode("utf-8"))
#关闭链接
conn.close()
socket_server.close()

正则表达式

# import re
#
# s = '22python dapython dwadpythondbuaihdwuihduiahudaiudha'
# #match是从头开始匹配
# # result = re.match("python",s)
# # print(result)
# # print(result.span())
# # print(result.group())
# #search找到匹配项,从前往后,找到第一个之后就停止
# # result = re.search('python',s)
# # print(result)
# result = re.findall('python',s)
# print(result)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值