Python基础---从hello world到面向对象
python基础
python简介
python是一个高层次的结合了解释性、编译型、互动性和面向对象型的脚本语言。
解析型语言意味着python
没有了像C语言
编译这样的环节。类似于php
。
交互式语言意味着可以在一个python
提示符>>>
下执行代码。
面向对象语言意味着支持python
支持面向对象将代码封装在对象的编程技术。
python是初学编程者最合适的语言,他是伟大的,既支持应用开发,从简单的文字处理到www浏览器到游戏。
python环境
python支持Windows、Linux、Mac多种平台。
通过终端
窗口输入python
就可以查看本机是否安装了python
windows安装python
下载python
python官网:https://www.python.org/downloads/windows/
下载合适的版本即可
配置环境变量
安装pycharm
pycharm是一个专业的python开发环境软件,当然可以使用其他的环境。
pycharm官网:
https://www.jetbrains.com/pycharm/download/#section=windows
安装完成后,可以进入终端输入python
进入>>>
然后输入print('hello world')
实现学习python的第一行代码
Python 3.9.13 (tags/v3.9.13:6de2ca5, May 17 2022, 16:36:42) [MSC v.1929 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> print('hello world')
hello world
>>>
python中文编码
前面我们已经学会hello world
,但是如果你输入你好,世界
python可能就会报错,是因为python编码的问题。
python2
默认编码是ascii
,没有修改编码的时候python无法读取汉字,所以读取中文会报错。
只需要在python文件开头加入,# -*- encoding: UTF-8 -*-
或者# encoding=utf-8
即可。
如果使用的是python3
环境,python3
中默认使用的就是utf-8
编码,就不会报错。
python基础语法
交互式编程
交互式编程不需要创建文件,只需要在python解释器
中进行编写代码
只需要在终端中输入python
就可以进入交互式终端,进入后会类似如下代码:
Python 3.9.13 (tags/v3.9.13:6de2ca5, May 17 2022, 16:36:42) [MSC v.1929 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>>
只需要在终端中输入print('hello world')
然后回车就可以执行代码
>>> print('hello world')
hello world
脚本式编程
脚本式需要创建一个文件,然后后缀名以.py
结尾。这里我创建一个test.py
下方代码是test.py
内容
print('hello world')
如果这里环境变量配置正确,进入创建文件的目录,打开终端输入
python test.py
,就可以指定代码
D:\>python test.py
hello world
python2
和python3
的兼容性
如果python2
想要使用python3
的print
,可以导入__future__
模块
form __future__ import print.funcation
print('hello world')
# 可以在python2中正常运行
python标识符
python,标识符由字母、数字、下划线组成
。
在python中,所有的标识符可以包括英文、数字、下划线
但是不能使用数字开头。
python可以同一行执行多条代码,必须使用;
隔开
Python 3.9.13 (tags/v3.9.13:6de2ca5, May 17 2022, 16:36:42) [MSC v.1929 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> print('hello world');print('nihao')
hello world
nihao
python变量类型
变量是存储在内存中的,这就意味着在创建变量的时候会在内存中开辟一个空间。
变量可以指定不同的数据类型,可以存储整数、小数或字符
。
基于变量的类型,解释器会分配指定内存,并决定那些数据是可以存储在内存中。
变量赋值
python中的变量不需要声明数据类型
。
每个变量在进行创建时,都包括变量的标识,名称和数据。
每个变量都需要进行赋值,只有赋值后变量才会进行创建。
等号=
用来给变量赋值。
格式为:变量名 = 值
,也就是等号左边的为变量名,右边的为赋给变量的值。
实例:
name = "Jungle"
print(name)
# 结果输入 Jungle
多个变量赋值
如果多个变量需要使用相同的值
a = b = c = 1
根据变量赋值格式:变量名 = 值
,首先1
赋值给c
,然后c
的值就是1
,然后将c
赋值为b
,所有b
也是1
,那么a
也同理。
如果多个变量不同的值
a,b,c = 'lql','zt','zmz'
格式为:变量1,变量2,变量3,变量... = 'aaa','bbb','ccc'....
同样左边的为变量名,然后不同的变量名通过,
逗号隔开,然后等号右边的不同变量的值也通过,
逗号隔开,第一个值就赋值给第一个变量,第二个赋值给第二个变量....
标准数据类型
上述说到,在内存中存储的数据可以有多种数据类型。
例如:一个人的名字可以使用字符串
来表示,而一个人的年龄可以用数字
来表示
Python定义了一些标准的数据类型,用于在内存中存储各种数据类型,如下:
- Nubmer(数字)
- String(字符串)
- List(列表)
- Tunple(元组)
- Dictionary(字典)
python数字
数字数据类型用于存储数值。
他们是不可改变的数据类型,这意味着改变数字数据类型会分配一个新的对象。
当你指定一个数字值时,数字类型就会被创建,例如:
num1 = 1
num2 = 11
可以使用del
删除声明的变量。
del num1
del num1,num2
python中支持四种不同的数字类型
- int(整形)
- long(长整型,可以代表八进制和十六进制)需要注意是的在python3中long已经被
int
类型代替 - float(浮点型)
- complex(复数型)
下列举例一些常见的数据,以及数据类型的分类
值 | 类型 | 特点 |
---|---|---|
0,1,5,7,10,-1,10 | 整形(int) | 由整数组成 |
0.1 ,0.5 ,0.00001 ,-1.1 |
浮点型(float) | 只有一个点 |
12 + 02.j |
复数型(complex) | 复数的特点呗 |
python字符串
字符串(strings)是有数字、字母和特殊字符组成。最常用到的数据类型,常用于表示文本。
表现形式:变量名 = "值"
,值通过单引号、双引号
包裹。例如:
str1 = 'love'
str2 = "LQL"
字符串也可以视为列表,可以进行下标取值。其中取值有两种方法
例如字符串有有三位,为LQL
L | Q | L | |
---|---|---|---|
方法1 | 0 | 1 | 2 |
方法2 | -3 | -2 | -1 |
可以使用这两种方式进行取值。格式为:变量名[下标]
str1 = "love"
print(str1[0]) # 值是l
print(str1[1]) # 值是o
# 第二种方法
print(str1[-2]) # 值是v
print(str1[-1]) # 值是e
如果要实现取出一段数据的方法,可以使用切片
的方法
格式:[开始下标:结束下标]
# coding=utf-8
str1 = "love 191"
print(str1[0:3]) # 值是lov
# 0 对应的是 l
# 3 对应的是 e
# 根据结果可以看出这个区间取值的方法包含开始不包含结束
print(str1[-3:-1]) # 值是 19
# 当取值中开始下标或者结束下标为空的时候,会直接定位最开始或最后
print(str1[0:]) # 值是 love 191
print(str1[:-4]) # 值是 love
字符串中之间使用+
代表字符串的拼接,*
代表重复次数
print("I" + "love" + "you")
# 输入 Iloveyou
print("I love you , 191" * 521)
# 输出 I love you , 191 一共 521次
python列表
列表也是python中经常使用的数据类型。
列表可以完成多种数据的集合。它支持字符、数字、字符串,甚至包含列表(嵌套)
列表使用[]
标识,其中每个值使用,
逗号隔开。
列表获取数据和刚刚讲的字符串获取数据一样的,通过下标
和切片
。例如:
list1 = ['Junglezt','Jackson','Bob']
list2 = ['www']
# 下标获取
print(list1[1]) # 返回 Jackson
print(list1[-1]) # 返回 Bob
# 切片
print(list1[1:3]) # 返回 ['Jackson', 'Bob']
print(list1[2:]) # 返回 ['Bob']
print(list1 + list2) # ['Junglezt', 'Jackson', 'Bob', 'www']
print(list1 * 2) # ['Junglezt', 'Jackson', 'Bob', 'Junglezt', 'Jackson', 'Bob']
python元组
元组是另一个数据类型,类似于list
列表
元组用()
标识,中间使用,
逗号隔开。但是元组不可以进行二次赋值,相当于只读列表。
tunple1 = ('test','aaa','bbb','ccc')
tunple2 = ('baidu','com')
print(tunple1[3]) # 返回 ccc
print(tunple2[1]) # 返回 com
print(tunple1[0:2]) # 返回 ('test', 'aaa')
print(tunple1 + tunple2) # 返回 ('test', 'aaa', 'bbb', 'ccc', 'baidu', 'com')
print(tunple2 * 2) # 返回 ('baidu', 'com', 'baidu', 'com')
上述说到,元组是不可改变的,列表是可以的,所以再次给元组赋值时会报错。
实例:
list1 = ['aaa','bbb','ccc']
tunple1 = ('test','aaa','bbb')
# 更改列表的值
list1[0] = "你好"
print(tunple1)
print(list1)
# 更改元组的值
tunple1[1] = '你好'
返回结果,可以看到报错了。
Traceback (most recent call last):
File "test.py", line 10, in <module>
tunple[1] = '你好'
TypeError: 'tuple' object does not support item assignment
('test', 'aaa', 'bbb')
['你好', 'bbb', 'ccc']
python字典
字典(dictionary)使除了列表以外最灵活的数据类型。列表是有序的集合,而字典是无序的。
与列表不同的字典通过键名
来获取值
。字典的标识是{}
,字典中的值是有键名
和键值
组成,其中一个键名
对应一个键值
,若需要更多的值使用,
逗号隔开,继续下一个值。
格式为:{'键名1':'键值1',"键名2":"键值2"}
。实例:
dict = {}
dict['first'] = 'hello'
dict[2] = 'world'
test_dict = {"name":"Junglezt","age":"18"}
print(dict['first']) # 打印 hello
print(dict[2]) # 打印 wrold
print(test_dict) # 打印列表
print(test_dict.keys()) # 获取所有key
print(test_dict.values()) # 获取所有值
返回结果
hello
world
{'name': 'Junglezt', 'age': '18'}
dict_keys(['name', 'age'])
dict_values(['Junglezt', '18'])
python数据类型转换
一些情况,我们需要对数据的类型转换,方便我们处理。
数据类型的转换的函数名很简单容易记住,就是我们要转换为的数据类型的名称。
例如我们要转换为列表
类型,就是list
转换为列表类型的函数就是list()
大部分是这样的,常见的数据类型转换的函数如下:
方法 | 作用 |
---|---|
int() |
转换为数字类型整形 |
float() |
转换为数字类型浮点型 |
cpmplex() |
转换为一个复数型,或者可以说创建一个复数 |
str() |
转换为字符串类型 |
repr() |
将对象转换为字符串 |
tunple() |
转换为一个元组 |
list() |
转换为一个列表 |
dict() |
转化为一个字典,条件是必须满足key:value 的条件 |
chr() |
将ascii 值转换为对应的字符 |
ord() |
将字符转换为ascii 值 |
bin() |
将数字转换为二进制 |
oct() |
将数字转换为八进制 |
hex() |
将数字转换为十六进制 |
这里不在一一举例。
python运算符
python中支持多种多样的运算符,什么是运算符,1+2=3
这可以称为一个算数运算
,4和5
是运算的字符,+
被称为算数运算符。
python支持以下几种运算符
算数运算符、比较运算符、赋值运算符、逻辑运算符、位运算符、成员运算符、身份运算符、运算符优先级
看样子很多运算符,很难?这怎么可能?那就让我来逐步击破吧
算符运算符
算数运算符是最简单的,就和数学是一样的,不过有一些特殊的算法。
python支持以下的运算符
运算符 | 作用 | 实例 |
---|---|---|
+ | 加法运算 | 1 + 2 = 3 |
- | 减法运算 | 5 - 3 = 2 |
* | 乘法运算 | 3 * 2 = 6 |
/ | 除法运算,结果为浮点数 |
10 / 2 = 5.0 |
% | 取余运算,得到余数 | 20 % 8 = 4 |
** | 幂运算,几次方 | 2 ** 3 = 8 |
// | 整除运算,得到结果的整数位 | 7 // 3 = 2 |
上述的大多数运算符只能对数字数据类型
使用,特殊的+、*
可以对其他的数据类型使用,在字符串和列表中+
代表拼接的意思,*
代表重复次数的意思。
eval()
函数
python中为算符运算符提供了一个遍历的函数eval()
,他的功能类似于计算器,能将输入的公式进行计算。
print(eval("1 + 2 * 3 / 4 * 5"))
# 返回 8.5
当然计算
只是eval()
函数的其中一个功能,在使用eval()
函数的使用,移动要谨慎使用,最好不要吧input()
动态传输的参数传入到eval()
函数,因为该函数也可以执行系统内置函数和方法。
# 可以使用__import__('模块名')导入模块
# 其中os模块下的system方法可以执行系统命令
print(eval("__import__('os').system('dir')"))
可以执行系统命令
比较运算符
大于,小于,等于就是这样
比较运算符返回的结果只有,True
和False
,正确
和错误
对了,需要注意的是如果比较两个值是否相等,使用的是双等号==
,因为单个等于号是=
赋值的意思,或许会详细讲到。
运算符 | 作用 | 实例 |
---|---|---|
== | 等于 | 1 == 1 (True) |
!= | 不等于 | 1 != 2 (True) |
<> | 不等于,python3已经弃用 | 1 <> 3 (True) |
> | 大于 | 3 > 2 (True) |
< | 小于 | 1 < 5 (True) |
>= | 大于等于 | 5 > 4 (True) 5 >= 5 (True) |
<= | 小于等于 | 8 < 9 (True) 8 <= 8 (True) |
上述也是只对于数字的比较,字符串也是可以进行比较的,只不过比较的是他的ascii
值,使用chr()
和ord()
可以快速转换字符串
的ascii
值
例如:a
的ascii
值是97
,b
的ascii
值是98
,所以在比较字符串'a' > 'b'
的时候,返回的结果是False
# 查看a和b的ascii值
print(ord('a'),ord('b')) # 返回 97 98
print(chr(97),chr(98)) # 返回 a b
# 比较 a 和 b
print('a' > 'b') # False
print('a' < 'b') # True
赋值运算符
上述我们已经使用过了变量的赋值=
运算符,这里介绍更多的赋值运算符
只有=
赋值运算使用最多,其他的大概了解即可。
运算符 | 作用 |
---|---|
= | 简单的赋值运算 |
+= | 加法赋值运算,a += c 就是 a = a + c |
-= | 减法赋值运算,a -= c 就是 a = a - c |
*= | 乘法赋值运算,a *= c 就是 a = a * c |
/= | 除法赋值运算, a /= c 就是 a = a / c |
%= | 取余赋值预算, a %= c 就是 a = a % c |
**= | 幂赋值运算, a **= c 就是 a = a ** c |
//= | 取整赋值运算, a //= c 就是 a = a // c |
可能理解着有点别扭,看一下实例:
# 简单的赋值运算
a = 5
# 加法赋值运算
a = 2
b = 3
a += b # 就是 a = a + b,也就是 2 + 3 = 5
print(a) # 返回结果是 5
# 减法赋值运算
aa = 111
bb = 55
aa -= bb # 就是 aa = aa - bb,也就是 111 - 55 = 56
print(aa) # 返回结果是 56
# 或许的类似,不在叙述
位运算
位运算是相对于数字的二进制
值进行预算。
先不说位运算
,这里叙述一下Python中的二进制、八进制、十六进制
,他们的表现形式为
进制 | 表述形式 |
---|---|
二进制 | 0b 开头 |
八进制 | 0o 开头 |
十六进制 | 0x 开头 |
print(0b10) # 返回 2
print(0o10) # 返回 8
print(0x10) # 返回 16
我们通常使用的进制为十进制
,就是逢十进一
,例如0,1,2,3,4,5,6,7,8,9
到了10
就需要进一位,而二进制是逢二进一
,八进制就是逢七进一
,十六进制就是逢十六进一
反码、补码
计算机在平常我们使用算数运算的时候,其实使用的就是二进制
运算,输入的值都会别识别为二进制
然后进行运算
这里我们来看一下5
和-5
的运算
# 5 和 -5 相加的二进制原理
a = 5
b = -5
# 首先 5 和 -5 转换为二进制
# 5 二进制 b0000 0101
# 在进行二进制运算时,最高位为符号位,0代表正数,1代表负数
# -5 二进制 b1000 0101
# 负数在进行运算时需要执行 反码 和 补码 两个过程
# 反码 : 符号位不变,其余取反,就是1变0,0变1
# 补码 : 在反码的基础上 + 1
# 所以在进行运算前需要将 -5 的二进制进行 反码 和 补码
# 原始 : b1000 0101
# 反码 : b1111 1010
# 补码 : b1111 1011
# 然后进行预算
# 5 的二进制 b0000 0101
# -5 反码补码后的二进制 b1111 1011
# 结果 : b10000 0000
# 得到的结果一共九位,二进制只能有八位,对多出的舍弃,所以最后的结果为
# 0b0000 0000
print(a + b) # 输出 0
# 所以结果就是 0
位运算符
运算符 | 作用 |
---|---|
& | 按位与运算 ,只有两个值都为1 结果才是1 ,否则为0 |
| | 按位或运算 ,两个值只要有一个1 ,值就是1,否则为0 |
^ | 按位异或预算 ,两个值不同是,值为1 |
~ | 按位取反 ,单独的预算,1 变0 ,0 变1 |
<< | 左移动运算符,将二进制全部向左移动指定位数,不受反码、补码影响 |
>> | 右移动运算符,将二进制全部向右移动指定位数,不受反码、补码影响 |
a = 60 # 60 = 0011 1100
b = 10 # 10 = 0000 1010
print(a & b) # 8 = 0000 1000
print(a | b) # 62 = 00111110
print(~a) # -61 = 11000011 # 需要进行 反码、补码,注意符号位不计入计算
print(a ^ b) # 54 = 0011 0110
print(a << 2) # 240 = 1111 0000
print(a >> 3) # 15 = 0000 1111
逻辑运算符
逻辑运算符是编写程序的精髓,很多情况下我们都需要逻辑运算符
运算符 | 作用 |
---|---|
and |
逻辑与 ,通常为x and y 的格式,通过布尔值进行判断,如果有一个布尔值为False 返回值就是False ,必须全部返回的值都是True ,结果才是True |
or |
逻辑或 ,通常为x or y 的格式,通过布尔值进行判断,如果有一个布尔值为True 返回值就是True ,必须全部返回的值都是False ,结果才是False |
not |
逻辑非 ,not x ,是非颠倒,如果x 为True 返回结果就是False ,如果为False ,返回结果就是True |
实例:
print(True and True) # 返回 True
print(True and False) # 返回 False
print(True and False and True) # 返回 False
# 在进行逻辑运算的时候,会进行布尔值类型的隐士转换
print(33 and 55) # 返回 55
print(bool(33)) # 返回 True
print(bool(55)) # 返回 True
# 逻辑 or 运算
print(False or True) # 返回 True
print(False or False) # 返回 False
print(False or False or True) # 返回 True
# 逻辑非
print(not False) # True
print(not True) # False
and 在遇到 False 时停止
or 在遇到 True 是停止
在逻辑运算符中,优先级not > and > or
成员运算符
成员运算符用于判断指定值
是否在序列中,这些序列例如字符串、列表、元组
运算符 | 作用 |
---|---|
in | 如果在指定的序列中找到了返回True ,否则False |
not in | 如果在指定的序列中没有找到返回True ,找到了返回False |
str1 = "fsjkldfjsadlfjasd;lfdjsal;fadjslf;adsjkfl;adsjkfl"
# in
print("f" in str1) # 返回 True
print("i" in str1) # 返回 False
# not in
print("f" not in str1) # 返回 False
print("i" not in str1) # 返回 True
身份运算符
身份运算符用于比较两个对象的存储单元,就是比较在内存中地址是否相同
运算符 | 作用 |
---|---|
is | 判断两个标识符 是否引用一个对象,x is y 类似于id(x) == id(y) 这样的命令,如果相同True ,不相同返回False |
is not | 判断两个标识符 是否引用不同对象,x is not y 类似于id(x) != id(y) |
id()
函数用于获取对象的内存地址。
a = 10
b = 20
print(a is b) # False
print(a is not b) # True
a = 100
b = 100
print(a is b) # True
print(a is not b) # False
数值在内存中有缓冲区
,其中保存的有-5
到256
的数据,在这个段的数据都会先指向缓冲区,由于pycharm
有优化,在终端
中进行测试
Python 3.9.13 (tags/v3.9.13:6de2ca5, May 17 2022, 16:36:42) [MSC v.1929 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> a = 256
>>> b = 256
>>> a is b
True
>>> a = 257
>>> b = 257
>>> a is b
False
运算符优先级
讲了很多很多的运算符,他们和数学一样是有优先级
,例如小学学习的先算乘除,再算加减
。
下边通过从高往低
来介绍运算符的优先级
运算符 | 描述 |
---|---|
** | 幂运算,最高级别 |
~ | 按位取反 |
* / % // | 乘、除、取余、取整 |
+ - | 加、减 |
>> << | 右移,左移位运算 |
& | 按位与 |
^ | | 按位异或、按位或 |
<= < > >= | 比较运算符 |
<> == != | 等于运算符 |
= | 赋值运算符 |
is、is not | 身份运算符 |
in、not in | 成员运算符 |
not and or | 逻辑运算符 |
所以呢,可以总结一下,在有算数规则的时候,先进行
算符规则(+、-、*、/)
>位运算
>比较运算
>等于运算
>身份运算
>成员运算
>逻辑运算(not and or)
大概了解即刻,一定要知道not > and > or
逻辑运算的优先级。
python条件语句
Python条件语句通过一条或多条语句的执行结果的布尔值(Ture、False)
来决定代码块
。可以简单理解为条件满足执行的语句
,不满足条件执行的语句
。
if语句的格式为:
if 判断条件:
条件满足执行的语句
else:
条件不满足执行的语句
python中在:
后面的语句需要进行缩进
,其代表的意思就是一段代码块。
缩进相同代表代码在同一范围。
可以看一个具体的例子:
name = "Junglezt"
# 只有在 name 的值是 Jack 才会执行打印 Jack,nice to meet you
if name == "Jack":
print("Jack,nice to meet you")
# 条件不满足,输出 He's not Jack 他不是Jack
else:
print("He's not Jack")
上述是一个很简答的例子,通过名称判断name
是否为Jack
,如果是输出Jack
输出Jack,nice to meet you
,如果不是He's not Jack
。
if语句的判断条件
可以是各种表达式
,例如常见的> >= < <= == !=
返回的结果是布尔值
类型,可以进行有效的判断。
上述是一种条件,如果有多个名字呢,例如:我想把Alice
也加入,对其输出Alice ? I think I know you.
这里就使用到了if
语句的多条件判断,格式如下:
if 判断条件1:
执行代码1
elif 判断条件2:
执行代码2
elif 判断条件3:
执行代码3
elif 判断条件4:
执行代码4
else:
执行代码
其中elif
可以拥有多个,也可以没有,看实例:
name = "Alice"
# 判断是否为 Jack
if name == "Jack":
print("Jack,nice to meet you")
# 判断是否为 Alice
elif name == "Alice":
print("Alice? I think I know you.")
# 如果两个条件都不满足
else:
print("He's not Jack or Alice")
python不支持switch ... case ..
语句,只能使用elif
来进行判断,有些时候可以使用一个条件进行判断,就是使用or
。
例如:if name == "Jack" or name == "Alice"
,这样也可以达到同样的目的。
num = 226
# 判断数字是否在 200 ~ 300 之间
if num >= 200 and num <= 300:
print("这个数字在200 ~ 300之间")
else:
print("这个数字不在200 ~ 300之间")
也可以在一行使用if
语句
a = 5
if a > 3 : print('这个数字大于3')
if语句可以进行嵌套
# 例如模拟车站入口
resp = input("你问题买票了吗?(yes/no)")
if resp == 'yes':
print("你买票了,请过安检!")
resp = input("是否通过了安检(yes/no)")
if resp == "yes":
print('恭喜你通过了安检!去候车区等待上车吧')
else:
print("你很可疑呢?诶?这个是什么?")
else:
print("你没有买票,你去售票台买票")
While循环
Python中使用while
循环执行程序,在条件成立的情况下
,循环执行某段语句
,d达到重复处理相同的任务。格式为:
while 判断条件:
执行语句
当判断条件
返回值为True
时,执行循环中的语句,判断条件
返回值为False
跳过循环或者说循环结束。类似于if
语句。
可以通过断点来查看while
循环的详细流程
a = 0
while a < 10:
print(a)
a += 3
在上述情况中,如果不在循环中对a
的值进行递增
,就会造成死循环
a = 0
while a < 10:
print(a)
# 这里就会不停的输出 a 的值 0
循环输出1~9
num = 1
while num < 10:
print(num)
num += 1
break、continue
while也支持break
和continue
关键字,非常的重要,break
用于结束本次循环,continue
用于跳过本轮循环,具体看实例:
# 循环 1~10,奇数跳过,偶数输出
num = 1
while num < 11:
# 如果除以 2 的余数不为0
if num % 2 != 0:
num += 1
continue
else:
print(num)
num += 1
# 循环 1~10 ,大于 10 时,停止循环
num = 1
while num < 100:
if num > 10:
break
print(num)
num += 1
while ... else ...
上述说到while
循环类似于if
和if
一样,while
可以使用while ... else...
格式的语句。
num = 1
while num <= 5:
print(num)
num += 1
else:
print("数字已经大于5")
1
2
3
4
5
数字已经大于5
while 简答语句
while也可以单行进行使用
num = 1
while num <= 5: print(num);num +=1
for循环
python可以使用循环遍历任何序列的项目,例如:列表
、字符串
for循环的语法格式如下:
for 迭代变量 in 迭代对象:
循环体
可能看着有一点奇怪,看个例子:
# 循环字符串
name = "LQL"
for a in name:
print(a)
# 循环列表
list = ['爱在西元前','发如雪','说走就走']
for b in list:
print(b)
结果
L
Q
L
爱在西元前
发如雪
说走就走
range()
如果我们想要循环一些数字就是用到了range()
方法,
方法 | 作用 |
---|---|
range(start,stop,step) |
生成一个指定范围的数字,包含开始,不包含结束,start为开始值,stop为结束值,step为步长 |
是用实例:
# 输入 1~9 数字
for i in range(1,10):
print(i)
# 输出 0 2 4 6 8
for j in range(0,10,2):
print(j)
for ... else ..
和while
循环语句一样,for
循环也支持for ... else...
语句。
这里标注一个重点,循环
重的else语句是在循环结束后执行的语句。
for i in range(1,6):
print(i)
else:
print("循环结束了")
1
2
3
4
5
循环结束了
求质数
首先:在自然数中,质数是只有1和本身以外没有其他因数,就是只能通过1和本身乘法得到该结果。
得到这个条件,书写代码
# 求 1~100 的质数
for i in range(1,101):
for j in range(2,i):
if i % j == 0:
break
else:
print(i)
Python中的循环是可以进行嵌套的,上述就是用了循环嵌套
pass关键字
pass关键字用于占位,可以理解为没用的,空的
例如我们执行if语句的时候:
后面的代码块必须有内容,有时我们现在不知道要写什么,可以使用pass
展示代替。
age = int(input("请输入你的年龄: "))
if age >= 18:
print('你成年了')
else:
pass
input()
函数会获取用户输入的信息,默认格式为字符串。
上述案例中,如果输入的数字大于18,就会打印你成年了,如果不满足条件,就会不予理睬。
python字符串
字符串是Python中最常用的数据类型。通常使用''
和""
进行包裹。
创建字符串字需要在''
或者""
中加入值即可。
str1 = "hello world"
str2 = 'hello python'
访问字符串
在上述简单数据类型的时候,我们已经讲解过可以使用下标
和切片
获取字符串的内容。
格式为:字符串[下标]
、字符串[开始下标、结束下标]
str1 = "hello world"
str2 = 'hello python'
print(str1[0]) # h
print(str1[0:6]) # hello
print(str2[-1]) # n
print(str2[-6:]) # python
字符串拼接、重复
字符串之间可以使用+
运算符进行拼接'你' + '好'
为你好
。
str1 = "你"
str2 = "好"
print(str1 + str2) # 你好
print("love " + "191") # love 191
想要重复单个字符串多次,可以使用*
多次
a = 'love 191\n' * 1314
print(a)
# 这里的 \n 是转义字符,为\n
转义字符
在需要使用特殊字符的时候,什么是特殊字符,例如换行
,tab
键这种特殊字符,Python中使用\
反斜杠代表转义字符。
常见的特殊字符如下:
特殊字符 | 作用 |
---|---|
\\ | 一个反斜杠字符 |
\' | 一个单引号 |
\" | 一个双引号 |
\b | 退格键,Baskspace |
\n | 换行 |
\r | 回车 |
\t | 横向制表符 |
\v | 纵向制表符 |
\f | 翻页 |
字符串常用运算符
字符串会常使用一下运算符
运算符 | 作用 | 实例 |
---|---|---|
+ | 将+ 号两边的字符串 进行拼接 |
"a" + "b" = "ab" |
* | 将字符串重复 指定次数 |
"a" * 2 = "aa" |
[] | 下标取值 | "abc"[0] = "a" |
[:] | 切片取值 | "abcdefg"[0:3] = "abc" |
in | 成员运算符 | "a" in "abc" = "True" |
not in | 成员运算符 | "a" not in "abc" = "False" |
r/R | 原始字符串,不使用转义,打印最原始的字符串,开头r 可以大写可以小写 |
print(r'\n') = \n |
% | 格式化字符串,或许详细讲解 | print("abc%d"%100) = abc100 |
例如成员运算符,可以判断指定的字符
是否在字符串
中。
str = "love 191"
print("191" in str) # True
print("love" not in str) # False
格式化字符串
Python支持格式化字符串输出。这样会用到更复杂的表达式,最基本的用法是将一个字符串
插入到一个带有字符串格式符%s
的字符串中。如下例子:
print("你好,%s"%"世界")
# 你好,世界
print("今天的天气是%s,温度是%d°"%("晴天",23))
# 今天的天气是晴天,温度是23°
上述使用到了%s
字符串的替换和%d
数字的替换,当然不仅仅是这些。
下列为常用格式化字符:
格式化字符 | 作用 |
---|---|
%s | 格式化字符串 |
%d | 格式化整数 |
%f | 格式化浮点数 |
%c | 格式化ascii 值 |
三引号
上述说到单引号
和双引号
可以创建字符串,三个单引号
和三个双引号
其实也可以进行创建字符串。
三个引号默认是多行注释的意思,可以书写多行的注释。
如果在开头使用赋值运算符
就可以进行变量的创建。
'''
我是一段注释
可以换行的注释
# 号只是单独的一行的注释
'''
str = """
我也是一个字符串变量,
我与普通'或"不一样的我可以进行换行,
没想到吧,我就是这么好用,
但是人们平常不使用我呢,
但有些人喜欢使用,就是这样。
"""
print(str)
Unicode字符串
定义Unicode字符串
很简单,和原始字符串类似,字符需要在字符串前加入u
即可。
str = u"hello world"
print(str)
# hello world
str2 = u"你好,\u4e16\u754c"
print(str2)
# 你好,世界
字符串常用内置方法
后续在进行我们会很多次使用到字符串,这里学习字符串常用的内置方法
方法 | 作用 |
---|---|
str.capitalize() |
首字母大写 |
str.count() |
计算指定字符出现的次数 |
str.decode() |
解码字符串 |
str.encode() |
编码字符串 |
str.find() |
查找字符串下标,默认左边第一个 |
str.strip() |
去除字符串左右两边的空 |
str.replace() |
替换字符串,注意字符串值不可改变类型 |
str.split() |
分割字符串 |
str.lower() |
字母全小写 |
str.upper() |
字母全大写 |
str.partition() |
使用指定字符将字符串分割为三个元组元素 例如: print('test.jpg'.partition('.')) 输出: ('test','.','jpg') |
str.index() |
和find() 类似,查找指定字符下标,默认左边第一个,错误会返回一个异常 |
str.format() |
格式化字符串,和% 方法类似,专门用于格式化字符串的方法 |
str = "heLLo woRLD"
# 首字母大写
print(str.capitalize()) # Hello world
# 计算一共有几个 L 的值
print(str.count('L')) # 3 一共有三个 L 字符
# 使用gbk编码字符串
print(str.encode('gbk')) # b'heLLo woRLD'
# 查找从左边字符串第一次出现的下标
print(str.index('L')) # 2
print(str.find('o')) # 4
# 查找从右边字符串第一次出现的下标
print(str.rindex('L')) # 9
print(str.rfind('o')) # 7
# 替换字符串的值
# 注意这里字符串值不可变类型,需要新创建一个字符串保存替换后字符串的值
str2 = str.replace("woRLD","191")
print(str2) # heLLo 191
# 使用空格分割字符串为列表
print(str.split(' ')) # ['heLLo', 'woRLD']
# 全大写
print(str.upper()) # HELLO WORLD
# 全小写
print(str.lower()) # hello world
format()格式化字符串
format()
和%
的使用方法类似,使用{}
代替之前的%
。看实例:
str = "{} {}"
print(str.format("hello","world")) # 可以赋予控制
# hello world
# 根据下标赋值
str = "{0} {1}"
print(str.format("world","hello"))
# world hello
str = "{0} {1} {0}"
print(str.format("world","hello"))
# world hello world
# 根据属性赋值
print("名称:{name},喜欢:{like}".format(name="Jungelzt",like="write python code"))
上述就是format()
函数的简单用法。
format()
函数也可以调用字典中的键名
和键值
对应的方法,需要在字典前加入**
。看实例:
dict = {"name":"IG","sign":"中国第一个英雄联盟LPL世界冠军。"}
print("战队名称:{name},标志:{sign}".format(**dict))
# 战队名称:IG,标志:中国第一个英雄联盟LPL世界冠军。
print("网站:{name},地址:{url}".format(**{"name":"百度一下,你就知道","url":"http://www.baidu.com"}))
# 网站:百度一下,你就知道,地址:http://www.baidu.com
详细使用方法:于菜鸟教程-python字符串
python列表
列表
属于序列
,序列
中的每一个值都会分配一个值(位置)
,可以叫做下标,索引
,第一个的索引是0,第二个的索引是1...以此类推。
Python中最常用的序列就是列表
和元组
序列
可以进行索引、切片、加、乘,成员运算
等操作。
序列
中内置确定序列长度、最大值、最小值
的方法。
此次我们将的列表是一个很常用的数据类型,其中每个值使用逗号隔开,最外层使用[]
包裹,列表中的值可以是任何数据类型,当然也可以是列表(列表嵌套)。
在之前的案例中我们已经简单了解过
列表
。
创建列表:
list1 = ['值1','值2','值3']
list2 = [1,2,3,4,5,6]
访问列表值
和字符串类似的方法,可以使用下标
和切片获取数据
names = ["周杰伦","孙燕姿","许嵩","韩红","成龙"]
print(names[0]) # 周杰伦
print(names[1:4]) # ['孙燕姿', '许嵩', '韩红']
更新列表
也就是在列表中插入新值,最常用的方式就是list.append('值')
# 定义一个空列表
list = []
# 在列表最后加入 Junglezt 值
list.append('Junglezt')
print(list) # ['Junglezt']
# 在列表最后加入值
list.append('http://cnblogs.com/Junglezt')
print(list)
# ['Junglezt', 'http://cnblogs.com/Junglezt']
另一个常用的方法insert()
也可以在列表中插入数据,insert()
可以指定下标插入值。格式为insert(下标,值)
list = ['Junglezt', 'http://cnblogs.com/Junglezt']
list.insert(0,'博客园')
print(list)
# ['博客园', 'Junglezt', 'http://cnblogs.com/Junglezt']
删除列表元素
常用的列表删除值得方法有del、remove()和pop()
list= ['博客园', 'Junglezt', 'http://cnblogs.com/Junglezt']
# del
# 删除列表中下标为 0 的值
del list[0]
print(list)
# ['Junglezt', 'http://cnblogs.com/Junglezt']
# remove()
# 指定列表值为 Junglezt 的值进行删除
list.remove('Junglezt')
print(list)
# ['http://cnblogs.com/Junglezt']
# pop()
# pop()方法默认会将列表中最后的值进行删除,并会将删除的值作为返回结果
test = list.pop()
print(test)
# http://cnblogs.com/Junglezt
# pop()
# pop() 可以执行下标获取删除的值
list = ['a','b','c']
str = list.pop(2)
print(str)
# 返回 c
列表常用操作
列表会经常使用以下运算符
操作 | 作用 | 值 |
---|---|---|
len(['a','b','c']) |
获取列表元素个数 | 3 |
['a','b','c'] + ['d','e','f'] |
列表拼接 | ['a','b','c','d','e','f'] |
['a'] * 5 |
列表重复 | ['a','a','a','a','a'] |
'c' in ['a','b','c'] |
成员运算 | True |
for i in ['a','b','c'] |
循环对象 | 迭代值,第一次a,第二次b,第三次c |
列表常用函数
方法 | 作用 |
---|---|
len() |
获取列表元素个数 |
max() |
返回列表最大值,如果是字母,按照ascii 比较 |
min() |
返回列表最小值 |
list() |
转换为列表类型 |
com() |
比较列表值 |
列表常用的方法
方法 | 作用 |
---|---|
list.append(值) |
在列表最后添加元素 |
list.count(值) |
计算元素在列表中出现的次数 |
list.extend(序列) |
在列表最后追加另一个序列的值,类似于+ |
list.index(值) |
查找列表元素的下标 |
list.insert(下标,值) |
在列表指定下标追加值 |
list.remove(值) |
在列表中删除指定元素 |
list.pop(下标) |
在列表中删除指定下标 ,并将删除元素作为返回结果,如果不指定元素下标,默认删除最后一个元素 |
list.reverse() |
列表排序,元素倒序排序,反向排序 |
list.sort(reverse=False) |
列表排序,默认使用升序排序,首先符号、数字、大写字母、小写字母 ,reverse 为True 时为降序 |
详细使用,菜鸟教程-python列表
list1 = ['Junglezt','226','$_zt','test','test']
# count()
# 计算 test 在列表中出现的次数
print(list1.count('test')) # 2
# extend()
list2 = ('a','b','c')
# 将 list2 元组序列的值,添加到 list1 列表序列中
list1.extend(list2)
print(list1)
# ['Junglezt', '226', '$_zt', 'test', 'test', 'a', 'b', 'c']
# index()
# 在列表中查找 226 的下标
print(list1.index('226')) # 1
# reverse()
# 对列表进行倒序排序
list1.reverse()
print(list1)
# ['c', 'b', 'a', 'test', 'test', '$_zt', '226', 'Junglezt']
# sort()
# 对列表进行 字符、数字、大写字母、小写字母 升序排序
list1.sort()
print(list1)
# ['$_zt', '226', 'Junglezt', 'a', 'b', 'c', 'test', 'test']
# 对列表进行 字母、数字、大写字母、小写字母 降序排序
list1.sort(reverse=True)
print(list1)
# ['test', 'test', 'c', 'b', 'a', 'Junglezt', '226', '$_zt']
python元组
元组和列表使用的方法是一样的,不过列表不可以进行值得修改。
如果说列表
是游戏中的角色临时buf
,那么元组
就可以看为游戏中角色默认属性
,是不可以进行修改的。
元组和列表的使用基本一直,这里不在进行叙述。
元组最重要一点
在我们进行变量名1,变量名2,变量名3 = 值1,值2,值3
这种格式赋值时,其实使用的就是元组赋值,相当于变量名1,变量名2,变量名3 = (值1,值2,值3)
a,b,c = "001","002","003"
print(a,b,c) # 001 002 003
# 加上括号
o,p,q = ("111","222","333")
print(o,p,q) # 111 222 333
# 可以看出,上述两条语句是一样的
python字典
字典很常用,格式为每个元素
由key:value
组成,这里我们就成为键:值
。
字典中的元素
是由键
和值
组成,之间使用:
隔开,这是一个元素;每个元素之间使用,
逗号隔开,最外层使用{}
大括号进行包裹。
格式为:{key1:value1,key2:value2,key3:...}
上述列表和字符串采用下标取值,而字典是没有下标的,采用key
键的方式取值。
基本操作
获取字典值、赋予字典新值、修改字典值、删除值。
# 注意:使用 dict 给字典的变量命名是不规范的,不建议使用。
dict = {'name':'Junglezt','age':'18'}
# 获取字典值
print(dict['name']) # Junglezt
# 给字典赋值
dict['sign'] = "一个在学习网络安全的小萌新。"
print(dict)
# {'name': 'Junglezt', 'age': '18', 'dign': '一个在学习网络安全的小萌新。'}
# 修改字典值
dict['name'],dict['sign'] = 'LQL','like Her'
print(dict)
# {'name': 'LQL', 'age': '18', 'sign': 'like Her'}
# 删除字典元素
del dict['name']
print(dict) # {'age': '18'}
# 删除字典
del dict
字典键的特性
字典的健有两个重要的特点
- 在创建字典时,不能拥有相同的键名,如果创建了,后创建的键名的值回被记住
- 键名是不可变类型,可以是用数字、字符串、元组,但是不可以使用
列表
。注意:字符串和元组是不可变类型。
# 后创建的键名会被记住
dict = {'name':'Junglezt','name':'LQL'}
print(dict['name'])
# LQL
如果键名为列表,则会报错
dict = {['list']:"test"}
Traceback (most recent call last):
File "test.py", line 3, in <module>
dict = {['list']:"test"}
TypeError: unhashable type: 'list'
# 类型错误: 不允许的类型,列表
字典常用函数
函数 | 作用 |
---|---|
cmp() |
比较两个字典元素 |
len() |
计算字典元素个数 |
str() |
转换为字符串类型 |
type() |
查看数据类型 |
字典常用方法
方法 | 作用 |
---|---|
dict.keys() |
获取字典所有键名 |
dict.values() |
获取字典所有值 |
dict.clear() |
清空字典 |
dcit.copy() |
对字典进行浅拷贝 |
dict.fromkeys(key,value) |
创建一个新字典,键名为key,值为value |
dict.get(key,value) |
和dict[键名] 获取值得方法一样,get() 在没有查找到结果会返回None ,而通过dict[键名] 会报错,返回值可以通过value 自定义 |
dict.items() |
items() 方法会获取字典中所有的键名和值 ,然后组成一个元组。 |
dict.update() |
把指定字典中的键和值 更新到当前字典 |
dict.pop(key,default) |
删除指定键 的值,没有找到`键会报错,可以通过设置默认返回值来避免。 |
dict.popitem() |
删除字典中最后一个元组的键和值 ,并以元组作为放回结果(键,值) |
fromkeys()
在不对元素值进行赋值时,默认值为None
,如果直接使用列表对元素值进行赋值,会直接将列表赋值过去,需要遍历列表值,进行赋值。
key = ['name','age','sign']
dict = dict.fromkeys(key)
print(dict)
# {'name': None, 'age': None, 'sign': None}
value = ['Junglezt','22','like security']
# 这里可以直接遍历value列表即可,当时也不知道脑子怎么想的,这种方法
for i in range(0,len(value)):
dict = dict.fromkeys(key,value[i])
print(dict)
# {'name': 'like security', 'age': 'like security', 'sign': 'like security'}
items()
items()方法会获取字典中元素的键和值
并将每个元素组成一个元组
dict = {'name':'Junglezt','age':'22','sign':'like security'}
print(dict.items())
# {'name': 'like security', 'age': 'like security', 'sign': 'like security'}
# 通过 items() 遍历字典所有的键和值
for key,value in dict.items():
print(key,value)
返回结果:
name Junglezt
age 22
sign like security
pop()、popitem()
pop()
可以指定删除的键值,并将删除键的值
作为返回结果,如果没有找到该键值,默认会报错,设置默认返回值可以避免该结果。
popitem()
会删除字典最后的元素,将键名和值
组合为元组进行返回(键,值)
,如果字典为空,则会报错。
dict1 = {'name':'Junglezt','age':'22','sign':'like security'}
# pop(key,default)
resp = dict1.pop('name')
print(resp) # Junglezt
aaa = dict1.pop('test','没有找到该键名')
print(aaa) # 没有找到该键名
# popitem()
bbb = dict1.popitem()
print(bbb) # ('sign', 'like security')
python日期和时间
python有很多处理日期的方式,转换日期格式是一个很常见的功能。当然这里我只知道一个time
模块。
时间间隔使用的是以秒为单位的浮点小数
。
每个时间戳
都是从1970年1月1日午夜(历元)
经过了多长时间表示。
当前时间戳
在time
模块下可以进行很多时间格式
的转换,常见的有time.time()
获取当前时间的时间戳。
import time
now = time.time()
print("当前时间戳是",now)
# 当前时间戳是 1666228226.9647925
时间戳适合做日期运算。但是1970年以前的日期就无法表示了,遥远的日期也不可以,windows
只支持到2038年
。
获取当前时间
时间戳我们是看不懂的,需要将其转换为可以看懂的格式,这是就用到time.localtime()
方法。
import time
now = time.time()
print(time.localtime(now))
# time.struct_time(tm_year=2022, tm_mon=10, tm_mday=20, tm_hour=9, tm_min=25, tm_sec=9, tm_wday=3, tm_yday=293, tm_isdst=0)
# 根据返回结果,可以看出时间为 2022 10/20 9:25 星期四 今天的293天
其实time.local.time()
方法不需要添值,可以直接获取当前时间。
这里每个值以tim_名称
开头,这是一个时间元祖
。具体含义:
属性 | 作用 | 值 |
---|---|---|
tm_year |
年份 | |
tm_mon |
月份 | 1-12 |
tm_mday |
日数 | 1-31 |
tm_hour |
小时 | 0-23 |
tm_min |
分钟 | 0-59 |
tm_sec |
秒,60或者61是闰秒 | 0-61 |
tm_wday |
星期,0是周一 | 0-6 |
tm_yday |
今年第几天, | 0-366 |
tm_isdst |
夏令时 | 0、1、-1 |
格式化当前时间
上述使用localtime()
方法获取的时间只是对时间戳进行了格式化,得到的只是一个时间元组
格式的时间,还需要我们手动进行解析,总之这不是最终想要的结果,还需要使用time.asctime()
格式化时间。
import time
now = time.time()
# 使用 time.asctime()方法格式化 时间元组
print(time.asctime(time.localtime(now)))
# 返回时间类型为:
# 星期 月份 日期 小时:分钟:秒 年
# Thu Oct 20 09:41:11 2022
这样就得到了一个看着很顺眼的时间。
上述使用了time()
方法获取当前时间戳,然后使用localtime()
解析当前时间戳获取当前时间,最后使用asctime()
方法格式化当前时间,所以我们就得到一个步骤。
时间戳 -> 解析 -> 格式化
strftime()
格式化时间
strftime()
方法专门用于格式化时间。
import time
print (time.strftime("%Y-%m-%d %H:%M:%S",time.localtime()))
# 2022-10-20 09:57:41
上述使用到了%Y、%m
这样的格式化时间字符,详细:
字符 | 作用 | 值 |
---|---|---|
%Y |
当前年份 | 00-99 |
%y |
当前年份 | 0000-9999 |
%m |
月份 | 01-12 |
%d |
月份中的某一天 | 0-31 |
%H |
24小时制小时 | 0-23 |
%I |
12小时制时间 | 01-12 |
%M |
分钟 | 00-59 |
%S |
秒 | 00-59 |
%b、%h |
当前月份 | 英文缩写,十月(Oct) |
%a |
当前星期 | 英文缩写,星期四(Thu) |
%B |
当前月份 | 全写 |
%A |
当前星期 | 全写 |
%j |
年内的一天 | 001-366 |
%p |
上午或下午 | AM 或者PM |
%U |
一年的第一个星期 | 00-53 |
%Z |
时区 | 例如:中国标准时间 |
%x |
显示日期 | 例如:10/20/22 ,月份/日期/年份 |
%X |
显示时间 | 例如:10:43:02 ,小时/分钟/秒 |
%c |
本地相应日期和时间 | 例如:Thu Oct 20 10:43:36 2022 星期 月份 天 小时:分钟:秒 年 |
python函数
函数是组织好的,可以重复使用的,用来实现单一或相关联功能的代码。
函数可以重复利用,Python中有许多内置函数,比如我们常用的函数print()
我们也可以自定义函数,被称为用户自定义函数。
定义、调用函数
定义函数的目的一般是为了实现某一个功能,函数的规则:
- 使用 def 进行定义,然后跟函数标志符,然后跟上
()
。- 任何函数中的代码必须都在
()
中。- 函数第一行一般是函数的注释介绍。
- 函数内容由
:
冒号开始,必须遵守缩进。return[表达式]
结束函数,选择性返回一个值。不使用return
默认返回None
。
语法:
def 函数名称(参数):
"注释——函数说明"
函数内容
return [返回值]
例如这里将一个值传入函数,最后将值输入到页面。
# 定义函数
def print_text(name):
# 函数说明
"打印传入的name"
# 函数功能,打印
print(name)
# 函数结束
return
# 调用函数
print_text('我的老哥')
# 我的老哥
参数传递
在python
中,变量属于对象,是没有数据类型的。
a = [1,2,3]
a = 'Junglezt'
在上述代码中,[1,2,3]
是list(列表)
类型,'Junglezt'
是str(字符串)
类型,而变量a
是没有数据类型的,变量的作用仅仅是一个指针(引用),可以是列表
也可以是字符串
。
mutable
和immutable
对象
就是可变类型和不可变数据类型,前面在讲解字符串
等数据类型事有提到过,字符串、元组、数字
是不可变数据类型,而列表、字典
是可变数据类型。
不可变数据类型
例如如果我们赋值变量a = 1
,这是如果我们想修改a
的值,需要再次赋值变量a
,例如:a = 2
这并不是修改,而是重新赋值,实际上是新生成了一个数字对象2
,然后指向a
,之间的1
值被丢弃。注意这里并不是修改了a
的值,可以理解为重复赋值,新创建了一个a
值。
参数传递
比如整数、元组、字符串
,例如:function(a)
,传递的只是a
的值,对a
的本身没有影响。如果在function(a)
内部修改a
值,只是修改函数内部复制的a
值,不会影响对象a
本身
可变数据类型
例如变量a = [1,2,3,4]
,然后再赋值a[1] = 5
,这里是将a
中第二个元素进行修改,a
本身并没哟进行修改,只是将内部的值进行了修改。
参数传递
比如列表、字典
,例如:``funcation(b),将
b值真正的传递过去,如果在函数中修改对象
b值,对象
b`会真正发生改变。
在python按照严格来说,一切都是对象,我们并不能说是值传递,还是引用传递,应该说传不可变对象
和传可变对象
。
实例
# 不可变类型,字符串实例
def fun1(test):
test = 10
print("函数中的test值",test)
return
test = 226
# 调用 fun1 方法
fun1(test) # 10
print("函数外的test值:",test) # 226
# 可变数据类型,列表实例
def fun2(test):
test.append('Junglezt')
test.append('Jackson')
print("函数中的test",test)
return
test = ['Alice','Bob']
print("函数外的test值",test) # ['Alice', 'Bob']
# 调用 fun2
fun2(test) # ['Alice', 'Bob', 'Junglezt', 'Jackson']
print("调用fun2方法后,test值",test) # ['Alice', 'Bob', 'Junglezt', 'Jackson']
# 可以看出 可变数据类型 在方法中确实会被修改
必备参数
必备参数必须以正常的顺序传入函数。调用时的数量必须和声明是的数量一样。
如果在调用上述模拟print
的print_test()
函数,我们必须传入一个参数,否则会报错。
# 定义函数
def print_test(name):
print(name)
return
# 调用函数
print_test()
返回结果
Traceback (most recent call last):
File "test.py", line 6, in <module>
print_test()
TypeError: print_test() missing 1 required positional argument: 'name'
# 类型错误:print_test() 缺少一个必备的位置参数
关键字参数
关键字参数和函数调用时关系紧密,函数调用使用关键字
可以确定传入的参数值
在我们使用函数时,需要按照函数定义好的参数顺序进行值的传递,在使用关键字参数传递值,因为直接采用属性名进行传递,顺序是不重要的。
看一下实例:
def print_info(name,age,sign):
print("Name",name)
print("age",age)
print("sign",sign)
return
# print_info("Junglezt",18,"like security")
# 采用 关键字 值传递,和上述代码效果一样
print_info(sign = "like security",name = "Junglezt",age = 18)
返回结果
Name Junglezt
age 18
sign like security
不定长参数
在声明参数的时候,有时传入的参数会多出我们声明的参数。可以使用*
开头的参数,将接收的未定义的多出的参数进行存储,这个参数叫做不定长参数
。
实例:
# * 开头为 不定长参数
def print_info(name,age,*str):
print("name:",name)
print("age:",age)
# 循环多出的 参数
for i in str:
print("{}:".format(i),i)
return
print_info("junglezt",18)
print("-------------------------")
print_info("Junglezt",18,"test","aaa","bbb")
返回结果
name: junglezt
age: 18
-------------------------
name: Junglezt
age: 18
test: test
aaa: aaa
bbb: bbb
匿名函数
Python使用lambda
来创建匿名函数
lambda
是一个表达式,比定义函数def
方法要简单很多。
语法格式:
lambda [参数1,参数2,...]:方法
具体使用:
# 定义 sum() 进行数字加法运算
sum = lambda num1 , num2 : num1 + num2
# 调用函数
sum(10,20) # 没有返回结构,因为并没有将结果进行打印
# 使用 print() 嵌套 sum()
print(sum(10,20)) # 返回 30
print(sum(100,200)) # 返回 300
return语句
在定义函数的最后,用于定义返回结果。没哟定义返回结果默认值为None
格式:return[表达式]
在之前中没哟使用过return
的返回结果,这里详细演示
# 定义 ride() 乘法运算函数,但不定义 return 返回结果
def ride(num1,num2):
result = num1 * num2
return
print(ride(2,2)) # 返回值为 None
# 定义返回结果为运算结果
def ride(num1,num2):
result = num1 * num2
return result
print(ride(2,2)) # 返回 4
变量作用域
一个程序的变量不是在哪里都可以访问的,这取决的变量在哪个作用域进行的赋值。
分别分为
- 全局变量
- 局部变量
全部变量可以在程序的任何位置进行访问,而局部变量只能在函数或者是被定义的作用域进行使用。看例子:
result = 0 # 这是一个全局变量
def sum(num1,num2):
result = num1 + num2 # 这是一个局部变量
print("局部变量result的值为:",result)
return result
sum(50,50) # 调用 sum() 函数
print(result) # 返回结果 0
# 可以看到调用了sum()函数后,result的结果还是0
# 说明sum()函数中的result值并没有起到效果
# 打印输入的结果还是全部变量result的值 0
python模块
模块(module)
,是一个python
文件,以.py
结尾,包含了python
对象定义和python语句
模块可以让你有逻辑的组织你的代码段,在使用相关的代码放到一个模块中,能让你的代码更好用,更易懂。
模块中能定义函数、类和变量,模块;就是一个python
文件
例如,以下是一个名为test.py
的python
文件
def print_test(main):
print(main)
return
该文件可以理解为一个python
,也可以被当做module
模块导入到其他的python
文件。
import导入模块
上述我们就相当于定义了一个python
模块,这时只需要我们导入即可。
格式:import 模块名
,例如导入test
模块。import test
如果想要使用test
模块下的print_test()
需要使用以下格式:模块名.函数名
。例如:test.print_test()
# 导入 test 模块
import test
# 使用 test 模块中的 print_test() 方法
test.print_test("Junglezt")
# Junglezt
在进行模块的导入时,一般将import
语句方法程序的开头。
在执行import
语句的时候,如果模块
在当前路径,就会被导入。
一个模块只会别导入一次,不管执行了多少次的import
,这样做是为了防止导入模块被一遍又一遍的执行。
注意事项:在导入模块的时候,可以使用
__file__
内置方法获取模块文件地址,给python
文件命名,不要起名和模块名
一样。
from ... import
from ... import
是用于导入模块中的函数,并不会将模块进行导入,只是导入模块指定的一个函数。
from 模块名 import 函数1,函数2,函数3...
注意事项:在使用
from...import...
的导入两个不同模块中两个一样的函数名时,后导入的函数或对象会被纪录,如果非要在两个不同模块中,导入两个相同的函数名,可以使用as
关键字起别名
例如需要导入base64
模块中的b64decode
函数
from base64 import b64decode
这个操作只会把b64decode
函数导入到程序中,并不会将base64
导入到程序。
如果想一次性导入模块中的所有方法,from 模块名 import *
语句
# 导入 base64 模块中的所有项目
from base64 import *
import
和from ... import
的区别就是,import导入的模块需要使用模块.函数
的方法调用,而from ... import
可以执行调用导入的函数。
搜索路径
我们导入模块的时候,Python会在本地计算机中寻找相关模块的路径,是有一定顺序的。
- 当前路径
- 如果不在当前路径,搜索
PYTHONPATH
下的每一个目录 - 如果都找不到,python会查看
默认路径
PYTHONPATH
就是python
默认安装目录
模块搜索路径存储在system
模块的sys.path
变量中。
一般默认路径为安装路径
在sys
,system模块中,path
变量存储着所有python
会查找的路径
使用print sys.path
查看搜索路径
import sys
print(sys.path)
返回
['F:\\python', 'F:\\python', 'C:\\Users\\Jackson\\AppData\\Local\\Programs\\Python\\Python39\\python39.zip', 'C:\\Users\\Jackson\\AppData\\Local\\Programs\\Python\\Python39\\DLLs', 'C:\\Users\\Jackson\\AppData\\Local\\Programs\\Python\\Python39\\lib', 'C:\\Users\\Jackson\\AppData\\Local\\Programs\\Python\\Python39', 'C:\\Users\\Jackson\\AppData\\Local\\Programs\\Python\\Python39\\lib\\site-packages']
保证导入模块不执行测试语句
在python
开发中,我们可以导入任何一个文件
,所以我们在开发时,建议写的每一个python
文件都可以被导入,在导入时,会自动执行一些没有缩进的代码,这并不是我们想要的,所以要对这种被导入时执行的代码,做我们需要做一些处理
__name__
属性
系统内置默认变量__name__
如果在当前文件默认值是__main__
,如果被其他文件当做为模块使用,返回的是__name__
所在的文件,可以用该值进行判断代码在执行的时候是被当做模块导入
还是在当前文件
定义aaa.py,内容为
if __name__ == '__main__':
print("这是一个aaa.py测试文件")
使用test.py
导入,并执行
import aaa
如果使用默认方法导入aaa.py
,会执行这是一个aaa.py测试文件
。
dir()
dir()
函数会返回模块中定义过的名字,例如函数
和变量
。
例如:
import sys
# 查看 dir 模块中定义的名字
print(dir(sys))
reload()
当一个模块被导入到程序中,import只会导入模块一次,如果这是模块加入的了新的内容,这是就需要使用reload()
函数重新加载模块。
格式:reload(模块名)
python中的包(package)
包是一个分层的文件目录结构,定义了一个由模块中字包
、字包下的字包
等组成的python应用环境。
包其实就是文件夹,但每个文件夹下必须有__init__.py
文件,该文件内容可以为空,但必须存在,它用于像python
标识当前文件夹是一个包。
例如,我们在test_packets
下创建packet1.py
、packet2.py
和必不可少的__init__.py
文件。
方法1
使用from 包名 import 包文件
,或者from 包名.包文件 import 包方法
可以导入到
packet1.py
def fun1():
print("There is packet1.py")
packet2.py
def fun2():
print("There is packet2.py")
__init__.py
这里可以为空
if __name__ == '__main__':
print('作为主程序运行')
else:
print('test_packets 初始化')
test.py
from test_packets.packet1 import fun1
from test_packets import packet2
# 不同的导入方法,使用不同的方法使用
fun1() # 返回 There is packet1.py
packet2.fun2() # 返回 There is packet2.py
运行结果
test_packets 初始化
There is packet1.py
There is packet2.py
方法2
使用import 包名
也可以导入包,但是导入后是不可以使用的,需要在包目录中__init__.py
文件中使用from . import 包文件
导入包文件
- 在
__init__.py
文件中导入包文件
- 在需要导入包的文件使用
import 包名
,导入包
send_mess.py
def send(mess):
print(mess)
__init__.py
from . import send_mess
test.py
import zt_test
zt_test.send_mess.send("hello")
上述中,包就是一个目录,名称为zt_test
,其中有两个文件send_mess.py
和__init__.py
。最后使用test.py
导入包。
python 输入输出
print()
输入就是我们最常用的print()
函数,它会将传入的值输入的页面中
print("结束了")
input()
输入,输入可以理解为获取键盘
输入的值,常用的函数为input()
函数
input()
获取的值是字符串
类型
name = input("请输入你的名称")
print("你的名字是",name)
文件基础操作
Python中提供了对文件读取、写入的常用方法
open()函数
如果想要打开一个文件,读取其中的内容,python需要使用open()
函数。
open()
函数返回的结果是一个file
对象。
函数格式:open(文件名[,对文件的操作方法,buffering])
常用的操作方法
方法 | 作用 |
---|---|
t | 文本模式,默认模式 |
r | 只读,文件必须存在 |
w | 只写,文件存在清空内容,文件不存在创建文件 |
a | 只写,文件存在追加内容,文件不存在创建文件 |
r+ | 读写,文件必须存在 |
w+ | 读写,文件存在清空内容,不存在创建文件 |
a+ | 读写,文件存在追加内容,不存在创建文件 |
ab | 使用二进制模式读取文件 |
wb | 使用二进制模式写入文件 |
实例:
# 对 test.txt 执行 r 读取操作
f = open("test.txt",'r')
# 使用 type() 函数查看返回变量 f 数据类型
print(type(f)) # <class '_io.TextIOWrapper'>
# 使用 file 对象内置方法 read() 读取变量 f 的内容
print(f.read())
file
对象常用的属性
属性 | 作用 |
---|---|
file.name |
文件的名称 |
file.mode |
打开文件的模式 |
file.closed |
文件被关闭返回true ,打开返回false |
f = open('test.txt','r')
# 文件名
print(f.name) # test.txt
# 模式
print(f.mode) # r
# 文件是否关闭
print(f.closed) # false
# 关闭文件
f.close()
print(f.closed) # true
close()方法
使用close()
方法会对缓冲区的数据进行刷新,并关闭改文件。
就是在进行写入
或追加
的操作后,需要使用close()
关闭打开的file
对象。
write()方法
write()
方法提供了写入打开文件的作用,python中的字符串可以是二进制
数据,并不完全是数字。看实例
# 对 test.txt 执行 写入 操作
f = open("test.txt",'w')
# 使用 write() 放发符 test.txt 进行写入
f.write("hellow-----world")
# 关闭打开的文件 test.txt
f.close()
# 再次对 test.txt 文件进行 读取 操作
b = open("test.txt","r")
# 读取 test.txt内容
print(b.read()) # 返回 hellow-----world
# 关闭打开的文件 test.txt
b.close()
read()方法
上述中我们也是用到了read()
方法,read()
可以读取file
对象中的字符串,类似的有readlines()
读取一行的数据
f = open('test.txt','r')
# 使用 readline() 读取 test.txt 第一行数据
print(f.readline()) # 返回 Junglezt
# 使用 read() 读取 test.txt 所有数据
print(f.read())
'''
返回
www.baidu.com
www.cnblgso.com/Junglezt
LQL
Admin123
其中值没有 Junglezt 的原因是,readline()方法在读取一行后,会将指针移动到下一行
'''
with open() as ...
在进行文件的写入
中,需要经典的三个步骤,open()函数打开文件
-> write()方法写入文件
-> close()方法关闭文件
,如下
# 打开文件
f = open('test.txt','w')
# 写入文件
f.write('xxxxxx')
# 关闭文件
f.close()
使用with open() as 变量名:
的方法可以让代码更简介,并且可以不使用close()方法
关闭文件,因为该方法会默认自动调用close()方法
。实例:
# 打开文件
with open('test.txt','r') as f:
# 读取文件
print(f.read())
这样可以避免读取文件是的一些错误。
文件指针
在使用read()
和readline()
时有提到过,read()
可有提供参数,参数的含义为读取多少字节。
read(8)
读取前文件前八个指针的数据,通常一个字节一个指针
f = open('test.txt','r')
# 文件指针往后移动 8 位
print(f.read(8))
此时如果再次读取test.txt
的文件内容,就会从指针8开始往后读取
tell()
方法可以获取文件的指针位置
f = open('test.txt','r')
# 文件指针往后移动 8 位
print(f.read(8))
print(f.tell()) # 返回 8
seek(开始,条件)
方法可以更改文件的指针,开始控制开始的指针,条件只能在开始
为0
时设置,条件为0
代表文件开始的位置,1
定位到当前指针,2
定位到结束指针
f = open('test.txt','r')
# 文件指针往后移动 8 位
print(f.read(8))
# 获取当前指针
print("当前指针是",f.tell()) # 返回 8
# 更改指针
f.seek(6)
print("当前指针是",f.tell()) # 返回 6
# 将指针更改为当前指针
f.seek(0,1)
print("当前指针是",f.tell()) # 返回 6
# 将指针更改为开始位置
f.seek(0,0)
print("当前指针是",f.tell()) # 返回 0
# 将指针更改为结束位置
f.seek(0,2)
print("当前指针是",f.tell()) # 返回 64
os
文件操作
如果要对文件进行重命名
和删除
的操作,python中提供了os
模块执行系统的操作命令。
os.rename(旧文件,新文件)
方法可以将文件重命名
os.remove(文件)
方法可以将文件删除
os.mkdir(新目录)
创建目录
os.chdir(目录)
切换目录
os.getcwd()
获取当前目录
os.rmdie(目录)
删除目录
os.path.exists(文件)
文件存在返回True,否则返回false
import os
# 将 test.txt 重命名为 aaa.txt
os.rename('test.txt', 'aaa.txt')
# 将 aaa.txt 文件删除
os.remove('aaa.txt')
# 创建 Junglezt 目录
os.mkdir('Junglezt')
# 获取当前目录
print(os.getcwd()) # F:\python
# 切换到 Junglezt 目录
os.chdir('Junglezt')
# 获取当前目录
print(os.getcwd()) # F:\python\Junglezt
print(os.path.exists('Junglezt'))
# 删除目录
os.rmdir('Junglezt')
'''
这里删除目录可能会报错,因为python解析型语言,只需要解释后交给内存和CPU处理
并不会顾及代码是否可以执行,
所以Python解释器会将所有的代码一行一行的交给处理器处理
删除文件时很快的,但是创建文件相对于较慢,
由于程序处理过快,在没有创建 Junglezt 目录的时候,就进行了删除
这里改进后的代码可以是,通过 if 语句判断 Junglezt 目录是否存在,然后进行删除
if os.path.exists('Junglezt'):
os.rmdir("Junglezt")
print("目录已经删除")
else:
print("没有找到 Junglezt 目录")
'''
python 异常处理
异常就是报错,在程序程序执行的时候遇到了错误,导致了报错、程序异常终止的事件发生
异常处理
在一个良好的程序中,不可能我们的程序报错、出现问题就不可以执行了,一些错误是可以避免的,python
提供了try: ... except:...
语句,用于捕捉异常。
try...except
语句会从try
语句块中判断语句中的错误,遇到异常交给except
捕获异常信息,并处理。
try except else
语法格式
try:
运行代码
except [异常类型]:
在try部分遇到异常,执行的代码
else:
没有发生异常执行的代码
语句逻辑很容易理解,首先执行try
语句代码块,后续如何执行取决于try
执行的代码是否异常。看具体实例:
try:
f = open('aaa.txt', 'r')
except:
print("没有找到文件,读取失败")
else:
print(f.read())
f.close()
当没有创建aaa.txt
的时候,try
语句异常,就会执行except
语句,输出没有找到文件,读取失败
,如果aaa.txt
存在就会输出aaa.txt
的内容。
这样做的好处就是没有报错提示信息,让代码逻辑更清晰,正确时执行的语句,异常是执行的语句。
默认情况下except
会捕获所有的异常,这并不是理想的状态,我们可以指定异常类型
,让except
捕获指定的异常类型
格式为:except 异常类型1,异常类型2,...
常见的异常
异常 | 原因 |
---|---|
SyntaxError |
python语法错误 |
TypeError |
类型错误,常见于不同数据类型的无效操作 |
NameError |
访问了一个未知的变量 |
ImportError |
无法导入模块,路径和名称的错误 |
IndentationError |
代码没有正确对齐,主要缩进错误 |
IndexError |
下标错误,超出序列范围 |
IOError |
输出输出异常,主要是无法打开文件 |
AttributeError |
访问的对象属性不存在 |
KeyError |
访问字典不存在的键 |
OverflowError |
数值运算超过最大限制 |
TabError |
Tab和空格用法的错误 |
ValueError |
无效的值,即使值得类型值正确的 |
ZeroDivisionError |
算数中的除数为0 |
这些都是基本上常见的,大概了解即可,详细可见菜鸟教程
其中有一个特殊用法Exception
,默认会捕捉所有异常。
try-finally 语句
try-finally
无论是否发生异常,都会执行最后的语句。
try:
a = 5
# 会输出 hello world,如果这里是except则不会执行
finally:
print('hello world')
获取异常信息
在except
语句后加入错误类型
然后as 变量名
即可获取错误信息
# 当用户输入的不是整数,输出报错信息,是整数打印数字退出循环
while True:
try:
num = int(input("请输入一个整数:"))
except ValueError as V:
print("出错了",V)
else:
print(num)
break
触发异常
我们可以使用raise 异常类型
自己触发异常
def loop(num):
if num < 5:
raise ValueError("num值不能小于5")
else:
print(num)
return
loop(1)
自定义错误
File "test.py", line 4, in loop
raise ValueError("num值不能小于5")
ValueError: num值不能小于5
进程已结束,退出代码1
OS模块
Python的os
模块提供了很对文件处理的方法,在上述中,我们对文件的处理简单使用了os
模块,这里我们了解os
模块中常用的方法
方法 | 作用 |
---|---|
os.getcwd |
获取当前工作路径 |
os.listdir(path) |
获取路径下所有的文件和目录组成的列表 |
os.walk(path) |
获取路径下文件和文件夹,并进行分类,并获取子目录的文件和文件夹,返回结果为元组(路径,目录,文件) ,可使用循环获取 |
os.path.exists(path) |
判断文件和文件夹是否存在,存在返回True ,不存在返回False |
os.mkdir(path) |
创建文件夹,如果文件夹存在创建会报错,建议配合os.path.exists 先检查文件夹是否存在 |
os.makedirs(path) |
递归创建文件夹 |
os.rmdir(path) |
删除文件夹,不过只能删除空文件夹 |
os.path.join(path,name) |
拼接路径,例如:os.path.join("F:/python","a.jpg") 返回: F:/python/a.jpg |
os.path.split(path) |
拆分路径,返回路径 和文件名 |
os.path.dirname(path) |
返回路径,类似split 的获取路径 |
os.path.basename(path) |
返回文件名,类似split 的获取文件名 |
os.path.isdir(path) |
判断是否为文件夹 |
os.path.isfile(path) |
判断是否为文件 |
os.path.sep |
返回当前系统路径分隔符 |
os.path.getsize(path) |
获取文件大小(字节) |
对文件处理是少不了路径
这个概念的,python
的路径有个以下几种表述方式
"F:/python" # 默认
r"F:\python" # 原生字符
"F:\\python" # \转义字符
使用实例:
import os
# 获取当前工作路径
path = os.getcwd()
print(path) # F:\python
# listdir() 获取指定目录下的所有文件
files = os.listdir('D:/upload')
print(files)
# ['.user.ini', '11.gif', '2.php', '23146.gif', 'a.py']
# walk() 获取指定目录下所有目录和文件,还有子目录中的目录和文件
for path,dirs,files in os.walk(r"D:\网络搭建"):
print(path)
print(dirs)
print(files)
print('\n')
# path.exists() 判断文件、目录是否存在
print(os.path.exists('D:/2.jpg')) # True
# 创建、删除文件夹
# os.mkdir('Junglezt')
# os.makedirs('aaa/bbb/ccc')
# os.rmdir('Junglezt') # 只能删除空文件夹
# 拼接路径
path = r"D:\test"
print(os.path.join(path,'a.jpg')) # D:\test\a.jpg
# 从完整路径获取 路径 文件名
path = r"C:\windows\system32\cmd.exe"
# os.path.split()
print(os.path.split(path)) # 返回元组 ('C:\\windows\\system32', 'cmd.exe')
# dirname() 单独获取路径
print(os.path.dirname(path)) # C:\windows\system32
# basename() 单独获取文件名
print(os.path.basename(path)) # cmd.exe
# isdir() 判断是否为目录
print(os.path.isdir('test')) # True
# isfile() 判断是否为文件
print(os.path.isfile('test.txt')) # True
# 获取系统路径分隔符
print(os.path.sep) # \
# 获取文件大小,字节单位
print(os.path.getsize('test.txt')) # 13
python面向对象
在python中,设计之初就是为了面向对象而设置,在python
中创建一个类
和对象
很容易。
什么是类?
当我们要做一些事情的时候,例如我们可以把有一些共同特征的对象
放入到一个类,所以在创建过程中,我们要先创建类,然后使用类
实例化一个对象
,也可以说是创建一个对象
,然后每个对象
有不同的属性
和方法
。
类
可以看为游戏中的英雄
,每个应用都是类似的,只是技能
和属性值
不相同,所以他们可以归到一个类,这是我们就可以创建一个类。
对象
可以看为英雄(类)
中的一个角色(对象)
,每个对象有不同的技能
和属性
。
在操作中,我们可以将类似的东西(对象)
归类到一个类中,这样在编写代码的时候思路更清晰,更有条理,每个对象拥有不同的功能和方法。
对象和类中含有属性和方法,可以理解为变量
和函数
。
基础语法
dir()函数
在python
中,对象无处不在,之前学习的变量、数据、函数
都是对象。
使用dir()
函数可以查看对象中的所有方法,利用好dir()
函数,就可以不用死记硬背很多的内置函数。
对象的内置方法,一般为__开头和__结束
定义类、创建对象
定义类
在一个类中定义多个方法,这样通过类创建的对象,就可以直接调用其中的方法
class 类名:
def 方法1(self,参数列表):
pass
def 方法2(self,参数列表):
pass
- 使用
class 类名:
就可以创建一个类 - 定义方法和之前定义函数一样,不同的是第一个值为
self
注:类名必须
大驼峰命名
创建对象
对象时根据类创建的,所以想要创建对象必须先创建类,然后将类实例化,就是创建对象,创建对象语法格式如下:
对象名 = 类名()
示例
# 创建猫类
class Cat:
"""这是一个猫类注释"""
# 定义 eat() 方法
def eat(self):
print("喜欢吃鱼")
# 定义 drink() 方法
def drink(self):
print("要喝水")
# 使用Cat类,创建jack对象
jack = Cat()
# 调用 eat()、drink() 方法
jack.eat()
jack.drink()
创建对象属性
使用对象名.属性 = 值
赋值运算符可以给对象
属性赋值。
如下案例,统计过Person
类创建了lql
对象,给lql
对象设置name
属性,起个名字
# 定义 Person 类
class Person:
pass
# 创建 lql 对象
lql = Person()
# 给 lql 对象设置 name 属性,值为 LQL
lql.name = "LQL"
# 输出 lql 对象 name 属性的值
print(lql.name)
self参数含义
删除在def 方法名(self)
创建类中方法的时候,其中第一个参数为self
,这是一个固定的格式,self
参数名并不固定,可以是其他的名称,但是其意义是一样的。
那个对象调用方法
,那个对象就是self
的引用;例如:tom
对象调用eat(self)
方法,eat(self)
方法中,self
就是tom
对象。
看实例:
# 定义 Cat 类
class Cat:
# 定义 eat 方法
def eat(self):
# 该方法会输出 self 值
print("小猫爱喝水",self)
# 创建 tom 对象
tom = Cat()
# 查看 tom 对象信息
print(tom)
# <__main__.Cat object at 0x0000027AFB9BE370>
# 调用 eat() 方法,可以看到输出的 self 的值就是 tom对象
tom.eat()
# 小猫爱喝水 <__main__.Cat object at 0x0000027AFB9BE370>
由此可以得到self
,哪个对象调用方法,self就是那个对象。
看以下案例
# 定义 Cat 类
class Cat:
# 定义 eat 方法
def eat(self):
# 输出 self 对象的 name 属性
print("%s爱喝水"%self.name)
# 创建 tom 对象
tom = Cat()
# 定义 tom 对象的 name 属性为 Tom
tom.name = "Tom"
# 调用 eat() 方法
tom.eat()
# Tom爱喝水
上述案例使用格式化字符串
的方法.
首先给tom
对象name
属性赋值,然后再调用eat()
方法的时候,self.name
就是tom.name
获取name
属性的值进行格式化字符串,得到返回结果Tom爱喝水
。
- 在日常开发中,不推荐对象的属性进行
外部
的属性增加,赋值。
初始化方法
- 当时用
类名()
这种方式穿件对象的时候,会自动进行一下操作:- 在内存中为对象分配空间,创建对象
- 为对象设置初始值,初始化方法
__init__
初始化方法
在对象
创建的完毕后进行调用,方法名称为__init__
,上述说到以__
开头和结束的是python对象内置方法
__init__
方法专用于创建一个对象时,拥有那些属性
查看实例:
class Test:
def __init__(self):
print("这是一段测试代码")
a = Test()
# 返回 这是一段测试代码
上述代码中,我们并没有手动调用__init__
方法,但是执行了__init__
方法中的语句,当然我们也可以手动调用。
可以看到__init__
方法中,默认也有self
参数,所以看下面代码
class Person:
def __init__(self):
self.name = "LQL"
zt = Person()
print(zt.name) # LQL
代码中我们并没有手动的创建name
属性的值,是__init__
方法自动调用,在对象
创建后默认添加的值,但是这里很明显有一个缺陷,我们创建的人的名称是zt
,结果赋name
的值是LQl
。
方法改造
- 在实际过程中,我们希望在创建对象的同时,可以自定义对象的初始值
- 把需要设置的属性值,定义为
__init__
的参数 - 在方法中使用
self.属性 = 形参
接收外部传入的参数 - 在创建对象时,使用
类名(形参1,形参2,...)
方式创建
- 把需要设置的属性值,定义为
# 创建 Person 类
class Person:
# 创建初始化方法
def __init__(self,name):
# 获取创建方法时的 name 值,使用upper()字符串内置方法将 name 值进行大写
# 并赋值给 self.name 值
self.name = name.upper()
# 创建 zt、lql 对象
zt = Person("zt")
lql = Person("lql")
# 输出 zt、lql 对象 name 属性
print(zt.name)
print(lql.name)
内置方法
__del__方法
__init__
方法可以在对象
创建后,进行操作,让我们的代码更加灵活。
如果我们想在对象销毁
时,进行一些操作,可以使用__del__
方法
- 销毁指的是
对象
在内存中消除时
__str__方法
- 默认情况下,创建一个对象后,使用
print()
函数输出对象的信息是对象属于的类,和对象在内存中的十六进制地址 - 使用
__str__
方法可以自定义print()
输出的信息,
需要注意的是,
__str__
必须有一个返回值,并且是字符串类型
class Cat:
def __init__(self,name):
self.name = name
def __str__(self):
"__str__方法可以定义 对象 的返回值"
return "这里%s对象"%self.name
zt = Cat('ZT')
print(zt)
tom = Cat('Tom')
print(tom)
练习1
小明爱跑步例子
- 小明体重
75.0
公斤 - 小明每次跑步会减肥
0.5
公斤 - 小明每次吃饭体重增加
1
公斤
首先需要分析,对象小明需要名称
、体重
属性。需要定义跑步
和吃饭
两个方法。
看实例:
class Person:
def __init__(self,name,weight):
self.name = name
self.weight = weight
self.count = 0
def run(self):
self.weight -= 0.5
self.count += 1
print("{}体重减少了0.5公斤,现在体重是{},已经跑步{}次".format(self.name,self.weight,self.count))
def eat(self):
self.weight += 1
print("{}体重增加了1公斤,现在体重是{}".format(self.name,self.weight),end='\n\n')
xm = Person("小明",75.0)
xm.run()
xm.eat()
在房子里添加家具
- 房子有户型、总面积、家具名称
- 家具有名称、占地面积
- 床(bed)占地
4
平米 - 衣柜(chest)占地
2
平米 - 餐桌(table)占地
1.5
平米
- 床(bed)占地
- 将家具添加到房子中
- 打印房子信息,要求输出:户型、总面积、剩余面积、家具名称
# 创建房子类
class Hourse:
def __init__(self,type,area):
self.hourse_type = type
self.hourse_area = area
self.area_free = self.hourse_area
self.jiaju_list = []
def add_jiaju(self,name,area):
if self.area_free < area:
print("当前屋子已经放不下这个家具了\n")
return
self.area_free -= area
self.jiaju_list.append(name)
def __str__(self):
return "户型:{}\n总面积:{} [剩余面积:{}]\n家具列表:{}".format(self.hourse_type,self.hourse_area,self.area_free,self.jiaju_list)
# 创建家具类
class Jiaju:
def __init__(self,name,area):
self.name = name
self.area = area
def __str__(self):
return "%s占地 %s平米"%(self.name,self.area)
# 创建家具对象
bed = Jiaju("床",20)
chest = Jiaju("衣柜",10)
table = Jiaju("餐桌",15)
# 创建房子对象
kehu1 = Hourse("二室一厅",80)
# 往房子里添加家具
kehu1.add_jiaju(bed.name,bed.area)
print(kehu1)
士兵开枪
- 士兵有名称、枪
- 士兵可以开火
- 枪能发射子弹和更换弹夹
首先需要定义士兵类
和枪类
,然后创建士兵和枪对象。设计思路,设计时先设计使用的物品,枪拥有名称和子弹数量两个属性,开火和换弹夹两个方法,士兵可以需要名称属性和枪属性,而枪属性取决于是否定义开火方法
。
例如不定义士兵的开火方法
class Gun:
def __init__(self,name):
self.name = name
self.count = 0
def add_count(self):
self.count = 40
print("子弹更换完成[40/40]")
def shoot(self):
if self.count < 1:
print("[%s] 没有子弹...[0/40]"%self.name)
return
self.count -= 1
print("[%s] tututu... [%d/40]"%(self.name,self.count))
def __str__(self):
return "[%s] 子弹:[%d/40]"%(self.name,self.count)
class Man:
def __init__(self,name):
self.name = name
self.gun = None
SCAR = Gun("FN SCAR")
soap = Man("索普")
soap.gun = SCAR
# 调用射击方法
soap.gun.shoot() # [FN SCAR] 没有子弹...[0/40]
# 调用换弹夹方法
soap.gun.add_count() # 子弹更换完成[40/40]
# 调用射击方法
soap.gun.shoot() # [FN SCAR] tututu... [39/40]
# 查看当前枪子弹
print(soap.gun) # [FN SCAR] 子弹:[39/40]
另一个方法需要在士兵类
中创建一个fire(self)
方法,判断士兵是否有枪,调用枪对象
开火方法。
私有属性、方法
在实际的开发中,对象的某些属性或方法只希望在内部被调用,不希望外部被访问到。
定义方法
在属性和方法的基础上,开头加上两个下划线。
- 格式:
__属性名、__方法名
私有属性并不是完全不可以访问,是可以访问的,但是最好不要访问,因为设置私有拥有其存在的意义。
访问格式:_类名__属性名、_类名__方法名
继承
类中的属性和方法可以继承给子类,创建子类语法格式:class 子类名(父类)
看案例:
# 创建 Animal 类
class Animal:
def eat(self):
print("吃")
# 创建 Cat 类
class Cat(Animal):
def dark(self):
print("喵喵叫")
# 使用 Cat 类创建 tom 对象
tom = Cat()
# 使用 tom 对象调用 eat()和dark() 方法
tom.eat()
tom.dark()
上述中,使用Cat
类创建出的tom
对象,在Cat
类中,并没有eat()
这个方法,但是调用是成功的,说明类中的属性和方法是可以继承的。
覆盖父类
覆盖父类(重写)的属性和方法,有时候父类定义一些的特征,子类是不希望拥有,可以在子类中进行定义,覆盖父类中定义的属性和方法。
直接在子类中进行赋值、创建语句就可以覆盖
扩展父类
扩展父类适用于在覆盖父类方法
的基础上,在子类覆盖了父类的属性和方法时,如果这时子类需要调用父类的属性和方法,就需要使用super()
对象,super()
对象可以在子类
中调用父类
的属性。
这就相当于在子类
对父类进行了一个扩展,使用格式:super().方法()
# 创建 Animal 类
class Animal:
def eat(self):
print("吃")
# 创建 Cat 类
class Cat(Animal):
def eat(self):
print("斯文的吃")
super().eat()
# 使用 Cat 类创建 tom 对象
tom = Cat()
# 使用 tom 对象调用 eat()和dark() 方法
tom.eat()
'''
斯文的吃
吃
'''
在python2
中,使用类名.方法名(self)
来调用,这个方法是不太好的,不推荐使用。
私有属性、方法的继承
私有属性和方法无法被子类继承的,私有方法只能在当前类中被调用,也不能在外部进行调用
多继承
一个子类可以拥有多个父对象,并且子类会继承每个父类的属性和方法
# 创建A类
class A:
def ZZZ(self):
print("ZZZ 方法")
# 创建B类
class B:
def TTT(self):
print("TTT 方法")
# 创建C类
class C(A,B):
pass
# 使用 C类 创建 one 对象
one = C()
# 调用继承来之A对象的ZZZ()方法
one.ZZZ() # ZZZ 方法
# 调用继承来之B对象的TTT()方法
one.TTT() # TTT 方法
但是这也也出现了多继承的一个问题,如果继承的类中有相同的方法名,或者属性名,那么,到底执行谁的属性和方法?
注意:在开发时,避免出现这种会让人困惑的操作,也就是避免重名
到底继承谁的,在继承的时候先继承的谁,就调用谁的方法,如上述C(A,B)
,A
和B
类中有相同的方法,由于先继承的A
所有A
的优先级比较高,就会调用A
类中的方法。
python中的 MRO
python
针对类提供了一些内置属性__mro__
,可以查看方法的搜索顺序。
所谓方法搜索顺序,就是在调用类中的方法时,python
会根据__mro__
值来决定调用哪个方法
类属性
在我们创建对象的时候,需要使用类进行创建,其中我们可以给创建的对象赋值属性,类也是可以创建属性的,只需要在类中,属性名 = 值
进行赋值即可
类也是一个对象,给类对象属性赋值,通常用于纪录与与这个类相关的特征
调用类属性和对象的方法一样,类名.类属性
class Tools:
# 定义类属性count,初始值为0
count = 0
# 定义初始化方法
def __init__(self,name):
# 获取name传参赋值给对象name属性
self.name = name
# 类属性 count 自增 1,也就是没创建一个对象,count +1
Tools.count += 1
# 创建三个对象
one = Tools("斧头")
two = Tools("剪刀")
three = Tools("弓箭")
# 输出 Tools 对象的 count 值
print(Tools.count)
属性获取机制
在创建类属性后,使用类创建的对象也可以访问类属性中的值,对象在获取属性时,如果自身没有,会找到自己的类,查看是否有该属性。
class A:
test = 1
one = A()
# 访问 test 属性
print(one.test)
但是不推荐使用对象来访问类属性,在开发中可能会产生一些混淆。
类方法
之前我们使用的方法def 方法名(self):
属于实例化方法
,是针对于对象
的方法,因为self
默认第一次传参需要是一个对象
类方法,就是针对于类对象
的方法。语法格式:
@classmethod
def 方法名(cls):
pass
-
@classmethod
修饰符用于告诉python
,下面的方法是一个类方法
-
类方法
的第一种参数是cls
,和self
类似cls
的意思为,哪一个类
调用的方法,cls
就是哪一个类- 也可以使用其他的名称,只是默认第一个参数含义是这样,可以修改名称
class A:
@classmethod
def test(cls):
print(cls)
A.test()
one = A()
one.test()
静态方法
静态方法和实例化方法、类方法
不同,可以理解为类
中的普通方法,没有任何特殊的参数,只需要在前一行传入@staticmethod
修饰符,然后下一行就可以定义静态方法
了
class A:
@staticmethod
def test():
print("这是一个静态方法")
# 类名调用
A.test()
# 对象调用
one = A()
one.test()
class Game:
top_source = 0
def __init__(self,name):
self.player_name = name
@staticmethod
def show_help():
print("提示: 种植植物,抵挡僵尸进攻")
@classmethod
def show_top_source(cls):
print("历史最高分为%d"%cls.top_source)
def start_game(self):
print("%s 已经开始了游戏"%self.player_name)
one = Game("Junglezt")
one.start_game()
单例设计模式
- 设计模式是一些开发前辈留下的开发思路,我们可以直接套用,不用再做掉头发的事情。
- 单例设计模式
- 让类创建的对象,在系统中只有一个唯一的实例
- 也就是每次执行
类名()
创建返回的对象,内存地址都是相同的 - 使用场景如:打印机、音乐播放器、回收站,虽然处理的东西很多,但只有一个处理对象
__new__方法
- 使用
类名()
创建对象的时候,python
首先会调用__new__
方法为对象分配空间 __new__
方法是一个由object
基类提供的内置静态方法,主要作用有两个:- 在内存中给对象分配地址
- 返回对象的引用
python
在获取了对象的引用
的后,会将引用
作为__init__
初始化方法的第一个参数
重写__new__
方法
上述我们说到,所有的对象的基类
都是object
,默认我们创建的对象都是继承object
的内置方法,我们可以手动重写__new__
方法,让我们知道知道在什么时候对象被分配的内存地址,但是重写__new__
需要固定的格式
- 因为
__new__
方法默认会返回对象的内存地址的引用
,所以我们在重写后,必须加上return super().__new__(cls)
,不然会返回一个空的对象
创建单例
上述说到,单例是通过类创建的对象,只要唯一一个实例
- 定义一个类属性,初始值为
None
,用于纪录单例对象的引用 - 重写
__new__
方法 - 如果类属性
is None
,调用父类方法分配对象内存地址,并使用类属性进行纪录对象引用 - 如果值不是
None
就返回类属性中记录的对象引用
这样就可以达到,所有的对象都引用的一个内存地址的需求,看代码实例:
# 创建 Musicplayer 类
class Musicplayer:
# 定义 instance 用来纪录创建对象分配的内存地址
instance = None
# 重写__new__方法
def __new__(cls, *args, **kwargs):
# 判断 instance 值是否为 None
if cls.instance is None:
# 如果为 None,分配动态地址给赋值给 instance 属性
cls.instance = super().__new__(cls)
# 如果不为 None,返回 instalce 的值引用内存地址
return cls.instance
# 测试 instance 的值是否为 None
print(Musicplayer.instance)
# 实例化 one 对象
one = Musicplayer()
# 验证 instance属性 的值和 one 对象为一个内存地址
print(Musicplayer.instance)
print(one)
# tow对象引用的内存地址也是一样的
two = Musicplayer()
print(two)
初始化动作只执行一次
在使用__init__
方法的时候,我们会多次调用其中的动作,每次创建对象都会触发,我们只想要在第一次创建的时候触发,如何实现。
- 于
__new__
创建单例类似,使用一个类属性存储是否执行过初始化方法,如果执行过,就不在执行其中的动作。
- 使用一个
类属性
纪录是否进行过初始化方法,值为False
- 使用
if
语句判断,如果值为False
,执行初始化方法 - 在执行初始化方法后,将
类属性
纪录值改为True
class A:
count = False
def __init__(self):
if A.count == False:
print("对象初始化")
A.count = True
one = A()
print(one)
two = A()
print(two)
返回结果
对象初始化
<__main__.A object at 0x000001BA872BF220>
<__main__.A object at 0x000001BA872BF1C0>
可以看出,输出了对象初始化
一次
发布模块
如果自己在再发中,创建了很好用的模块,可以分享给其他人。
python
中提供了setup
方法方便模块的共享。
使用from distutils.core import setup
即可导入
1.创建 setup.py
from distutils.core import setup
setup(name="zt_test", # 包名
version="1.0", # 版本
description="测试发布模块", # 描述
long_description="来自Junglezt的测试", # 长的描述
author="Junglezt", # 作者
author_email="353823806@qq.com", # 作者邮箱
url="www.cnblogs.com/Junglezt", # 主页地址
py_modules=["zt_test.send_mess",
"zt_test.resp_mess"] # 模块名
)
2.构建模块
python setup.py bulid
会在执行命令的当前目录生成一个bulid
目录,里面的目录为指定的包名
和包模块
3.生成压缩包
python setup.py sdist
将构建的模块打包为一个tar.gz
的压缩包
4.使用模块
首先将文件解压,使用命令
tar zxvf 压缩包名.tar.gz
解压后进入解压目录,其中有一个build
目录,就是包的模块库文件,还要一个PKG-INFO
是作者的描述,其中有一个setup.py
,进入命令行
python setpu.py install
安装模块,会提示模块安装的路径。如果要将模块删除,到执行目录下删除包名
的目录即可。
pip使用
因为中有很多强大的第三方模块,例如:Pygame
、Requests
、Scapy
、Ipython
这些模块都不是python
内置的函数,是由别人开发的模块,因为像上述使用setup.py install
的方式一个一个安装很慢,python
推出使用pip
进行快速的安装卸载模块,非常方便
使用php -V
可以查看php的版本
pip -V
使用php list
可以查看当前已经安装的模块
pip list
使用pip install 模块名
和pip uninstall 模块名
可以安装卸载模块
pip install requests
pip uninstall requests
使用pip install -r 文件名
可以逐行读取文件中的模块进行安装
pip install -r requirements.txt
设置清华源
pip默认下载从国外的网站下载速度很慢,可以参考清华源暂时使用清华开源的地址下载。
更新pip
python -m pip install --upgrade pip
# 使用清华源更新pip
python -m pip install -i https://pypi.tuna.tsinghua.edu.cn/simple --upgrade pip
临时使用清华源
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple 模块名
把清华源设置为默认源
pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple