数据分析之python基础学习

Python基础学习内容详细

编程与编程语言

什么是编程语言?
    语言:中文、英文、日文、韩文...
    作用:人与人之间相互沟通交流的媒介
    
    编程语言:人与计算机之间沟通交流的媒介
    作用:想让计算机按照我们的逻辑思维和想法帮我们做事情

我们学习英文的目的是为了跟外国人交流,同理我们为了能够跟计算机沟通交流所以需要学习编程语言,即学习编程语言的过程就相当于在学习一门外语

什么是编程?
	其实就是人将自己的思维逻辑和想法用计算机能够识别的语言写下来的过程

计算机内部储存数据的原理

计算机能够帮助我们存储各式各样的数据
    文本文件
    表格文件
    视频文件
    图片文件
    ...
    
计算机的工作必须依赖于"电",而电信号只有高低电平两种状态
也就意味着在计算机的世界里面只认识两种状态,我们人为的将高低电平定义为数字1
低电平定义为数字0(计算机只认识数字0和1>>>:二进制)
为了能够表示出万物,我们采用0和1数字的组合
    0:你
    1:我
    一位数字只能表示两种状态
    00
    01
    10
    11
    两位数能表示四种状态
    ...
    2的N次方
    
重要的单位换算
    00000000	八位作为最小的单元	2的8次方
    我们将八位二进数取名为"8个比特位(bit)"
    8bit = 1bytes(1个字节)
    1024bytes = 1KB
    1024KB = 1MB
    1024MB = 1GB
    1024GB = 1PB

其实对于计算机来说,所有的数据都仅仅是一串二进制数(010101010101)

# 总结:
	计算机只认识二进制数(010101010)

编程语言的发展史

1.机器语言
    站在计算机的角度,说计算机能够听懂的语言即二进制
    程序员直接使用二进制与计算机沟通交流
    	优点:计算机能够直接"听懂",执行速度快,效率高
        缺点:学习难度大,开发效率低
        
2.汇编语言
    还是站在计算机角度,说计算机能够听懂的语言
    只不过我们开始用一些简单的英文字母来表示一串二进制数
    	优点:计算机能够直接"听懂",执行速度快,效率高
        缺点:学习难度偏大,开发效率偏低
        
3.高级语言
	站在人的角度,说人能够听明白的语言
    	优点:学习难度低,开发效率高
        缺点:计算机无法直接识别
    高级语言:Python、Java、C++、C#、PHP...
需要"翻译官"
	人类的字符翻译成计算机能够读懂的二进制

编程语言的分类

针对高级语言主要分为两大类
编译型语言:C++
    类似于谷歌翻译,一次性将需要的翻译文本全部翻译出来
    之后拿着翻译的结果反复执行
    优点:翻译一次之后可以反复使用,执行速度快
    缺点:一旦内容出错,每次都需要从头开始重新翻译一遍,跨平台性较差
    
解释型语言:Python
    类似于同声传译,说一句翻译一句
    优点:出错之后修改起来方便(无论是否出错效率都是差不多的)
    缺点:执行速度没有编译型快

Python语言

1.Python是一门编程语言
2.Python能够应用的领域十分广泛
    人工智能
    机器学习
    数据分析
    自动化运维、测试
    web开发
    网络爬虫
    金融量化
    ...

Python解释器

如果你想让你的计算机能够识别Python代码,那么你必须在你的计算机上面下载一个Python解释器(翻译官)

解释器版本问题
    Python2.x
    	最高版本是Python2.7,2020年之后就不在维护更新了
    	有一些公司比较老的项目使用的还是Python2.7版本
    Python3.x
    	最高版本Python3.9,但我们不推荐直接使用最高版本
        我们学习统一使用Python3.6版本(非常稳定)
"""
在IT领域不会轻易地尝试最新版本的软件
	如果一个程序运行着没有问题,那么我们不会主动的更新里面的软件
	并且新版本可能会出现一些未知的错误
"""

下载地址:https://www.python.org/

步骤:
    downloads
    windows
    选择3.6版本下载
    完成之后双击该文件一步步安装即可
    	下载的软件尽量不要安装在C盘,C盘是系统盘
        存储的数据过多会导致机器速度变慢(尤其是开机的时候)
        D:python36
       
常见问题:
    1.之前已经装过会报不同的提示
    2.电脑系统操作位数不一致
    	x86_32bit
        x86_64bit
        32位的电脑没有办法安装64位的软件
        而64位的电脑可以兼容32位的软件      
    

环境变量的概念

文件名是.exe结尾的文件一般都是可执行文件

环境变量
    在cmd中窗口输入文件名的时候其实会自动去环境变量中查找是否有该文件
    
Python.exe就是python解释器环境
如何启动
    方式1:
        windows+r键 输入cmd回车
        切换路径
        	D:
                cd python36
           输入python即可
    方式2:
        将python.exe所在的路径添加到环境变量中
    
win10和win7环境变量界面有一点不同
     win10比较好用
     win7较为复杂
    	所有的路径全部在写一行
        路径与路径之间是以分号分割的
        path1;path2;path3
        如果你要新增环境变量数据
        path1;path2;path3;new_path;

运行Python代码的方式

https://www.jetbrains.com/pycharm/download/#section=windows
 专业版本是收费的,但是有一个月的免费试用
并且我们也可以破解使用
    1.激活码
    2.1.直接在cmd窗口下运行代码
    不推荐使用(代码无法保存且编写困难)
    print(123)
2.可以写在一个文本文件里面
    不推荐使用(不够简单)
    python D:\abc.txt
3.借助于对应的编辑器
    vscode:对小白不太友好
    pycharm:功能强大、且非常好用
        
    下载地址:https://www.jetbrains.com/pycharm/download/#section=windows
   
安装流程截图可以参考:https://www.runoob.com/w3cnote/pycharm-windows-install.html前三步即可
            
专业版本是收费的,但是有一个月的免费试用
并且我们也可以破解使用
	激活码

pycharm如何破解

1.新版本的pycharm很难再永久激活
    激活码网站:http://idea.medeming.com/jets/
    该网站是实时更新的,一旦你的激活码失效重新访问下载即可
 
2.如果不激活第一次体验一个月
    一个月之后,如果你还不激活,那么每次打开pycharm只能够使用30分钟
    30分钟到了会自动保存你当前内容然后关闭,而你只需要再次打开继续30分钟
 
3.如果需要永久激活,需要你在下载老版本的pycharm
	2018.1~1028.3
    进入pycharm编辑界面,将破解文件拖入即可
    	jetbrains-..jar

pycharm简单使用

1.创建新项目
    1.create new project
    2.File
    	new project
        
2.解释器的选择

3.基本设置(便于开发和肉眼观察)
	file
    	  settings
        	editor
            	    code scheme
    控制字体缩放
        file
          settings
        	editor
            	    general
4.新建文件

文件的后缀名

.text
.mp4
.xlsx
.pdf
.jpg
.gif
.word
...
1.文件的后缀名有什么用?
    文件的后缀名主要是用来标识改文件内数据的数据类型
2.文件的后缀名是给人看的还是给计算机看的亦后者是其他什么情况?
    文件的后缀名仅仅是用来给人看的(因为所有的数据对于计算机来说都是一串01010的二进制数)
# 总结:
    文本文件我们习惯用.txt后缀名
    表格文件我们习惯用.xlsx后缀名
    对于我们编写的代码也应该专门昭一中文件后缀名存储
    目的就是为了便于用户区分
"""针对存储Python代码的文件后缀名,同意采用.py结尾"""

Python的注释

什么是注释?
    就是对一段代码的解释
在py文件中如果想要书写除Python语言以外的文字。需要采用注释的形式书写
否则会导致整个文件无法被解释器执行
方式一:单行注释
	# 注释
方式二:多行注释
    '''注释'''
    """注释"""

计算机三大核心硬件

CPU	
    是计算机里面真正帮你干活的人
内存	
    临时存、取数据
    缺点:基于电工作,断电数据立刻丢失
    优点:存、取数据的速度非常快
    # 所有的程序要想运行起来,该程序代码必须存在内存中
硬盘(U盘、磁带、硬盘、固态硬盘)
    永久保存数据
    缺点:存、取数据的速度较慢
    优点:在不认为破坏的情况下,能够永久的保存数据
    
"""
我们下载的软件都是下载到计算机的硬盘中的
而我们双击软件其实就是将该软件的代码从硬盘中读取到内存
之后cpu去内存里面执行,给你的感觉就是这款软件在运行了
"""
1.正在运行的软件产生的数据第一时间肯定是在内存中
2.保存数据的过程(ctrl+s)其实就是将内存里面的数据刷到硬盘从而实现永久保存

变量

变量就是可以变化的量,量指的是事物的状态,比如人的年龄、性别,游戏角色的等级、金钱等等
程序执行的本质就是一系列状态的变化,变是程序执行的直接体现,所以我们需要有一种机制能够反映或者说是保存下来程序执行时的状态,以及状态的变化。

eg:
你在路上遇到了我,为什么立刻就认出我了
     姓名:wxj
     身高:178
     体重:75
     长相:还行
    # 变量的本质其实就是用来帮助我们记录事物的状态
反应到程序中
    name = 'wxj'
    age = 18
    gender = 'male'
    height = 170
    
# 到底发生了什么事
name = 'wxj'
"""
1.在内存中申请一块内存空间将wxj存进去
2.给wxj绑定一个门牌号name(赋值过程)
3.以后要想访问wxj就拿着门牌号name即可

name ='wxj'
1.name是变量名
2.=是赋值符号
3.wxj是变量的值
"""

age = 18
age = 19
print(age) # 19

name = 'wxj'
name1 = name
print(name1) # wxj
"""
看到赋值符号
    1.先看赋值符号的左侧
    2.再看赋值符号的右侧
将赋值符号右侧的数据赋值给左侧的变量名
"""

变量命名规范

1.变量名只能包含数字、字母、下划线
2.数字不能开头
3.变量名一定要做到见名知意
name@ = 123 
不可以 @是特殊符号
1name = 123
不可以 数字不能开头
n123m_E = 123
可以

1.中文虽然理论上可以作为变量名  但是极力不推荐使用
姓名 = 'wxj'
print(姓名)
2.汉语拼音是完全符合变量的规范 但是也不推荐使用(万不得已)
xm = 'wxj'
xl = '本科'
只要能够做到见名知意,变量名稍微长一点也没关系
User_From_DB_MySQL = 'wxj'

变量的命名风格

1.下划线(单词之间用下划线隔开)	Python推荐使用
	user_name = 'wxj'
2.大驼峰(每个单词首字母大写)	JS推荐使用
	UserNmae = 'wxj'
3.小驼峰(第一个单词首字母小写 其他单词首字母全部大写)
	userName = 'wxj'
'''命名风格随个人喜好,你只要能够做到一心一意即可(尽量只用一种)'''

常量

常量顾名思义就是不变化的量
在Python中没有真正意义上的常量,我们约定俗成的将全大写的变量名看成是常量
HOST = '127.0.0.1'
真正意义上的常量,定义了之后就无法在改变
eg:JavaScript中就有真正意义上的常量
    const pi = 3.1415926
    undefined
    pi
    3.1415926
    pi = 666 # 无法修改 直接报错
"""
以后在Python程序中如果看到了全大写的变量,那么在修改的时候就需要注意点,或者询问一下定义该变量的工作人员是否可以直接修改
"""

常用方法

name = 'wxj'
age = 18
id() 查看数据的内存地址
print(id(name))  # 相当于内存地址
type()	查看数据的数据类型
print(type(name),type(age))  # <class 'str'> <class 'int'>

数据类型的概念

我们学习变量是为了让计算机能够像人一样去记忆事物的某种状态,而变量的值就是用来存储事物状态的,很明显事物的状态分成不同种类的(比如人的年龄,身高,职位,工资等等),所以变量值也应该有不同的类型
eg:实际生活中我们接触的数据也是有很多不同的类型
	文本文件
   	视频文件
        音频文件
针对不同类型的数据我们有不同的存储方式和操作手段

数据类型之整型

整型大白话洽会就是'整数'
作用:记录年龄,出生年份,学生人数等整数相关的状态
使用:
    age = 18
    birth = 1996
    stu_num = 7

数据类型之浮点型

浮点型大白话其实就是"小数"
作用:记录人的身高,体重,薪资等小数相关的状态
使用:
    height = 1.83
    weight = 74.9
    salary = 3.1

数据类型之字符串(重点)

字符串大白话其实就是"文本数据"
作用:用来记录人的名字,家庭住址,性别等描述性质的状态
使用:(定义字符串有三种方式)
'''本质:引号引起来的就是字符串'''
# 方式1:单引号
    name = 'wxj'
# 方式2:双引号
    name = "wxj"
# 方式3:三引号(没有赋值符号就是注释 有赋值符号就是字符串)
    name = """wxj"""
    name = '''wxj'''

疑问:为什么定义字符串有这么多种方式?
	因为我们在书写文本的时候也可能需要用到引号,为了避免冲突从而设置了多个定义方式

数据类型之列表(重点)

列表大白话其实就是能够存储多个数据的容器
描述:使用的是[],中括号里面可以存储多个元素(数据),元素与元素之间逗号隔开
元素可以是任意的数据类型
name_list = ['jason','wxj','owen']
l = [18,1.11,'wxj',[11,22,33]]

# 索引取值
'''索引的起始位置是从0开始的'''
print(name_list[0])		# jason
print(name_list[1])		# wxj

# 小练习题
# 利用索引取值的方式获取元素22
l1 = ['jason', 18, ['country', [11, 22, 33]]]
# 分步操作
# 将小列表重新赋值给一个变量名
l2 = l1[2]
# 将更小的列表重新赋值给一个变量名
l3 = l2[1]
l4 = l3[1]
print(l4)
# 一次性完成
print(l1[2][1][1])

数据类型之字典

字典既可以存储多个数据,并且还可以标识数据到底表示什么含义
我们在存储用户信息的时候可以考虑使用列表,但是多个元素之间没有具体的指向,容易产生混淆,那么为了能够更加精确的存储数据我们引入了字典的概念
字典:使用的是{},大括号里面可以存储多个元素,元素与元素之间逗号隔开,元素的表现形式是"key:value"键值对
user_dict = {
    'username': 'wxj',
    'password': 123,
    'age': 18,
    'address': 'China'
}
"""
key是字典的键,用来对value进行描述(一般情况下都是字符串)
value是字典的值,用来存储真正的数据,可以是任意的数据类型
"""
user_info = {
    'username': 'wxj',
    'age': 18,
    'salary': 3.1,
    'hobbies': ['read', 'study', 'music', 'run'],
    'address': {
        'country': 'China',
        'city': 'SH'
    }
}

# 字典的取值
# 字典的取值不能用索引(字典内元素是无序的没有索引的概念)
print(user_info['username'])
print(user_info['hobies'])
print(user_info['xxx'])		# 中括号里面的键一定要是存在的

数据类型之布尔值

布尔值其实就是用来表示“真假”、“对错”的
布尔值只有两种
    True
    False
作用:用来程序中的逻辑判断

在设计到逻辑判断的时候数据都会转换成布尔值进行判断
1.记忆
	布尔值为False的数据有:
    0,None,'',[],{}...
    其他情况下布尔值都是True
    
2.了解
在存储布尔值的时候我们会习惯用is_或者is开头
    is_right = True
    is_status = True
    is_delete = True

数据类型之元祖

元祖跟列表非常的相似,我们可以把元祖看成是不可变的列表
元祖:使用的是(),小括号内可以存放多个元素,元素与元素之间用逗号隔开,元素只能是不可变类型
t = (1,2,3,4,5,6)

数据类型之集合

集合主要是用来做
    1.去重
    2.关系运算
集合:使用的是{},大括号里面可以存储多个元素,元素与元素之间用逗号隔开,元素只能是不可变类型,并且元素不是k:v键值对形式
s = {1, 2, 3, 4, 5}	# 一定要跟字典区分开

总结

数据类型的专业英文
整型			int
浮点型		        float
字符串			str
列表			list
字段			dict
布尔值			bool
元祖			tuple
集合			set

与用户交互

eg:以前去银行办理业务需要排队等柜台办公人员
   现在我们只需要使用ATM或者手机银行即可办理
    
1.获取用户输入(input)
username = input('请输入您的用户名:')
# 将input获取到的用户输入赋值给变量名username
print(username,type(username))
"""input获取到的用户数据都是字符串类型"""

2.输出内容(print)
print('Hello World')

格式化输出

把一段字符串里面的某些内容替换掉之后再输出,就是格式化输出。
我们经常会输出具有某种固定格式的内容,比如:'亲爱的xxx您好!您xxx月的话费是xxx,余额是xxx'我们需要做的是将xxx替换为具体的内容。

# 待替换内容 需要提前使用特殊符号占位
res = '亲爱的%s您好!您%s月的话费是%s,余额是%s'
print(res % ('jason', 12, 100, 100000000))
print(res % ('tony', 12, 100000, -99999))
# 占位符:提前占位之后可以给其他数据使用
# %s:可以给任意数据占位
# %d:只能给数字占位
res = '亲爱的%s您好!您%d月的话费是%d,余额是%d'
print(res % ('wxj', 12, 100, '111'))	# 报错
"""以后我们使用占位符的时候可以直接使用%s不需要考虑%d"""

# %d使用场景
print('%08d' % 1)
print('%08d' % 123)
print('%08d' % 12334243242)
00000001
00000123
12334243242


# 练习2:用户输入姓名、年龄、工作、爱好 ,然后打印成以下格式
------------ info of Tony -----------
Name  : Tony
Age   : 22
Sex   : male
Job   : Teacher 
------------- end -----------------

res = """
------------ info of %s -----------
Name  : %s
Age   : %s
Sex   : %s
Job   : %s 
------------- end -----------------
"""
name = input('name>>>:')
age = input('age>>>:')
gender = input('gender>>>:')
job = input('job>>>:')
print(res%(name,name,age,gender,job))

运算符

# 算数运算符
Python支持的算数运算符与数学上计算的符号使用是一致的
x = 10
y = 2
print(x - y)
print(x + y)
print(x * y)
print(x / y)
print(x % y)	# 取余数
print(x ** y)	# 次方

# 比较运算符
比较运算符用来对两个值进行比较,返回的是布尔值True或False
print(x > y)	# True
print(x < y)	# False
print(x == y)	# 等号要用两个== 一个=是赋值符号  False

# 增量赋值
x = 6
x = x + 1
# 程序员法则:能少敲一个字母绝不多敲
x += 1	# 等价于 x = x + 1
x -= 10	# 等价于 x = x - 10
x *= 2	# 等价于 x = x * 2
x /= 1	# 等价于 x = x / 1

# 链式赋值
x = 10
y = x
z = x
# 简写
x = y = z = 10

# 交叉赋值
x = 666
y = 222
# 将x与y的值互换
# 错误解法
x = y
y = x
print(x,y)
# 方式1:采用中间变量
tmp = x
x = y
y = tmp
print(x,y)
# 方式2:交叉赋值
x,y = y,x
print(x,y)

# 解压赋值
l = ['jason', 'tony', 'jerry', 'owen']
# name1 = l[0]
# name2 = l[1]
# name3 = l[2]
# name4 = l[3]
# print(name1,name2,name3,name4)
# 解压赋值
# n1, n2, n3, n4 = l  # 按照位置一一赋值
# print(n1, n2, n3, n4)
# n1, n2 = l  # 少了不行
# n1, n2, n3, n4, n5 = l  # 多了也不行
# 打破个数约束
a, *_ = l
print(a, _)  # jason  ['tony', 'jerry', 'owen']
a, *_, b = l
print(a, _, b)  # jason ['tony', 'jerry'] owen

运算符之逻辑运算

逻辑运算符用于连接多个条件,进行关联判断,会返回布尔值True或者False
与		and
或		or
非		not

and
可以用and连接多个条件,会按照从左往右的顺序依次判断,一旦某一条件为False,则无需再往右判断,可以立即判定最终结果就位False,只有在所有条件的结果都为True的情况下,最终结果才为True
2 > 1 and 1 == 1 and True and 3 > 2  # True
2 > 3 and 1 == 1 and True and 3 > 2  # False

or
可以用or连接多个条件,会按照从左到右的顺序依次判断,一旦某一个条件为True,则无需再往右判断,可以立即判定最终结果为True,只有在所有条件的结果都为False的情况下,最终结果才为False
2 > 1 or  2 == 1 or False or 3 > 4  # True
2 > 3 or  2 == 1 or False or 3 > 4  # False

not
取反(类似于说反话)
not 1 == 1  # False
not 2 > 10  # True

"""
上述三个逻辑运算符组合在一起使用,是有先后顺序的
    3>4 and 4>3 or 1==3 and 'x' == 'x' or 3 >3
但我们不应该考虑先后顺序,而应该主动使用括号的形式
明确执行的先后顺序
    联想小学学习的加减乘除(先乘除后加减)
    通过使用括号可以打破顺序
    (3>4 and 4>3) or ((1==3 and 'x' == 'x') or 3 >3)
"""

运算符之成员运算

判断个体在不在某个群体之内
names = ['jason', 'wxj', 'tony']
name1 = 'tom'
# 判断tom在不在学生名单内
print(name1 in names)	# False
# 判断jason在不在学生名单内
name2 = 'jason'
print(name2 in names)	# True

# 取反
print(name1 not in names)	# True
print(name2 not in names)	# False

运算符之身份运算

值是否相等(==)
内存地址是否相等(is)

l1 = [11,22,33,44]
l2 = [11,22,33,44]
print(l1 == l2)		# True	仅仅判断值是否相等
print(li is l2)		# False	判断的是内存地址是否相等
print(id(l1),id(l2))	# 1607102483592 1607102526728
'''
值相等内存地址可能不等
内存地址相同值肯定相同
'''

流程控制概念

流程控制即控制流程,具体指控制程序的执行流程,而程序的执行流程分为三种结构:
    1.顺序结构
    2.分支结构(用if判断)
    3.循环结构(用到while与for)

分支结构

人类某些时候需要根据条件来决定做什么事情,比如:如果今天下雨,就带雨伞,所以程序中必须由相应的机制来控制计算机具备人的这种判断能力
分支结构玖拾根据条件判断的真假去执行不同分支对应的子代码

# 代码编写
if
elif
else
三者只会有一个执行(执行了if就不会执行elif和else...同理...)

# 代码结构
if 条件1:		# 如果条件1的结果为True,就依次执行:代码1、代码2,...
	代码1 
    代码2
    ......
elif 条件2: # 如果条件2的结果为True,就依次执行:代码3、代码4,......
   代码3
    代码4
    ......
elif 条件3: # 如果条件3的结果为True,就依次执行:代码5、代码6,......
   代码5
    代码6
    ......
else:     # 其它情况,就依次执行:代码7、代码8,......
    代码7
    代码8
    ......  
"""
条件可以是单个 也可以是用逻辑运算符连接的多个条件的组合
"""

用户的登录功能
# 获取用户的用户名和密码
username = input('请输入您的用户名:')
password = input('请输入您的密码:')
# 判断用户名和密码是否准确
if username == 'jason' and password == '123':
    print('登录成功')
else:
    print('用户名或者密码错误')

流程控制之循环结构

人类某些时候需要重复做某件事情
所以程序中必须有相应的机制来控制计算机具备人的这种循环做事的能力

循环结构玖拾重复执行某段代码块

while 条件:
	代码1
    代码2
    代码3
    ......
# while的运行步骤
# 步骤1:如果条件为真,那么依次执行:代码1、代码2、代码3、......
# 步骤2:执行完毕后再次判断条件,如果条件为True则再次执行:代码1、代码2、代码3、......,如果条件为False,则循环终止

count = 0
while count < 5:
    print('循环了')
    count += 1
    
如何主动结束本层循环(可以理解为break只能结束距离它上方最近的一个while)
	break
    
while True:
	# 获取用户的用户名和密码
    username = input('username:')
    password = input('password:')
    # 判断用户名密码是否正确
    if username == 'jason' and password == '123':
        print('登陆成功')
        while True:
            cmd = input('请输入您的指令:')
            if cmd == 'q':
                break	# 结束本层循环
            print('正在执行您的指令:%s' % cmd)
    else:
    	print('用户名或密码错误')

如何主动结束本次循环(直接结束本次循环 开始下一次循环)
	continue

# 循环打印0-10
count = 0
while count < 11:
    print(count)
    count += 1
    
# 循环打印0-10 其中6不打印
count = 0
while count < 11:
    if count == 6:
        count += 1
        continue	# 结束本次循环
    print(count)
    count += 1

循环结构之for循环

for循环能够做到的事情while循环都可以做到,但是for循环愈发更加简单,代码更加的精简

for 变量名 in 可迭代对象:# 此时只需要知道可迭代对象可以是字符串、列表、字典
	代码1
    代码2
    ...
    
# 1.for循环列表元素
for item in ['a','b','c','d']:
    print(item)
# 运行结果
a
b
c
d

# 参照例1来介绍for循环的运行步骤
# 步骤1:从列表['a','b','c','d']中读出第一个值赋值给item(item='a'),然后执行循环体代码
# 步骤2:从列表['a','b','c','d']中读出第一个值赋值给item(item='b'),然后执行循环体代码
# 步骤3:重复以上过程知道列表中的值读尽

range方法

"""
range方法括号内可以放三个数字
放一个数字
    range(10)	表示从 0 到 9(顾头不顾尾)
放两个数字
    range(1,5)	表示从 1 到 4(顾头不顾尾)
放三个数字
    range(1,10,2)	表示从1 到 9 并且中间隔一位取一位
    [1,3,5,7,9]
"""
for i in range(0,100,25):
    print(i)
# 0
# 25
# 50
# 75

数据类型内置方法之整型与浮点型

数据的类型转换
res = '123'
print(type(res))	# <class 'str'>
res1 = int(res)		# 将字符串的123转换为数字123
print(type(res1))	# <class 'int'>
int方法只能转换纯数字的文本内容(小数点也不行)
float方法可以识别小数点

数据类型之字符串内置方法(重点)

'''Python中不同数据类型之间无法直接操作'''
res = 'hello world'
1.索引取值
print(res[1])	# e
print(res[-1])	# d		-1表示最后一位
2.切片操作
print(res[1:4])	# ell	顾头不顾尾
3.步长(间隔)
print(res[1:8:2])	# el o
4.统计长度
print(len(res))		# 11
5.类型转换(所有的数据类型都可以转换成字符串)
str(123)	str(1.11)	str([1,2,3,4])	str({'username':'jason'})
6.移除字符串首尾的空格
res1 = '   jason    '
print(len(res1))
res2 = res1.strip()
print(len(res2))
res3 = '$$jason&&'	# 还可以指定移除的字符
print(res3.strip('$'))
print(res3.strip('&'))
username = input('username:').strip()
if username == 'jason':
    print('jason你好')
else:
    print('放学啦')

代码的缩进

1.在Python中,我们通过代码的缩进来表示代码的从属关系
if age > 35 :
    print('阿姨好')
上述代码中的print('阿姨好')缩进了,那么表示它属于上面的if,它是否执行就取决于if了,而不是直接就可以执行
2.并不是所有的代码都可以拥有子代码,可以拥有子代码的
if
while
for
...

3.如果出现多行代码输入一个关键字,那么该多行代码必须是相同的缩进量

4.缩进的代码 到底缩进几位合适?
    Python中代码缩进推荐使用4个空格(windows中就是tab键)
"""
代码是否需要缩进你还可以根据一个特殊符号来判断“冒号”
一行代码的结尾如果是冒号,那么下一行代码肯定需要缩进
"""

字符串内置方法

res = 'jason|123|read'
1.字符串的切割操作(按照指定的字符切割数据)
"""当你看见字符串里面有股东的符号作为分隔符 那么应该考虑切割"""
print(res.split('|'))	# ['jason', '123', 'read'] 结果是一个列表

name, age, hobby =res.split('|')	# 将切割之后的列表的三个元素解压赋值给三个变量
print(name,age,hobby)

还可以指定切割几次 默认的顺序是从左往右
print(res.split('|', maxsplit=1))	# ['jason', '123|read']
print(res.rsplit('|', maxsplit=1))	# ['jason|123', 'read']

2.字符串转大小写
res1 = 'JaSonNB好厉害!'
print(res1.upper())		# JASONNB好厉害!
print(res1.lower())		# jasonnb好厉害!

3.判断字符串里面是否是纯数字
res2 = input('res2:')
print(res2.isdigit())

4.判断字符串以什么开头或者结尾
res3 = 'jason'
print(res3.startswith('j'))		# True
print(res3.startswith('a'))		# False
print(res3.endswith('n'))		# True
print(res3.endswith('b'))		# False

5.字符串的格式化输出
方式1:占位符 %s %d
方式2:format方法
    1.似于占位符%s
    print('my name is {} my age is {}'.format('wxj', 18))
    2.根据索引可以重复使用数据
    print('{0} my {0} name is {0} my {1} age is {1}'.format('wxj', 18))
    3.指名道姓的获取数据
    print('{name} my name is {name} my age is {age}'.format(name='wxj',age=18))

6.替换字符串
res4 = 'wxj is NB NB NB NB wxj wxj wxj'
将字符串中的wxj改为jason(类似于word里面的全局替换)
print(res4.replace('wxj', 'jason'))		# jason is NB NB NB NB jason jason jason

局部替换
print(res4.replace('wxj', 'tom', 1))	# tom is NB NB NB NB wxj wxj wxj

列表数据类型内置方法

l = [11,22,33,44,55,66,77]
1.索引取值
print(l[0])		# 11
print(l[-1])	# 77
print(l[-2])	# 66

2.切片取值
print(l[1:4])	# [22,33,44]

3.步长
print(l[1:4:2])	# [22,44]

4.统计长度(统计元素的个数)
print(len(l))	# 7

5.添加数据(尾部追加)
l.append(88)	# [11,22,33,44,55,66,77,88]
l.append([11,22])	# [11,22,33,44,55,66,77,[11,22]]

6.插入数据
l.insert(0,888)	# (索引位置,数据)
print(l)	# [888,11,22,33,44,55,66,77]

7.扩展列表
l1 = ['jason', 'wxj', 'tom']
l.extend(l1)	# 内部原理就是for循环+append操作
for i in l1:
    l.append(i)
print(l)

8.删除列表元素
l.remove(l1)	# 指定元素
l.pop()		# 尾部弹出元素
del l[1]	# 通用的删除数据的方法

9.列表生成式
l2 = ['jason', 'wxj', 'tom', 'tony']
需求:将列表中所欲的人名后面加上NB后缀生成一个新列表
方式1:
    new_l = []
    # 循环获取l2里面的每一个人名
    for name in l2 :
        # 在每一个人名后拼接NB
        new_name = name + 'NB'
        # 添加到新的列表中
        new_l.append(new_name)
    print(new_l)

方式2:
一条代码解决上述需求
new_l = [name + 'NB' for name in l2] # 先for循环 在字符串拼接 最后生成列表
print(new_l)	# ['jasonNB', 'wxjNB', 'tomNB', 'tonyNB']

10.排序
l3 = [22, 66, 33, 55, 44, 99, 77, 88, 11]
l3.sort()	# 默认是升序
print(l3)	# [11, 22, 33, 44, 55, 66, 77, 88, 99]
l3.sort(reverse=True)
print(l3)	# [99, 88, 77, 66, 55, 44, 33, 22, 11]	

字典内置方法

user_dict = {
    'username': 'jason',
    'age': 18,
    'hobbies': ['read', 'run', 'music']
}
1.按照key取值
print(user_dict['username'])	# jason
print(user_dict['xxx'])		# 键不存在会直接报错
print(user_dict.get('username'))	# jason
print(user_dict.get('xxx'))		# None(空)	键不存在不会报错

2.统计键值对的个数
print(len(user_dict))	# 3

3.修改数据(将username键对应值修改为wxj)		键存在的情况下修改
user_dict['username'] = 'wxj'
print(user_dict)	# {'username': 'tony', 'age': 18, 'hobbies': ['read', 'run', 'music']}
user_dict['password'] = '123'			键不存在的情况下则新增个键值对
print(user_dict)	# {'username': 'tony', 'age': 18, 'hobbies': ['read', 'run', 'music'], 'password':'123'}

4.删除数据
user_dict.pop('username')	# 指定键 弹出对应的键值对数据
print(user_dict)

可变与不可变类型

可变类型:值改变,内存地址不变(列表、字典)
不可变类型:值改变,内存地址肯定变(整型,浮点型,字符串)

res = 'jason'
print(id(res))
res = res + 'NB'
print(id(res),res)

l = [11,22,33]
print(id[l])
l.append(44)
print(id(l))
"""
如果不明白,那么直接记忆即可
"""

元祖与集合

元祖内元素不能被修改,你可以把元祖直接看成是不可修改的列表即可
t = (1,2,3)

集合内元素必须是不可变类型(数字、字符串)
s = {1,2,3}

# 去重
集合内不可能存在重复的元素,自动去重

# 关系运算
f1 = {'jason', 'jerry', 'tom', 'owen'}
f2 = {'jason', 'kevin', 'oscar', 'jerry'}
# 求两个人共同好友
print(f1 & f2)  # {'jerry', 'jason'}
# 求两个人的所有好友
print(f1 | f2)  # {'jerry', 'owen', 'jason', 'kevin', 'oscar', 'tom'}
# 求某个人的独有的好友
print(f1 - f2)  # {'tom', 'owen'}
print(f2 - f1)  # {'kevin', 'oscar'}
# 求两个人各自独有的好友
print(f1 ^ f2)  # {'tom', 'owen', 'oscar', 'kevin'}

字符编码

字符编码主要是用来研究文本文件内部数据的存储原理
不适用于除文本文件以外的其他文件类型

1.一家独大
    计算机是由美国人发明的,美国人是用的是英文
    而计算机只能识别01二进制数,如何让计算机能够认识英文呢?
    美国人发明了英文字符与数字对应得关系标准
    ASCII码
    	该编码表记录了英文字符与数字之间的对应关系
        基于ASCII码表的计算机只认识英文,不认识其他国家的语言
        ASCII码使用8bit来表示英文字符
        其实7bit足够表示所有英文,多一位是为了后续扩展考虑
            
2.群雄割据
	中国
    GBK编码表
    	记录了中文字符、英文字符与数字之间的对应关系
    日本
    shift_JIS表
    	记录了日文字符、英文字符与数字之间的对应关系
    韩国
    Euc_kr表
        记录了韩文字符、英文字符与数字之间的对应关系
    # 但这样会导致不同国家之间的计算机无法实现数据交互
    
3.天下统一
	Unicode万国码
    	记录了所有国家的字符与数字的对应关系
    Unicode在存储数据的时候统一都是采用2bytes存储数据
    针对Unicode存储的问题我们做了优化
    utf8编码
    	针对Unicode做存储优化
        针对英文还是采用1bytes
        针对中文采用3bytes
"""
我们目前在使用文本文件保存数据的时候
统一使用的编码就是utf8
"""
文件之所以会乱码,其实就是因为采用的编码本不一致导致的
文件存的时候才用的是编码本1 文件读取的时候才用的是编码本2

我们解决乱码的方式其实就是保住文件在存储和打开的时候采用的是同一个编码本即可

文本转义

# 斜杠与字母的组合有时候会产生特殊意义
res = 'D:\project\nython\tachong'
print(res)
# 取消转义
res1 = r'D:\project\nython\tachong'
print(res1)

路径

路径其实就是用来标识文件位置的信息
相对路径
    需要有一个参照物
绝对路径
    不需要参考物

文件操作

通过Python代码来操作文件的读写过程

下面的写法不推荐使用 因为每次open都需要close
f = open(r'aaa.txt', 'r', encoding='utf8')
print(f.read())	# 读取文件内容
f.close()  # 关闭文件

推荐使用with语法
只能打开文本文件
with open(r'aaa.txt', 'r', encoding='utf8') as f :
    print(f.read())	# 当with的子代码执行完毕之后会自动帮你调用close
打开所有文件
with open(r'D:\数据分析三期\linux基础\day5\day5-昨日回顾、重定向、打包压缩.mp4', 'rb') as f:
    for line in f:
        print(line)

文件操作之读写模式

r
	只读模式(用r模式打开的文件只能读取内容,不能写入)
w
	只写模式(用w模式打开的文件只能写入内容,不能读取)
a
	只追加模式

只读模式

1.文件路径不存在:r模式会直接报错
with open (r'b.txt', 'r', encoding='utf8') as f :
    pass 	# 补全语法结构但是本身并没有任何含义

2.文件路径存在:打开该文件支持读内容
with open (r'a.txt', 'r', encoding='utf8') as f:
    print(f.read())	# 可以读内容
    f.write('你好啊')	# 不支持写内容

只写模式

1.文件路径不存在:会自动创建文件
with open (r'b.txt', 'r', encoding='utf8') as f :
    pass 

2.文件路径存在:
"""
1.先清空该文件内容
2.再写入新数据内容
虽然w模式打开已经存在的文件会清空文件内容,但是工作中我们主要是创建新文件并写入数据
"""
with open(r'a.txt', 'w', encoding='utf8') as f:
    f.writr('你好啊!')		# 写入内容

只追加模式

1.文件路径不存在:会自动创建文件
with open(r'c.txt', 'a', encoding='utf8') as f:
    pass

2.文件路径存在:
    2.1 不会清空文件内容 
    2.2 在文件末尾主追加新的内容
with open (r'a.txt', 'a', encoding='utf8') as f:
    f.write('你好啊!')	# 支持写内容

操作模式

t
文本模式(文件默认是t模式)
    rt
        open(r'a.txt', 'rt', encoding='utf8')
    wt
    	open(r'a.txt', 'wt', encoding='utf8')
    at
    	open(r'a.txt', 'at', encoding='utf8')
1.该模式只能操作文本文件
2.读写都是以字符串为单位
3.必须要加encoding参数
    
b
二进制模式
    rb
        open(r'a.txt', 'rb')
    wb
        open(r'a.txt', 'wb')
    ab
        open(r'a.txt', 'ab')
 1.该模式都是可以操作任意类型的文件
 2.读写都是以bytes为单位
 3.一定不能加encoding参数
    
针对二进制模式rb wb ab与rt wt at规律一致
with open(r'a.txt', 'rb') as f:
    res = f.read()
    print(type(res))	# <class 'bytes'>
    res1 = res.decode('utf8')
    print(type(res1))	# <class 'str'>

with open(r'b.txt', 'wb') as f:
    f.write('大宝贝'.encode('utf8'))	# 包含中文需要使用关键字encode
    f.write(b'big baby')	# 如果是纯英文 只需要在最前面加一个b即可
    
利用b模式完成文件的拷贝功能
先利用rb读取图片数据
with open(r'111.jpg', 'rb') as f:
    data = f.read()
再利用wb写入到新文件
with open(r'D:\333.jpg', 'wb') as f:
    f.write(data)

常见方法及策略

with open(r'a.txt', 'r', encoding='utf8') as f:
    print(f.read())		# 一次性将文件内容全部读出来
    print(f.readable())	# 判断文件是否可读
    print(f.readline())	# 一次只读文件一行
    print(f.readlines())	# 结果是列表 一个个元素就是一行行内容
    
    
试想如果文件特别大,直接全部读取出来会产生内存溢出(爆满)
'''在读取文件内容的时候一般都是采用下列的方式一行行读取'''
for line in f:
    print(line)
    
with open(r'b.txt', 'w', encoding='utf8') as f:
    print(f.write())	# 写内容
    print(f.writeable())	# 判断文件是否可写
    print(f.writelines(['jason\n', 'wxj\n']))
    f.flush()	# 立刻将文件内容保存到硬盘 相当于Ctrl+s

文件修改

方式1(当文件过大的时候可能会造成内存溢出)
先以rt模式读取文件内容
with open(r'c.txt', 'r', encoding='utf8') as f:
    data = f.read()
再以wt模式写入文件内容
with open(r'c.txt', 'w', encoding='utf8') as f:
	f.write(data.replace('jason', 'tony'))

方式2:
先创建一个新的文件,循环读取老文件内容修改并写入新文件
之后将老文件删除,将新文件名修改为老文件名
import os

with open(r'c.txt', 'r', encoding='utf8') as read_f, \
        open(r'c.backend.txt', 'w', encoding='utf8') as write_f:
    for line in read_f:
        write_f.write(line.replace('tony', 'BigBaby'))
删除c.txt
os.remove(r'c.txt')
将c.backend.txt重命名为c.txt
os.rename(r'c.backend.txt', r'c.txt')

函数

函数其实就是工具,我们提前准备好工具,之后要想使用就可以直接拿来就用并且可以反复使用
eg:修理工在修理东西的时候需要用到老虎钳、扳手...
    如果没有工具就需要现场打造
    如果提前准备好直接拿来就可以使用
在我们写代码的时候也是如此,有时候需要反复的执行某一段代码,并且在不同的位置执行,那么直个时候我们也可以考虑将代码制作成函数(工具)

在程序中,具备某一功能的‘工具’指的就是函数,‘事先准备工具‘的过程即函数的定义,’拿来就用‘即函数的调用

准备工具
def auth_login():
    username = input('username:')
    password = input('password:')
    if username == 'wxj' and password == '123':
        print('登录成功')
    else:
        print('登录失败')
        
使用工具
auth_login()
'''准备好工具之后,将来就可以反复的在任意位置使用,从而减少代码冗余'''

函数语法

固定句式
def 函数名(参数1,参数2, ...):
    '''函数的注释'''
    函数代码体
    return 函数的返回值
1.def(必须的)
	是定义函数的关键字
2.函数名(必须的)
	遵循变量名的命名规范
3.参数(可选)
	在使用函数的时候还可以给函数内部传入外界数据
4.函数的注释(可选)
	用来解释函数的具体功能以及参数含义(类似于说明书)
5.函数体代码(必须的)
	其实就是函数真正的业务逻辑
6.return(可选)
	执行玩函数之后,还可以给调用函数的人返回一些数据
    
    
    
################################################################# 
注意
1.函数必须先定义之后才能使用
auth_login()  # 不能在函数定义之前使用
# 准备工具(先定义)
def auth_login():
    username = input('username>>>:')
    password = input('password>>>:')
    if username == 'jason' and password == '123':
        print('登录成功')
    else:
        print('登录失败')
# 使用工具(后使用)
auth_login()  # 使用函数的过程我们称之为"函数的调用"

2.函数在定义阶段只识别语法不执行函数体代码,只有在调用函数的时候才会执行
def index():
    sdasd
    print('from index')
################################################################# 

函数的返回值

1.不写return默认返回None
	def index():
            print('from index')
2.写了return,后面跟上什么就返回什么
	def index():
            print('from index')
            return 123
        res = index()
3.如果是多个元素会自动组织称元祖返回
	def index():
            print('from index')
            return 123,11,22,33
        res = index()
4.函数体代码遇到return就会自动结束整个函数的运行(类似于break)

参数的概念

我们在定义函数的时候括号内写的变量名称之为函数的形式参数
	简称"形参“
我们在调用函数的时候括号内写的真是数据称之为函数的实际参数
	简称"实参"
形参类似于变量名,实参类似于变量的值,在调用函数的时候会将实参赋值给形参函数运行结束自动接触关系
def index(x,y):	# x,y形参
    """
    将1赋值给了形参x
    将2赋值给了形参y
    x = 1
    y = 2
    """
    if x > y:
        print(x)
    else:
        print(y)
index(1,2)	# 1,2实参

函数的参数值位置参数

针对位置参数,有几个就传几个,多了不行少了也不行
传值的时候玖拾按照前后顺序给形参赋值

函数的参数之关键字参数

指名道姓的给对应的形参传值
def index(x,y):
    print(x,y)
index(x=11, y=12)	# 全部按照关键字参数
index(11,y=22)		# 位置参数 关键字参数

index(y=22, 11)		# 关键字参数必须写在位置参数的后面
index(11,x=66)		# 一个形参只能赋值一次

函数的参数之默认参数

在函数的定义阶段就已经给形参赋值,称之为默认参数
    1.用户不传改参数的就用默认的
    2.用户传了的就用传了的
    
def register(name, age, gender='male'):
    print('%s:%s:%s' % (name, age, gender))
    
    
register('jason', 18)
register('tony', 32)
register('jerry', 44)
register('lili', 18, 'female')

函数参数之可变长参数

需求1:函数无论接收多少个位置参数都可以正常的执行
def index(a,*x):
    print(x)
*在形参中会接收多余的位置参数并组织成元祖的形式赋值给*后面的变量名
index(1)  # ()
index(1, 2)  # (2,)
index(1, 2, 3, 4)  # (2, 3, 4)
需求2:函数无论接收多少个关键字参数都可以正常执行
def index(b, **y):
     print(y)
**在形参中会接收多余的关键字参数并组织成字典的形式赋值给**后面的变量名
index(b=1)  # {}
index(b=1, a=2, z=3)  # {'a': 2, 'z': 3}
如何定义一个函数无论接收多少位置参数和关键字参数都可以运行???
def index(*x, **y):
    print(x, y)
index()  # () {}
index(1, 2, 3)  # (1, 2, 3) {}
index(x=1, y=2, z=3)  # () {'x': 1, 'y': 2, 'z': 3}
index(1, 2, 3, x=1, y=2, z=3)  # (1, 2, 3) {'x': 1, 'y': 2, 'z': 3}
"""
在形参中书写在*和**后面的变量名可以自定义
但是我们会墨守成规的使用下列的命名方式
    *args
    **kwargs
def func(*args, **kwargs):
    pass
"""

模块

可以是别人写好的代码,也可以是自己写的代码
倒入模块其实就会执行模块所对应的py文件,然后将执行之后产生的数据交给导入者使用

本地导入
    1.导入自己写的代码(自己写的)
    	import mymd
    2.导入本地自带的模块(Python自带的)
    	import time
    3.还可以导入网络上第三方开放的模块
    	pip3	# 下载模块的工具
        1.需要将pip所在的文件路径添加到环境变量中
        	D:\python3\Scripts
        2.输入pip3检验是否有效果(一定要重新打开一个cmd窗口)
        3.下载网络上的模块
        	pip3 install 模块名
利用pip3下载模块的地址默认是国外的仓库,速度可能会很慢
我们可以修改下载模块的地址,修改为国内的地址
(1)阿里云 http://mirrors.aliyun.com/pypi/simple/
(2)豆瓣http://pypi.douban.com/simple/
(3)清华大学 https://pypi.tuna.tsinghua.edu.cn/simple/
(4)中国科学技术大学 http://pypi.mirrors.ustc.edu.cn/simple/
(5)华中科技大学http://pypi.hustunique.com/
指定下载地址
pip3 install 模块名 -i http://pypi.douban.com/simple/
pycharm也提供了快捷下载模块的功能

导入模块的语句
方式1
import 模块名  # 所有资源
方式2
from 模块名 import ...  # 从里面拿指定的资源

如果模块的名字比较长 我们还可以给模块起别名
import 模块名 as 别名

常见模块的使用

"""
作为一名python工程师,当需要使用一些较为复杂的功能的时候,不要想着直接自己动手完成,而应该想着有没有相应的模块直接帮忙实现
"""
使用模块基本上都是通过模块名点点点来完成操作的

时间模块
import time

时间戳:1970年1月1日距离刚刚代码执行距离的秒数
print(time.time())
time.sleep(3)	# 将程序沉睡3秒之后再运行
print(time.strftime('%Y-%m-%d %H:%M:%S'))
print(time.strftime('%Y-%m-%d'))
print(time.strftime('%m-%d'))
"""
%Y 年
%m 月
%d 日
%H 时
%M 分
%S 秒
"""

import datetime
print(datetime.datetime.today())	# 年月日时分秒
print(datetime.date.today())		# 年月日

import os
os.mkdair(r'文件路径')	# 创建文件夹

随机数模块
import random

print(random.random())	# 随机产生一个0-1之间的小数
print(random.randint(1,6))	# 随机产生一个1-6之间的整数(掷骰子)
res = ['特等奖','一等奖','二等奖','三等奖','谢谢惠顾']
print(random.choice(res))	# 随机选择一个元素(抽奖,随机抽查)
l = [2, 3, 4, 5, 6, 7, 8, 9, 10, 'J', 'Q', 'K', 'A']
random.shuffle(l)	# 随机打乱顺序(洗牌)
print(l)
验证码:大写字母 小写字母 数字 三者随机结合产生的
print(chr(65))	# A
print(chr(90))	# Z
chr将数字按照ASCII码表转换成对应的字符
"""
A-Z	65-90
a-z	97-122
"""

小练习:生成五位数的随机验证码

code = ''
for i in range(5):
    # 随机生成一个大写字母
    upper_str = chr(random.randint(65,90))
    # 随机生成一个小写字母
    lower_str = chr(random.randint(97,122))
    # 随机生成一个数字
    random_int = str(random.randint(0,9))
    # 随机从上面三个中去一个
    tmp = random.choice([upper_str,lower_str,random_int])
    # 字符串的拼接
    code += tmp
print(code)


加密模块:将一串明文的数据加密成无法直接识别的内容
加密的目的其实就是为了保证明文数据的安全
import hashlib
加密的方法有很多 常见的有md5加密  sha加密
md5 = hashlib.md5()	# 生成一个md5加密的工具
将明文数据录入
md5.update(b'jason123')
获取md5加密之后的密文结果
res = md5.hexdigest()
print(res)

加盐处理:在需要加密的数据前面人为的添加一些干扰项
import hashlib
加密的算法有很多 常见的有md5加密 sha加密
md5 = hashlib.md5()  # 生成一个md5加密的工具
将明文数据录入
md5.update('公司内部自己定的一个干扰项'.encode('utf8'))
md5.update(b'jason123')
获取md5加密之后的密文结果
res = md5.hexdigest()
print(res)

动态加盐
import hashlib
加密的算法有很多 常见的有md5加密 sha加密
md5 = hashlib.md5()  # 生成一个md5加密的工具
将明文数据录入
md5.update('每一次的干扰项都不一样'.encode('utf8'))
md5.update(b'jason123')
获取md5加密之后的密文结果
res = md5.hexdigest()
print(res)

面向对象

对象:其实就是一个内部包含了数据和功能的容器
类:多个对象之间相同的数据和功能的结合体(减少代码冗余)
# 学生对象1:
    数据:
        学校=清华大学
        姓名=李建刚
        性别=男
        年龄=28
    功能:
        选课
# 学生对象2:
    数据:
        学校=清华大学
        姓名=王大力
        性别=女
        年龄=18
    功能:
        选课
# 学生对象3:
    数据:
        学校=清华大学
        姓名=牛嗷嗷
        性别=男
        年龄=38
    功能:
        选课
# 学生类
    相同的特征:
        学校=清华大学
    相同的功能:
        选课
# 在编程世界里必须要先有类才能产生对象
class Student: # 类的命名应该使用“驼峰体”
    school='清华大学' # 数据
    def choose(self): # 功能
        print('choosing a course')
    
"""
类的语法结构
class 类名:
	相同的数据
	相同的功能
1.class
	定义类的关键字
2.类名
	命名规范与变量名一致,并且类名推荐首字母大写
3.相同的数据
	变量名 = 变量值
4.相同的功能
	def 函数名():
		pass
"""
"""对象如果需要拥有自己独有的数据 必须在类里面定义一个__init__方法"""


class Student:  # 类的命名应该使用“驼峰体”
    school = '清华大学'  # 数据

    # 对象独有的数据
    def __init__(self, name, age, gender):
        self.name = name  # 固定写法
        self.age = age
        self.gender = gender

    def choose(self):  # 功能
        print('%s正在选课'%self.name)


obj1 = Student('jason', 18, 'male')
obj2 = Student('tony', 32, 'male')
obj3 = Student('tom', 33, 'female')
print(obj1.school)
print(obj2.school)
print(obj3.school)
print(obj1.name)
print(obj2.name)
print(obj3.name)  # 对象点数据
obj1.choose()  # 对象点方法
obj2.choose()
obj3.choose()
posted @ 2021-03-26 15:50  孔夫子挂妖刀  阅读(229)  评论(0)    收藏  举报