python基础个人总结

1、Python的可变与不可变

  不可变类型:数字、字符、元组(一旦改变,变量所指向的地址发生变化)
    可变类型:列表、字典、集合(在地址块内部进行修改,变量指向的地址不发生变化)

2、装饰器:

def fun02(fun):
    weight = 100
    def fun03():
        if weight >= 100:
            print("穿件黑色衣服,不要紧身的")
            fun()
    return fun03
@fun02  #将下面的函数名当做参数传递到fun02函数
def fun001():
    print("fun001")
fun001()

3、匿名函数

sum = lambda a, b: a + b
print(sum(2, 3))

4、偏函数

def add(a,b,c):
    print(a,b,c)
    return a+b+c
plus=partial(add,8)
print(plus(9,10))

5、转为十进制

print(int("1010",base=2))//表示“1010” 2进制 转换为 十进制

6、回调函数

def clean01(times):
    print("打扫房间%d次"%times)

def clean02(times):
    print("扫地%d次" %times)

def clean_control(times,func):#控制器
    return func(times)

clean_control(3,clean02)

7、python"name"的使用

1. 如果模块是被导入,__name__的值为模块名字
2. 如果模块是被直接执行,__name__的值为’__main__’

8、运算符的重载(熟练)

同样的运算符执行不同数据之间的运算时,采用不同的计算方式
运算符的重载案例:

print(1+2)
print("1"+"2")

class Person(object):
 	def __init__(self,num):
      self.num = num
	#运算符重载
    def __add__(self, other):
        return Person(self.num+other.num)
    def __str__(self):
    return "num="+str(self.num)
    
per1 = Person(1)
per2 = Person(2)
print(per1+per2)#3  ====print(per1.add(per2))
print(per1.add(per2))
print(per1)
print(per2)

9、@property(get+set)

使用@property实现getter 和 setter方法的功能

property:可以让你对受限制访问的属性使用点语法

class Money:
    def __init__(self):
        self.__money = 0

    @property
    def money(self):
        return self.__money

    @money.setter
    def money(self, value):
        if isinstance(value, int):
            self.__money = value
        else:
            print("error....")
     
a = Money()
print(a.money)
a.money = 189
print(a.money)

10、限制动态给实例添加属性和方法

其中在空类中定义:slots=(“name”,“age”,“speak”)等时,在动态添加属性、方法时,定义的属性名、方法名要和上面限制一样才可添加,否则报

11、关于数据类型总结

序列:包含列表、元组、字符串

序列的主要特点:支持索引和切片

可变数据类型:列表、字典、集合

不可变数据类型:数字、字符串、元组

有序数据类型:字符串、列表、元组

无序数据类型:数字、字典、集合

#有序的数据类型,每增加一个数据,这个数据都会被排到最后

#无序的数据类型,增加一个数据,这个数据不一定会排在最后

12、正则符号以及函数

字符

字符      功能
.        匹配任意1个字符(除\n)
[]       匹配[]中列举的字符
\d       匹配数字(0~9)
\D       匹配非数字,即不是数字
\s       匹配空白   空格  tab
\S       匹配非空白
\w       匹配单词字符,a~z A~Z 0~9 _ 汉字
\W       匹配非单词字符

字符   功能
*      表示匹配前一个字符出现0次或者无限次,即可有可无
+      表示匹配前一个字符出现1次或者无限次,即至少一次
?     表示匹配前一个字符出现1次或则0次,
													即,要么一次,要么没有

{m}    表示匹配前一个字符出现m次
{m,}   表示前一个字符至少出现m次
{m,n}   表示匹配字符出现从m到n次

字符         功能
^        匹配字符串的开头
$        匹配字符串的结尾
\b      表示匹配一个单词的边界

字符        	功能
|       	匹配左右任意一个表达式
(ab)    	将括号中字符作为分组
\num     	引用分组num匹配到字符串

正则函数

re.match

尝试从字符串的起始位置匹配一个模式,如果不是起始位置匹配成功的话,match()就返回""()None。

re.search

匹配成功re.search方法返回一个匹配的对象,否则返回None。

re.match与re.search的区别
re.match只匹配字符串的开始,如果字符串开始不符合正则表达式,则匹配失败,函数返回None,而re.search匹配整个字符串,直到找到一个匹配。

import re
pattern = re.compile(r'\d+')                    
m = pattern.match('one12twothree34four') 
print(m)

re.compile

用于编译正则表达式,生成一个正则表达式( Pattern )对象,供 match() 和 search() 这两个函数使用。

re.findall (返回空列表)

在字符串中找到正则表达式所匹配的所有子串,并返回一个列表,如果没有找到匹配的,则返回空列表。

re.finditer(返回迭代器)

和 findall 类似,在字符串中找到正则表达式所匹配的所有子串,并把它们作为一个迭代器返回。 

re.split(可扩展)

 split 方法按照能够匹配的子串将字符串分割后返回列表, 

检索与替换(删除)

语法:
re.sub(pattern, repl, string, count=0, flags=0)
参数:
pattern : 正则中的模式字符串。
repl : 替换的字符串,也可为一个函数。
string : 要被查找替换的原始字符串。
count : 模式匹配后替换的最大次数,默认 0 表示替换所有的匹配

正则表达式对象

re.RegexObject

re.compile() 返回 RegexObject 对象。

re.MatchObject

group() 返回被 RE 匹配的字符串。

start() 返回匹配开始的位置

end() 返回匹配结束的位置

span() 返回一个元组包含匹配 (开始,结束) 的位置

字符串中必须含有每个()中的一个参数

import re
word="123_qwe_QQWE"
#********一下的为一行********
result=re.match(
    "(?=.*[a-zA-Z])(?=.*[0-9])"
    "(?=.*[_@\.!#%&])"
    "[a-zA-Z_0-9@\.!@#%&]{6,20}$"
    "",word).group()
#********以上的为一行********   
print(result)

一、注释

单行注释:  #(注释代码)
多行注释:  “”“(代码块)”“”    或   '''(代码块)'''

二、标识符

1 定义

标识符:字母/下划线/数字组成,数字不能开头
注意:大小写区分

2 命名规则:

1.见名知意:
    起一个有意义的名字,尽量做到一眼看上去就知道它的意思(提高代码可读性),例如:
    姓名:name 学生:student 年龄:age     
2.驼峰式命名:
	2.1 小驼峰命名法则:第一个单词的首字母小写,从第二个单词开始及后面的单词的首字母大写,
		例如:firstName  getArticleList
	2.2 大驼峰命名法则:每一个单词的首字母都要求大写:例如:
		例如:GetArticleList   
3.下划线连接法:
    在程序中使用”_“连接单词:例如: my_name last_name

3 关键字

1.定义:
   python一些具有特殊功能的标识符-----》关键字
  关键字,是python中已经使用过的标识符,所以不允许开发者自定义和关键字名字相同的标识符
['False', 'None', 'True', 'and', 'as', 'assert', 'async', 'await', 'break', 'class', 'continue', 'def', 'del', 'elif', 'else', 'except', 'finally', 'for', 'from', 'global', 'if', 'import', 'in', 'is', 'lambda', 'nonlocal', 'not', 'or', 'pass', 'raise', 'return', 'try', 'while', 'with', 'yield']

三、输出、输入

1 python中的输出

print('hello world')

2 格式化的输出

	在python语言里 只要看见%操作符 它就是格式化输出;
	常用格式化符号
	 格式符号           转换
		%d             有符号的十进制整数
		%s             通过字符串格式化
		%c             字符
		%u             无符号的十进制整数
		%o             八进制整数
		%x/X           十六进制整数
		%e/E           索引符号
		%f             浮点实数

3 输出实例

#代码===========================
    name = '张三'
    age = 18
    sex = '男'
    address = '安徽安庆'
    hobby = '敲代码'
    print('张三')
    print(name)
    print('%s'%name)
    print('%s%d%s%s%s'%(name,age,sex,address,hobby))
    print('%s\n%d\n%s\n%s\n%s'%(name,age,sex,address,hobby),end='')
#结果===========================
    张三
    张三
    张三
    张三18男安徽安庆敲代码
    张三
    18
    男
    安徽安庆
    敲代码

4 换行与不换行

print(参数的类型:字符串/整形,end='')
end = '' 起到一个取消换行的作用  阻止print()自动换行
print()直接输出是一个空格  换行
\n  换行

5 输入

使用函数input(),获取用户从键盘输入的数据
#输入 input()函数
height = input('请输入你的身高')
print(height)
"""
总结:
  input函数()里面放的是提示信息  获取用户键盘返还的信息
  input()返还的结果赋给一个变量
  input()获取键盘返回的值都当做字符串进行处理
"""
#获取变量的数据类型  type()获取变量的数据类型  格式:type(变量名)
print(type(height))

四、常量与变量

1 常量

注意:
     在定义常量的时候一般将常量的名字全部大写(行业规则)
	 PI = 3.1415926
  常量的特点:一旦定义,不能更改。
  		python没有任何机制保证常量不会被修改,没有提供定义常量的保留字。
   总结:实际常量的值是可以修改的 后面学习将常量锁定  常量实质还是变量 。 

2 变量

2.1 变量的分类

* 局部变量
* 成员变量(全局变量)

2.2 局部变量

#局部变量
def test1():
    a = 10
    b = 10
    
def test2():
    a = 10
    b = 20
    
# 以上函数中的变量----》局部变量

局部变量总结:

局部变量:
    就是在函数内部定义的变量
    不同的函数,可以定义相同名字的局部变量,各个变量之间不会发生干涉不会影响
    局部变量的作用:为了临时保存数据需要在函数中定义变量来进行保存

2.3 全局变量

#全局变量
定义:
   如果一个变量,既能在一个函数中使用,
 也能在另外一个函数中使用---》全局变量
"""
#定义一个全局变量
a = 100
def test3():
    print(a)
def test4():
    print(a)

test3()
test4()

2.4 全局和局部变量名字相同

"""
全局变量和局部变量名字相同的问题
"""
s = 100
def test5():
    s = 200
    print(s)   	#200
    s = 300
    print(s)	#300
    
def test6():
    print(s)	#100
test5()

2.5 修改全局变量

* global  关键字   修改全局变量
* 格式:global 需要修改变量名  
# 没有加global修饰的全局变量
num = 11
def num01():
    num = 12
    return num
print(num01())
print(num)
print("*" * 30)

# 在外部加global修饰的全局变量
global num001
num001 = 110
def num011():
    global num001
    num001 = 100
    return num001
print(num011())
print(num001)
print("*" * 30)

# 在函数内部加global修饰的全局变量
num002 = 110
def num012():
    global num002
    num002 = 100
    return num002
print(num012())
print(num002)
print("*" * 30)

再来一个案例

print("*" * 30)
wendu = 0
def get_wendu():
	# 想一下wendu=33不加注释的运行结果
    # wendu = 33
    global wendu
    wendu = 34

def print_wendu():
    print(wendu)

get_wendu()
print_wendu()

2.6 局部变量和全局变量的区别

1.在函数外面定义的变量称为:全局变量
2.全局变量能够在所有的函数中被访问
3.如果在函数中修改全局变量,那么需要使用global关键字进行声明,否则出错
4.如果出现同名的现象,先到局部找---》全局-----》报错,这个被称为:就近原则

他们的本质的区别:
     在于作用域

2.6.1 局部和全局变量区别案例
#案例:
def get_wendu():
    wendu = 33
    return wendu
def print_wendu(wendu):
    print(wendu)
    
result = get_wendu()
print_wendu(result)

wendu = 0
def get_wendu1():
    wendu = 34
    # global wendu
    wendu = 33
    
def print_wendu1():
    print(wendu)

2.6.2 可变类型的全局变量
  • 可变类型值: 列表 字典 集合
  • 不可变类型: 引用 元祖 数字 字符串
当不可变的数据类型作为全局变量: 需要用global声明,进行修改
当可变的数据类型作为全局变量:  不一定需要global声明

2.6.3 可变类型全局变量案例:

#案例:
test = []
def d():
    test.append(2)
    print(test)
d()

test1 = []
def e():
    test1 = [1,2]
    # global test1
    test1 = [3,4]
    # print(test1)
e()
print(test1)

test2 = [1,2]
def f(a):
    a += a
    print(a)

f(test2)
print(test2)

再来一个案例

# 没有加global修饰的全局变量--可变类型
list01 = [1, 2, 3, 4]
def list001():
    list01.append(5)
    return list01
print(list001())
print(list01)
print("*" * 30)

# 加global修饰的全局变量--可变类型
global list02
list02 = [6, 1, 2, 3, 4]
def list002():
    global list02
    list02.append(5)
    return list02
print(list002())
print(list02)

2.6.4 不可变类型全局变量案例:
#不可变
a = 1
def g():
    a = 2
    a += 1
    print(a)
    # global a
    a = 4
g()
print(a)

五、数据类型

数据类型(了解)

Number(数字)
String(字符串)
List(列表)
Tuple(元组)
Set(集合)
Dictionary(字典)
Python3 的六个标准数据类型中:
	  不可变数据(3 个):Number(数字)、String(字符串)、Tuple(元组);
      可变数据(3 个):List(列表)、Dictionary(字典)、Set(集合)。

1 Number数据类型

python3包含int float bool complex(复数) 
例如:14 + 5j 
python2里面还有一个long长整形
python3只有一个int整形  
type()函数可以获取变量的数据类型 
a,b,c,d = 10,3.15,True,10 + 4j 交互赋值方式

#连续赋值
num = num2 = num3 = 10

#单独赋值
a = 10
b = 3.15
c = True 
d = 10 + 4j

#isinstance(变量名称,预测的变量类型)获取变量的数据类型
s = 1234
print(isinstance(s,int))

"""
type()直接获取变量的数据类型 它不会认为子类和父类是相同的类型
isinstance() 预测一个是什么数据类型 它会认为子类和父类是相同数据类型
"""

#案例 整数/浮点/布尔/复数
#1.整数:我们可以定义任意数字整数 包含负整数 和数学里面写法一样
num1 = 10
num2 = 0  #0是特殊的整形
print(type(num1))
print(type(num2))

#2.浮点:带有小数点的数字
f = 3.15
f2 = 6.8
f3 = f + f2
print(type(f3))

#布尔类型 只有两个值 True和False
b = True
print(type(b))

#复数:由数字开头 后面包含字母
f = 10 + 4j
print(type(f))
print(f.real) #获取复数里面的实数
print(f.imag) #获取复数里面的虚数


#空值 在python里面使用None表示  None不能理解0
n = None
print(type(n))

1.1 常用的数据类型之间的转换

函数             说明
int(x)      将x转换为一个整数
float(x)    将x转换为一个浮点数
complex(real,[,imag])    创建一个复数
str(x)     将对象x转换为字符串
repr(x)     将对象x转换为表达式字符串 用的不多
tuple(x)    将序列转换为元祖
list(x)     将序列x转换为列表
chr(x)   将一个整数转换为一个字符
unichr(x)   将一个整数转换为unicode字符
ord(x)    将一个字符转换为整数
hex(x)    价格一个整数转换为一个十六进制的字符串

#定义一个字符串变量
str = '100'
print(type(str))
#将字符串转换为整形 int(变量名)
#str2 = int(str)
#print(type(str2))
#将字符串转换为浮点类型
#f = float(str)
#print(type(f))

#将字符串转换为列表
"""
list = list(str)
print(type(list))
print(list)
"""

#特殊的数字不能进行转换
"""
a = 'abc'
a = "12ddd"
b = int(a)
print(type(b))
"""

#必须是正整数或者负整数转换才有意义
print(int("+123"))
print(type(int("+123")))
print(int("-100"))
print(int("12 + 4")) #报错
print(int("20 - 5"))

1.2 int数据类型(掌握)

int表示长整型,Python只有这一种整数类型,包含正整数和负整数
    #
    a = 123
    b = -345
    接下来的写法和上面的写法作用相同
    a, b = 123, 345
    print(a + b)
    print(a - b)
    print(a * b)
    print(a / b)
    *
输出结果
    #
    -222
    468
    -42435
    -0.3565217391304348

1.3 float数据类型(掌握)

float表示小数,只有这一种小数类型,包含正小数和负小数
   #
   i = 11.1
   j = -22.2
   print(i + j)
   print(i - j)
   print(i * j)
   print(i / j)
输出结果
   #
   -11.1
   33.3
   -246.42
   -0.5

1.4 bool数据类型(掌握)

Python3中表示真或假的类型

  • Python3中bool类型只有两个值:True和False
  • python2中没有True和False,用0和1表示
  • True和False可以直接和数字运算
h = True
k = False 
print(h + k)
print(h + 1)
print(h - k)
print(h * k)
print(h / k)# 报错
输出结果
1
2
1
0
Traceback (most recent call last):
File "Demos/Demo_Key.py", line 42, in <module>
print(h / k)
ZeroDivisionError: division by zero

1.5 complex类型(掌握)

complex在Python中表示复数类型

这里的复数解释为常量和变量的组合

例如:k = 123+45j

123表示常量

45j表示变量
g = 123+45j
print(g)
print(g.real)
print(g.imag)
输出结果:
(123+45j)
123.0
45.0

1.6 常用的模块

1.6.1 math
作用:进行数值的运算 

import math
#求绝对值
a = -5
print(math.fabs(a))
print(abs(-10))

#如果想查看某个函数 里面的参数 包括返回值 按住键盘上面ctrl键 再把鼠标移动到方法上面

#求浮点数的四舍五入的值 round(变量名,保留小数的位数)
  print(round(3.5))
  print(round(12.59,1))
	但是到了python3.5的doc中,文档变成了"values are rounded to the closest multiple of 10 to the power minus ndigits; if two multiples are equally close, rounding is done toward the even choice." 如果距离两边一样远,会保留到偶数的一边。比如round(0.5)和round(-0.5)都会保留到0,而round(1.5)会保留到2。


#向上取整
print(math.ceil(3.1))

#向下取整
print(math.floor(3.9))

#取整数部分和小数部分mody()
print(math.modf(12.35))

#求平方根
x = 5
y = 2
print(math.pow(x,y))

1.6.2 random
随机数
1.直接查询API
2.直接调用dir

随机数使用的场景
 数学  打游戏 安全领域 
 
 import random
#print(dir(random))

#返还一个随机的0-1之间的随机数
print(random.random())

#choice()返回随机的一个元素
print(random.choice('abcdefg'))

#randrange()随机返回一个元素  做微信随机抢红包
print(random.randrange(1,10,2))
"""
randrange(start,stop,step)
start起始值
stop结束值
step步长
"""

#shuffle()可以随机打乱列表里面的元素值
list = [3,1,6,20,4,True,'abc']
print(list)
random.shuffle(list)
print(list)


2 字符串(String)

2.1 字符串的介绍

定义:
放在单引号 或者 双引号 里面的数字 字母 特殊字符 ----》字符串

2.2 python中字符串的格式

格式:
name = '123'
name2 = "abc"
name3 = "@#"

注意:字符串里面的值不可改

2.3 字符串的输出

#字符串的输出 print(变量名,end = '')函数 end取消换行
print('明天星期天')
str = '明天星期五'
print(str)

name = '张三' #声明了一个变量 变量的名称叫name 给它赋值张三
address = '上海'
print("我的姓名是:%s,我住在:%s"%(name,address))

2.4 字符串的输入

input()函数可以获取键盘输入的信息,返还的结果当做字符串处理,需要报存到一个变量里面
#字符串的输入 input()函数
username = input('请输入你的用户名:')
password = input('请输入你的密码:')
if username == 'lishi' and password == '289001':
    print('欢迎你%s回来'%username)
else:
    print('用户名或者密码错误')

2.5字符串常用函数

2.5.1 下标和切片(重点)
2.5.1.2 下标
定义:
	下标 ---- >编号
生活中的场景:
	做火车--->找座位号

定义一个字符串变量
name = 'zhangsan'
格式:	print(name[0])

#下标
names = 'wangwu'
"""
print(names[0])
print(names[1])
print(names[2])
print(names[3])
print(names[4])
print(names[5])
"""

#使用for循环获取
for temp in names:
    print(temp)	
2.5.1.2 切片(重点)
定义:
	截取变量里面的部分元素值---->切片
格式:[开始:结束:步长]

name = 'hello world'
print(name[0::])  #如果起始值是0 表示从头截取到尾部
print(name[3::])  #从起始值3开始 截取后面所有字符
print(name[:2:])
#从后往前截取 最后一个元素-1
print(name[::-2]) #如果步长负值 代表从后往前截取
print(name[:-1:])  
2.5.2 字符串中常见的运算
#1.字符串相加
str = 'hello '
str2 = 'world'
str3 = str + str2  #字符串里面+是拼接
print(str3)

#2.输出5个world
print(str2 * 5)

#3.字符串里面替换  注意:String值不能修改
"""
name = 'abc'
name[0] = 'c'
print(name)
"""
name = 'hello world'
print(name[0::])  #如果起始值是0 表示从头截取到尾部
print(name[3::])  #从起始值3开始 截取后面所有字符
print(name[:2:])
#从后往前截取 最后一个元素-1
print(name[::-2]) #如果步长负值 代表从后往前截取
print(name[:-1:])

2.5.3 字符串里面转义字符
#1.换行 \n
print('hello \nworld')

#2.使用\\对\进行转义
print("hello\\world")

#3.\'
print("hello\'world")

#4.\"
print("hello\"world")

#5.\t 制表符
print('hello\tworld')

#6.如果转义的字符非常多 可以使用r
print(r"ddddd\tdddk\'kkkkkkk\kkkkk\"kkgdfdffdf")
2.5.4 替换字符串
print(name.replace("a", "w", 1))
2.5.5 把首字母大写
print(name.capitalize())
2.5.6 all单词的首字母大写
print(name.title())
2.5.7 大小写转换
print(name.swapcase())
2.5.8 判断开头或者结尾字符
print(name.startswith("xiao"))
print(name.endswith("xiao"))
num = ord("a")
word = chr(num - 32)
print(word)
2.5.9 左侧对齐
==width表示这个元素的总宽度,如果字符长度不够用空格补齐==
word = "abcdefg"
print(word.ljust(20))
print(word.ljust(20), "*")
2.5.10 右侧对齐
==width表示这个元素的总宽度,如果字符长度不够用空格补齐==
print(word.rjust(20))
print(word.rjust(20), "*")
2.5.11 居中显示
==width表示这个元素的总宽度,如果字符长度不够用空格补齐==
print(word.center(20))
print(word.center(20), "*")
2.5.12 fill()右对齐,左补0
print(word.zfill(20))
2.5.13 strip() 去除空格
word = "   word  wordw  "
print(word.strip())
print(word.strip().strip("w"))
2.5.14 rfind从右侧开始查找
aaa.aaa.aaa.txt
print(word.rfind("w"))
print(word.rfind("w", 14, 20))
2.5.15 转义字符
print("hello01", end="\t")
print("hello02", end="\n")
print("hello03", end="\r")
print("hello04", end="\r\n")
print("hello05", end="\r")
print("hello06", end="\r")
输出结果:
#
hello01	hello02
hello04
hello06

3 列表List(掌握)

3.1 列表的定义

列表介绍:
​ 序列是Python中最基本的数据结构。
​ 序列中的每个元素都分配一个数字 - 它的位置,或索引,第一个索引是0,第二个索引是1,依此类推。
​ 列表是常用的Python数据类型,它可以作为一个方括号内的逗号分隔值出现。
​ 列表可以进行的操作包括索引,切片,加,乘,检查成员。
此外,Python已经内置确定列表的长度以及确定最大和最小的元素的方法。
​ 列表的数据项不需要具有相同的类型

列表格式:

列表名 = [列表选项1,列表选项2,…,列表选项n],

3.2、创建列表

list1 = [1, 2, 3, 4, 5]
list2 = ["a", "b", "c", "d"]
list3 = [True, False]
list4 = ["a", 1, True, None]
list5 = []

3.3 控制台运行输出列表

代码:
  	print(list1)
    print(list2)
    print(list3)
    print(list4)
    print(list5)
    print(type(list4))
    print(type(list5))
运行输出结果:
    #
    [1, 2, 3, 4, 5]
    ['a', 'b', 'c', 'd']
    [True, False]
    ['a', 1, True, None]
    []
    <class 'list'>
    <class 'list'>
    #

想一想:list6 = [None],print(list6)在控制台运行输出的是什么结果

3.4 运行输出列表(掌握)

3.4.1 调用print()函数直接打印
#
创建列表
    list1 = [1, 2, 3, 4, 5]
    list2 = ["a", "b", "c", "d"]
运行输出列表
    print(list1)
    print(list2)
运行输出结果
    [1, 2, 3, 4, 5]
    ['a', 'b', 'c', 'd']
3.4.2 下标运行输出列表中元素
创建列表
	list1 = ["a", "b", "c", "d"]
运行输出列表
    print(list1[0])
    print(list1[1])
    print(list1[2])
	print(list1[3])
运行输出结果:
    #
    a
    b
    c
    d
3.4.3 for循环输出列表元素
使用for循环
    namesList = ['xiaoWang', 'xiaoZhang', 'xiaoHua']
    for name in namesList:
        print(name)
运行输出结果:
    xiaoWang
    xiaoZhang
    xiaoHua
3.4.4 while循环输出列表元素
#使用while循环
    namesList = ['xiaoWang', 'xiaoZhang', 'xiaoHua']
    length = len(namesList)
    i = 0
    while i < length:
        print(namesList[i])
        i += 1
运行输出结果:
    xiaoWang
    xiaoZhang
    xiaoHua
3.4.5 列表重复运行输出
    namesList = ['xiaoWang', 'xiaoZhang', 'xiaoHua']
    print(namesList * 2)
运行输出结果:
	['xiaoWang', 'xiaoZhang', 'xiaoHua', 'xiaoWang', 'xiaoZhang', 'xiaoHua']

3.5 列表常用操作(掌握)

我们对数据常用的操作一般可以总结为:增、删、改、查,下面我们来学习关于列表的常用操作

3.5.1 访问列表元素
    namesList = ['xiaoWang', 'xiaoZhang', 'xiaoHua']
    print(namesList[0])
    print(namesList[1])
    print(namesList[2])
运行输出结果:
    xiaoHua
    xiaoZhang
    xiaoHua
想一想:print(namesList[3])在控制台运行输出的结果是什么
3.5.2 更改
代码:
    namesList = ['xiaoWang', 'xiaoZhang', 'xiaoHua']
    print("更改前的nameList:%s" % namesList)
    namesList[0] = "小王"
    print("更改后的nameList:%s" % namesList)
运行输出结果:
    更改前的nameList:['xiaoWang', 'xiaoZhang', 'xiaoHua']
    更改后的nameList:['小王', 'xiaoZhang', 'xiaoHua']
3.5.3 增加
3.5.3.1 增加append(追加)

通过append可以向列表中添加元素,添加的元素放在最后

    namesList = ['xiaoWang', 'xiaoZhang', 'xiaoHua']
    print("添加元素前的nameList:%s" % namesList)
    namesList.append("xiaoMing")
    print("添加元素后的nameList:%s" % namesList)
运行输出结果:
    添加元素前的nameList:['xiaoWang', 'xiaoZhang', 'xiaoHua']
    添加元素后的nameList:['xiaoWang', 'xiaoZhang', 'xiaoHua', '小明']
3.5.3.2 增加列表元素insert

通过insert可以向列表指定位置添加元素

列表增加元素–insert(index, object)

    namesList = ['xiaoWang', 'xiaoZhang', 'xiaoHua']
    print("添加元素前的nameList:%s" % namesList)
    namesList.insert(1, "小明")
    print("添加元素后的nameList:%s" % namesList)
运行输出结果:
    添加元素前的nameList:['xiaoWang', 'xiaoZhang', 'xiaoHua']
    添加元素后的nameList:['xiaoWang', '小明', 'xiaoZhang', 'xiaoHua']
3.5.3.3 增加列表元素extends

列表增加元素–extend(list)

    namesList1 = ['xiaoWang', 'xiaoZhang', 'xiaoHua']
    namesList2 = ['小王', '小张', '小华']
    print("添加元素后的nameList:%s" % namesList1)
    namesList1.extend(namesList2)
    print("添加元素后的nameList:%s" % namesList1)
运行输出结果:
    添加元素后的nameList:['xiaoWang', 'xiaoZhang', 'xiaoHua']
    添加元素后的nameList:['xiaoWang', 'xiaoZhang', 'xiaoHua', '小王', '小张', '小华']
3.5.3.4 列表相加
namesList1 = ['xiaoWang', 'xiaoZhang', 'xiaoHua']
namesList2 = ['小王', '小张', '小华']
namesList3 = namesList1 + namesList2
print(namesList3)
运行输出结果:
#
['xiaoWang', 'xiaoZhang', 'xiaoHua', '小王', '小张', '小华']
3.5.4 查找

(in, not in, index, count)

in(存在):如果存在返回的结果为True,反之False
not in(不存在):如果不存在结果为True,反之False
index(str, start, end)查找元素第一次出现的下标
count(str)查找元素个数目
3.5.4.1 查找列表元素
代码:
	namesList1 = ['xiaoWang', 'xiaoZhang', 'xiaoHua']//获取用户要查找的名字
    findName = input("请输入需要查找的名字:")//查找判断,是否存在
    if findName in namesList1:
        print("找到有这个人...")
    elif findName not in namesList1:
        print("查无此人....")
运行输出结果:
    请输入需要查找的名字:aaa
    查无此人....
    请输入需要查找的名字:xiaoHua
    找到有这个人...
    
index()案例:index /count
    a = ["a", "b", "c", "b", "d", "a"]
    print(a.index("b"))
    print(a.index("b", 2, 5))
    print(a.count("a"))
运行输出结果:
    1
    3
    2
想一想:print(a.index("e"))和print(a.count("e"))运行输出什么结果
3.5.5 删除元素

(del/pop/remove)

  • del list[index] 删除指定位置的元素
  • pop(index) 删除一个元素,把删除的这个元素返回,index不写时默认是最后一个
  • remove(onject)
3.5.5.1 del案例:
# 删除元素(del list[index])
    word = ["a", "b", "c", "b", "d", "a"]
    print("删除元素前的word:%s" % word)
    del word[1]
    print("删除元素后的word:%s" % word)
#运行输出结果:
    删除元素前的word:['a', 'b', 'c', 'b', 'd', 'a']
    删除元素后的word:['a', 'c', 'b', 'd', 'a']
3.5.5.2 pop()案例:
# 删除元素(pop(index))
    word = ["a", "b", "c", "b", "d", "e"]
    print("删除指定位置元素", word.pop(1))
    print("删除默认位置元素", word.pop())
#运行输出结果:
    删除指定位置元素 b
    删除默认位置元素 e
3.5.5.3 remove()案例:
# 删除元素(remove(object))
    word = ["a", "b", "c", "b", "d", "e"]
    print("删除元素前的word:%s" % word)
    word.remove("a")
    print("删除元素后的word:%s" % word)
    word.remove("a")
3.5.6:列表排序sort()
列表排序sort(reverse=False):
    word = ["a", "b", "c", "b", "d", "e"]
    print("排序前的word:%s" % word)
    word.sort(reverse=False)
    print("顺序排序后的word:%s" % word)
    word.sort(reverse=True)
    print("逆序排序后的word:%s" % word)
运行输出结果:
    排序前的word:['a', 'b', 'c', 'b', 'd', 'e']
    顺序排序后的word:['a', 'b', 'b', 'c', 'd', 'e']
    逆序排序后的word:['e', 'd', 'c', 'b', 'b', 'a']
3.5.7 列表的嵌套

类似while、for循环的嵌套,列表也支持嵌套

一个列表中的列表作为一个元素

格式:列表名 = [ [ ], [ ], [ ] ]
例如:schoolNames = [["清华大学","北京大学"],["哈尔滨佛学院"],[]]
    namesList = [["赵毅", "钱尔", "孙三"], ["里斯", "周武"], ["吴柳", "郑琦"]]
    for cls in namesList:
        print(cls, end=",")
    print()
运行输出结果:
    赵毅,钱尔,孙三,
    里斯,周武,
    吴柳,郑琦,
3.5.8 获取最大值、最小值
word = ["a", "b", "c", "b", "d", "e"]
print(max(word))
print(min(word))
运行输出结果:
a
e

4 元组tuple(熟练)

4.1 元组定义

-  元组概述
   -  python的元组和列表类似,不同之处在于元组的元素不能修改,
-  元组格式:
   -  元组名 = (元组元素1,元组元素2.....元组元素n)

4.2 创建元组

 代码:
  	tuple1 = ()
    tuple2 = (1, 2, 3)
    tuple3 = (1, 2, 3, "hello", True)
    print(tuple1)
    print(tuple2)
    print(tuple3)
    print(type(tuple1))
    print(type(tuple2))
    print(type(tuple3))
运行输出结果:
    (1, 2, 3)
    (1, 2, 3, 'hello', True)
    <class 'tuple'>
    <class 'tuple'>
    做一做:tuple0 = (1),print(type(tuple0))运行输出结果是什么

4.3 访问元组

tuple4 = (1, 2, 3, "hello", True)
print(tuple4[2])
print(tuple4[3])
运行输出结果:
#
3
hello

4.4 遍历元组

tuple5 = (1, 2, 3, "hello", True)
for t in tuple5:
    print(t)
运行输出结果:
#
1
2
3
hello
True

4.5 重复运行输出元组

#
tuple1 = (1,2,3)
print(tuple1 * 3)
运行输出结果:
#
(1, 2, 3, 1, 2, 3, 1, 2, 3)

4.6 元组常用操作

4.6.1 修改

==元组内一旦创建,不可更改,==可修改的是元组内的可变类型例如:数组

tuple5 = (1, 2, 3, 4, True, [5, 6, 7])
# tuple5[0] = 100		#报错,元组不能修改
# tuple5[-1] = [7,8,9]	#报错,
tuple5[5][0] = 500
print(tuple5)

运行输出结果

(1, 2, 3, 4, True, [500, 6, 7])
4.6.2 删除元组

del可以删除元组,但是后果很严重。。。

#
    tuple6 = (1, 2, 3)
    del tuple6
    print(tuple6)
运行输出结果:
    Traceback (most recent call last):
    File "/Day06/Tuple_Demo01.py", line 61, in <module>
      print(tuple6)
    NameError: name 'tuple6' is not defined

* 试一试:del tuple6[1]运行输出什么结果
4.6.3 元组相加
    tuple1 = (1, 2, 3)
    tuple2 = (4, 5, 6)
    tuple3 = tuple1 + tuple2
    print(tuple3)
    print(type(tuple3))
    print(tuple1)
    print(tuple2)
运行输出结果:
#
    (1, 2, 3, 4, 5, 6)
    <class 'tuple'>
    (1, 2, 3)
    (4, 5, 6)


4.6.4 判断是否存在X 元素

使用in,not in可以判断某个元素是否在目标元组

    tuple4 = (1, 2, 3)
    print(3 in tuple4)
    print(3 not in tuple4)
运行输出结果:
    True
    False

4.6.5 截取元组内容

格式: 元组名[开始 : 结束 :步长](含头不含尾)

案例:

    tuple6 = (1, 2, 3, 4, 5, 6, 7, 8)
    print(tuple6[:])
    print(tuple6[3:7])
    print(tuple6[3:])
    print(tuple6[:7])
    print(tuple6[:-1])
    print(tuple6[-1::-1])
运行输出结果:
#
    (1, 2, 3, 4, 5, 6, 7, 8)
    (4, 5, 6, 7)
    (4, 5, 6, 7, 8)
    (1, 2, 3, 4, 5, 6, 7)
    (1, 2, 3, 4, 5, 6, 7)
    (8, 7, 6, 5, 4, 3, 2, 1)

4.6.6 元组嵌套

元组的嵌套(二维元组),元素是一维元组

格式:元组名 = ((),(),()…)

案例:

    tuple7 = ((1, 2, 3), (4, 5, 6), (True, False))
    print(tuple71)
    for tuple0 in tuple7:
        for num in tuple0:
            print(num, end=",")
        print()  
运行输出结果:
    #
    5
    1,2,3,
    4,5,6,
    True,False,

5 字典dict(熟悉)

5.1 字典定义

字典格式
	格式:{key1 : value1, key2 : value2, key3 : value3, ....}
创建字典
	定义一个变量info为字典类型
	info = {"name" : "zhangsan", "id" : 1234, "address" : "北京"}

5.2 字典常用操作(掌握)

5.2.1 增加字典内容
变量名["键"] = 数据时,如果该键在字典中不存在,会自动创建
    info = {"id": 100, "address": "北京", "name": "zhangsan"}
    print("添加元素前的字典info:", info)
    info["phoneNum"] = 10086
    print("添加元素后的字典info:", info)
运行输出结果:
#
    添加元素前的字典info: {'id': 100, 'address': '北京', 'name': 'zhangsan'}
    添加元素后的字典info: {'id': 100, 'address': '北京', 'name': 'zhangsan', 'phoneNum': 10086}

5.2.2 修改字典内容
==变量名["键"] = 数据时,如果该键在字典中存在,会改变原值==

==变量名["键"] = 数据时,如果该键在字典中不存在,会自动创建==
    info = {"id": 100, "address": "北京", "name": "zhangsan"}
    print("修改前的字典info:", info)
    newAddr = input("请输入您所在的城市:")
    info["address"] = newAddr
    newAge = int(input("请输入您的年龄:"))
    info["age"] = newAge
    print("修改后的字典info:", info)
运行输出结果:
#
    修改前的字典info: {'id': 100, 'address': '北京', 'name': 'zhangsan'}
    请输入您所在的城市:上海
    请输入您的年龄:18
    修改后的字典info: {'id': 100, 'address': '上海', 'name': 'zhangsan', 'age': 18}

5.2.3 删除字典元素

del :删除指定的元素

clear():清空字典

案例:
del案例:

    info = {"id": 100, "address": "北京", "name": "zhangsan"}
    print("删除元素前的字典info:", info)
    del info["address"]
    print("删除元素后的字典info:", info)
运行输出结果:
#
    删除元素前的字典info: {'id': 100, 'address': '北京', 'name': 'zhangsan'}
    删除元素后的字典info: {'id': 100, 'name': 'zhangsan'}

clear()案例:

    # clear()
    print("clear()前的字典info:", info)
    info.clear()
    print("clear()后的字典info:", info)
运行输出结果:
#
    clear()前的字典info: {'id': 100, 'name': 'zhangsan'}
    clear()后的字典info: {}

5.2.4 查看字典元素

get()函数:在我们不确定字典中是否存在某一个键而又想获取它的值,可以使用get(),可以设置默认值

案例:

    info = {"id": 100, "address": "北京", "name": "zhangsan"}
    age = info.get("age")  # age键不存在,所以age的值为None
    print(age)
    age = info.get("age", 18)
    print(age)
运行输出结果:
#
    None
    18

5.3 字典常用函数(掌握)

info = {"id": 100, "address": "北京", "name": "zhangsan"}
-  字典长度-  len(dict)
	len0 = len(info)
	print("字典info的长度是:", len0)
	
	字典info的长度是: 3

-  获取所有的键key--dict.keys()
	keys = info.keys()
	print("字典info的键集合是:", keys)
	
	字典info的键集合是: dict_keys(['id', 'address', 'name'])
	
-  获取所有的值value-  dict.values() 
    values = info.values()
    print("字典info的值集合是:", values)
    
    字典info的值集合是: dict_values([100, '北京', 'zhangsan'])

-  获取所有的键值对-  dict.items()
	items = info.items()
	print("字典info的键值对集合是:", items)
	
	字典info的键值对集合是: dict_items([('id', 100), ('address', '北京'), ('name', 'zhangsan')])

4、遍历字典 - 使用for循环可以搞定

# 字典的遍历
# 遍历字典中的key
info = {"id": "100", "address": "北京", "name": "zhangsan"}
print("--------遍历字典中的key--------")
b = info.keys()
print(type(b))
for key in b:
    print(key, end=",")

print("\n--------遍历字典中的value--------")
# 遍历字典获取字典中所有的值
c = info.values()
for value in c:
    print(value, end=",")

print("\n--------遍历字典中的键值对--------")
# 获取键值对
itmes = info.items()
for itme in itmes:
    print(itme)
print("\n--------遍历字典中的键值对改良版--------")
# 改进
for key, value in itmes:
    print("key = %s,value = %s" % (key, value))

运行输出结果:

--------字典的遍历--------
--------遍历字典中的key--------
<class 'dict_keys'>
id,address,name,
--------遍历字典中的value--------
100,北京,zhangsan,
--------遍历字典中的键值对--------
('id', '100')
('address', '北京')
('name', 'zhangsan')
key = id,value = 100
key = address,value = 北京
key = name,value = zhangsan


案例:

chars = ['a', 'b', 'c', 'd']
i = 0
for chr in chars:
     print("%d %s"%(i, chr))
     i += 1
运行输出结果:
0 a
1 b
2 c
3 d

第二种方式:使用enumerate()解决

print("第二种方式:")
for i, c in enumerate(chars):
    print(i, c)
运行输出结果:
0 a
1 b
2 c
3 d

5.4 字典和列表优缺点比较

集合与之前的列表和元组类似,可以存储多个类型数据,这些数据不能重复

  • 理解
    • 相对于字典,是一组key,没有value
  • 本质:
    • 无序,无重复元素元素的集合
    • 集合的对象支持union(联合),intersection(交),difference(差),system-difference(系统差集)等运算
  • 特点:
    • 不能存储重复元素

6 集合set(熟练)

6.1 创建集合:

  • 集合的创建 ,需要列表、元组、字典等可迭代类型作为元素输入集合
  • 重复的元素在集合中会被自动过滤掉
  • set = {},print(type(set))运行得到的结果不是集合
  • set = set()

创建集合案例:

    set01 = set([1, 6, 9, 3, 6])
    set02 = set({"id": "100", "address": "北京", "name": "zhangsan"})
    set03 = {}		# 创建的不是集合,是字典
    set04 = set("abcde")
    print(set01)
    print(set02)
    print(set03)
    print(set04)
    print(type(set03))
    print(type(set04))
运行输出结果:
#
    {1, 3, 6, 9}
    {'name', 'id', 'address'}
    {}
    {'e', 'a', 'c', 'd', 'b'}
    <class 'dict'>
    <class 'set'>

6.2 集合的常用操作(掌握)

6.2.1 向集合添加元素
  • 集合添加元素使用add()
  • 格式:set.add(obj)

集合添加数据案例:

# 集合添加元素
print("---------add---------")
# 添加add
s1 = set([1, 2, 3, 4, 5])
s1.add(6)
print(s1)
s1.add(3)  # 添加重复的元素,没有效果
print(s1)
运行输出结果:
#
    ---------add---------
    {1, 2, 3, 4, 5, 6}
    {1, 2, 3, 4, 5, 6}    

读一下代码,说出运行结果:

s1.add([7, 8, 9])  		# set的元素不能是列表,列表是可变的
print(s1)
s1.add({1: "haha"})  	# set的元素不能是字典,字典也是可变的
print(s1)
s1.add(7, 8, 9)  		# set的元素不能连续添加
print(s1)
s1.add((7, 8, 9))  		# set的元素可以是字典,字典也是不可变的
print(s1)


6.2.2 集合更新update()
  • 插入(更新)update()
  • 可以插入list/tuple/String打碎插入(无序,去重)

update()案例:

    # 插入(更新)update()
    # 可以插入list/tuple/String打碎插入(无序,去重)
    print("----------Update()----------")
    s2 = set([1, 2, 3])
    s2.update([4, 5, 6])
    print(s2)
    s2.update((9, 10))
    print(s2)
    s2.update("haha")
    print(s2)
    s2.update("哈哈")
    print(s2)
运行输出结果:
#
    ----------Update()----------
    {1, 2, 3, 4, 5, 6}
    {1, 2, 3, 4, 5, 6, 9, 10}
    {'h', 1, 2, 3, 4, 5, 6, 9, 10, 'a'}
    {'h', 1, 2, 3, 4, 5, 6, 9, 10, '哈', 'a'}

6.2.3 删除集合元素
删除集合元素使用remove(object)

删除元素案例:

# 删除集合元素
    print("------remove------")
    # 删除remove()
    s3 = set([1, 2, 3, 4, 5])
    s3.remove(4)  # 删除是具体的元素
    print(s3)
    s3.remove(9)  # 这个元素是不存在的
    print(s3)
运行输出结果:
    ------remove------
    {1, 2, 3, 4, 5}
    {1, 2, 3, 5---}


删除不存在元素:

# 删除集合元素
    print("------remove------")
    # 删除remove()
    s3 = set([1, 2, 3, 4, 5])
    s3.remove(9)  # 这个元素是不存在的
    print(s3)
运行输出结果:
    Traceback (most recent call last):
    File "/Day06/Set_Demo01.py", line 58, in <module>
    s3.remove(9)  # 这个元素是不存在的
    KeyError: 9

6.2.4 遍历集合
  • 集合是可迭代类型数据
  • 使用for循环可以遍历集合
  • set集合没有索引,无法使用while进行遍历
  • 如果想要得到索引和对应的值,使用enumerate

遍历集合案例:

# 遍历集合
    print("---------for循环遍历集合——----")
    s4 = set([1, 2, 3, 4, 5])
    for i in s4:
        print(i, end=",")

    print("-------带索引的遍历方式-------")
    s5 = set("床前明月光")
    for index, i in enumerate(s5):
        print(index, i)
运行输出结果:
#	
    1,2,3,4,5,
    -------带索引的遍历方式-------
    0 前
    1 床
    2 月
    3 光
    4 明

6.3 集合的交集和并集

  • 交集:返回两个集合相同的元素,返回数据类型是集合
  • 并集:返回两个集合内多有的元素并去除重复,返回数据类型是集合

交集和并集案例:

      print("--------交集-------")
      # 交集,使用运算符	"&"
      s5 = set([1, 2, 3])
      s6 = set([4, 5, 6, 2, 3])
      # 交集  &
      s7 = s5 & s6
      print(s7)

      print("--------并集-------")
      # 并集,使用运算符	"|"
      s8 = s5 | s6
      print(s8)
      print(type(s8))
运行输出结果:
#
      --------交集-------
      {2, 3}
      --------并集-------
      {1, 2, 3, 4, 5, 6}
      <class 'set'>

六、运算符

1 算术运算符

下面的例子以a = 10  b = 20  为例进行计算
运算符        描述         实例
+       加      两个对象相加       	a + b      输出的结果  30
-       减      两个对象进行相减       a - b      输出的结果   -10
*       乘      两个对象进行相乘       a * b      输出的结果   200
/       除      两个对象进行相除       b / a      输出的结果   2
//      取整    返回商的整数部分       9//2       输出的结果   4    9.0//2.0   输出的结果 4.0  
%       取余    返回除法的余数         b % a      输出的结果   0
**      幂      返回x的y次幂           a ** b    10的20次方  输出的结果

2 赋值运算符

  运算符         描述           实例
	=        赋值运算符    把=号右边的结果赋值给左边的变量   num = 1+2*3   
赋值运算符的基本格式:
  变量  =  表达式
功能:
    计算了等号右侧的表达式的值,赋值给等号左边的变量,赋值结束后的变量

3 复合运算符

a = 3 c = 10
+=     加法赋值运算     c += a  ===>     c = c + a
-=     减法赋值运算     c -= a  ===>     c = c - a
*=     乘法赋值运算     c*= a  ===>      c = c * a
/=     除法赋值运算     c /= a  ===>     c = c / a
%=     取余法赋值运算   c %= a  ===>     c = c % a
**=    幂法赋值运算     c **= a  ===>    c = c ** a
//=    取整法赋值运算   c //= a  ===>    c = c // a

4 比较运算符

比较运算符
运算符        描述          示例
==   检查两个操作数是否相等,如果是条件为真(True),反之为否(False)  注意:不仅比较大小,还比较类型
   				例:print(10 ==  '10')   False
!=   检查两个操作数是否相等,如果是值不相等(True),反之False
  			    例:print(10 !=  '10')    True
>    检查左操作数的值是否大于右操作数的值,如果是返回True,反之False
<    检查左操作数的值是否小于于右操作数的值,如果是返回True,反之False
>=   检查左操作数的值是否大于等于右操作数的值,如果是返回True,反之False
<=   查左操作数的值是否小于等于右操作数的值,如果是返回True,反之False


5 逻辑运算符

逻辑运算符
运算符       逻辑表达式      描述                  示例
and     x and y 布尔“与”  如果x为false,x and y   返回false,否则返回y的计算值
or      x or y  布尔“或”  如果x为True             返回True 反之返回y的计算值 
not      not x 布尔“非”   如果x为True             返回的False,如果False返回的True
#代码=======================
      # 逻辑运算符
      a = True
      b = 10
      print(a and b)
      print(a or  b)
      print(not a)
      a = False
      b = 10
      print(a and b)
      print(a or  b)
      print(not a)
#结果=======================
      10
      True
      False
      False
      10
      True

6 位运算符

概述:
    按照位运算符把数字转换为二进制来计算
python中的位运算法则有哪些?
运算符      描述       示例
&    按位与运算符:参与运算的两个值,如果两个相应位都是1,则该位的结果为1,否则为0

|    按位或运算符:只要对应的两个二进制位有一个为1,结果就为1,反之为0   	

^    按位异或运算符:当两个二进制位不相同时,结果为1,反之为0

~    按位取反运算符:对数据的每一个二进制位进行取反,即把1变为0,0变为1 ~x类似-x-1  10 -11 
			
<<    左移运算符:运算数的每一个二进制位全部向左移若干位,由<<右边的数字指定了移动的位数,高位丢弃,低位补0

>>   右移运算符:把>>左边的运算数的各个二进制位全部右移若干位,由>>右边数字控制移动的位数

七、条件语句

1 if条件语句的概述

当满足某个条件的时候 我们要做的事情

生活中的场景
做地铁/火车 需要先安检 如果有票就能进站  或者不允许进站

开发中的场景
用户登陆注册 判断登陆时候填写信息是否和注册提交给后台的保持一致

例子:判断重要的日期 五一劳动节,情人节,发工资

思考:单分支条件语句,如果条件为真执行要做的事情 条件为假不会有任何输出,我如果想条件为假的结果
     

2 if判断语句的格式

2.1 if语句的基本格式

作用:if语句用来进行判断:
if 要判断的条件:
    条件成立,要做的事

if的基本格式
if 条件:
    要做的事情

2.2 if…else

if...else
格式:
   if 条件:
       满足条件,做事情1
       满足条件,做事情2
       满足条件,做事情3
       ....
   else:
       不满足条件,做事情1
       不满足条件,做事情2 
       不满足条件,做事情3  

练习:
   要求,从键盘获取自己的年龄,判断是否大于等于18,如果条件成立“XXXX”
    age = int(input('请输入你的年龄'))
    if age >= 18:  #执行条件为真的结果
        print('成年了')
    else:   #执行条件为假的结果
        print('未成年')

   
   #案例,进火车站检票 如果有票可以进站 或者不允许进站
    ticket = 0 #1表示有票 0表示无票
    if ticket == 1:
        print('有车票可以进站')
    else: #执行条件为假的结果
        print('没有车票,请先购票')

练习:
   要求:从键盘输入刀子的长度,如果刀子长度没有超过10cm,允许上火车,反之不允许
   	knife1 = input('请输入刀子的长度:')
    knife = int(knife1)  #int()函数把input()函数返还的字符串先转换成数字类型
    if knife <= 10:  #满足进站的条件  执行条件为真的结果
        print('可以进站')
    else:  #执行条件为假的结果
        print('不允许进站')


拓展
#if比较运算符
age = 17
if age >= 18:
    print('可以进网吧了')
else:
    print('未成年人不准进网吧')

#if逻辑运算符 or
my = input('你去吗?')
mywife = input('你去吗?')
if my == '去' or mywife == '去':
    print('去买菜')
else:
    print('下馆子')

#if逻辑运算符  and
my = input('你去吗?')
mywife = input('你去吗?')
if my == '去' and mywife == '去':
    print('可以领证了')
else:
    print('再等等,过段时间再去')

#案例:if逻辑运算符not
age = 16
if not(age >= 18):
    print('成年了')
else:
    print('未成年')

#案例3:if逻辑运算符   ---白富美
color = input('你白吗?')
money = float(input('你富吗?'))
beautful = input('你美吗')
#带有小数点的浮点型 属于数字类型
if color == '白' and money >= 10000000 and beautful == '美':
    print('白富美')
else:
    print('--------')

2.3 elif

1.if单分支条件语句 当条件为真执行要做的事情 条件为假不会有任何输出  如果我想输出条件为假的结果
2.if else 多分支条件语句  当条件为真执行要做的事情 条件为假执行else后面的语句  如果我们有多个条件都为真 只要满足就可以做对应的事情 
 
格式:
elif 的使用格式:
if 条件1:
    事情1
elif 条件2:
   事情2
elif  条件3:
    事情3
else: #执行条件为假的结果
	要做的事情

说明:
当条件1满足时,执行事情1,然后整个if语句结束
当条件1不满足,那么需要判断条件2,如果条件2满足,执行事情2,然后整个if语句结束
当条件1和2都不满足,如果条件3满足,执行事情3,然后整个if语句结束
案例:

#if...elif案例
#根据考试的成绩,判断学生的等级
#案例:通过键盘录入的方式获取学生的成绩(Number类型中的int)
score = 59
if score == 60:
    print('D')
elif score > 60 and score <= 75:
    print('C')
elif score > 75 and score < 90:
    print('B')
elif score >= 90:
    print('A')
else: #以上条件都不满足 执行else条件为假的结果
    print('你要补考')

注意:
   elif必须和if一起使用,否则出错
   
练习:
   根据用户的输入,判断是星期几,用户输入的数值范围为1~7(正整数)

3 if语句的嵌套

3.1 概述

条件语句里面再嵌套条件语句

3.2 if语句嵌套的格式

if 条件1:
    满足条件1,做事情1
    满足条件1,做事情2
    满足条件1,做事情3
    .....(省略)
    if 条件2:
        满足条件2,做事情1
        满足条件2,做事情2
        满足条件2,做事情3

说明:外层的if判断,if...else
      内层   if...else


# if语句嵌套
#案例,火车安检,先验票,再检查有没有携带违禁品  如果刀子长度没有超过10cm,允许上火车
nicket = 1 #1有票 0无票
knife = 12  #单位cm
#1.先检查用户是否有票
if nicket == 1:
    print('通过安检,可以进站')
    if knife <= 10:
        print('可以上车了')
    else:
        print('携带违禁物品,先抓起来暴打一顿,再送公安局')
else:
    print('请先买票再进站')

4 if 的应用(猜拳游戏)

石头 剪刀 布
要求:
   电脑随机生成一个0~2之间的正整数0,1,2,剪刀(0),石头(1),布(2),要求用户通过键盘录入的方式输入0~2之间的正整数,产生结果:
# 石头剪刀布游戏===========================================
# import random
# listuser = ['剪刀','石头','布']
# jiqiuser = random.choice(listuser)
# User=input('输入的石头、剪刀或者布')
# print(jiqiuser)
# if (User=='石头' and  jiqiuser=='剪刀') or (User=='剪刀' and jiqiuser=='布') or (User=='布' and  jiqiuser=='石头'):
#     print('你赢了')
# elif User==jiqiuser:
#     print('平手')
# else:print("你输了")
#===========================================

八、循环语句

1 循环语句的介绍

生活中的场景
电风扇 跑道 

软件开发场景

总结: 在程序开发过程中 如果相同的代码执行多次 我们就可以使用循环,循环不是必须的
提高代码的重复使用率,一般应用在开发中

2 while循环

2.1 while循环的格式

格式
while(循环的条件): 如果循环条件满足
	做事情1,
	做事情2,
	做事情3

案例:循环输出1-5的数字

2.2 while循环的应用

案例1:
   计算1~100之间的累计和(包含1和100)
   
案例2:
   计算1~100之间偶数的累计和(包含1和100)
   
   思考:while循环当条件为真执行对应结果 为假就不会执行 如果想输出条件为假的结果 while else 类似
   if else语句


2.3 while…else

格式:
while 判断表达式:
     语句1
else:
     语句2

逻辑:
   在条件语句(判断表达式)为false,执行else中的语句2
   
案例:循环输出数字1-3

2.4 while循环的嵌套

while循环,while里面嵌套一个while
格式:
    while 条件1:
          条件1满足,做事情1
          条件1满足,做事情2
          条件1满足,做事情3
          .....
          while 条件2:
               条件2满足,做事情1
               条件2满足,做事情2
               条件2满足,做事情3

2.5 while循环嵌套的应用

案例1.打印一个矩形

******
******
******
******
代码:
  # 打印一个矩形===========================================
  i = 1
  while ( i <= 4):
      j = 1
      while(j <= 6):
          print("*",end='')
          j +=1
      else:
          print()
      i +=1
  # 非嵌套=====================================
  i  = 1
  while ( i <= 24):
      print("*",end="")
      if i%6==0:
          print()
      i +=1
  # ==========================================

案例2:
打印杨辉三角

*
*  *
*  *  *
*  *  *  *
*  *  *  *  *

代码:

# 杨辉三角===================================	
i = 1
while (i <= 5):
    j=1
    while (j <= i):
        print("* ",end='')
        j+=1
    print()
    i+=1
# ==========================================

案例3:
打印九九乘法表
代码:

    i = 1
    while(i <= 9):
         j = 1
         while (j <= i):
            print("%d*%d=%d  "%(i,j,i*j),end='')
            j+=1
        i+=1
        print()

3 for 循环

3.1 for循环格式

和while一样 也能够进行数据的循环

循环序列的项目 String 

格式:
for 临时变量 in 字符串或者列表
	执行循环对应的结果
else:
	执行不满足循环条件的结果 
	
#案例:循环一个字符串里面每一个字符

#案例:循环一个空字符串

#循环输出1-10的结果

拓展:
	enumerate()枚举函数 可以同时获取下标和元素值 


3.2 for循环的嵌套

语法格式:
for 临时变量1  in 字符串或者列表:
	for 临时变量2 in 字符串或者列表:
		执行的代码
		
#输出5*5的矩形

#打印九九乘法表



3.3 死循环

1.cpu满负荷工作 损坏计算机硬件
2.内存溢出 

语法格式:
while True:
	执行的代码
	需要有一个结束的条件

4 break / continue

4.1 break

#总结:终止程序的执行  后面代码不会继续执行

4.2 continue

#总结:跳出当前循环 后面的会继续循环执行

4.3 注意点

1.break,continue一般使用在循环语句里面  在if条件语句使用


九、进制以及原码、补码

1 进制的概述

数据的存储

数据存储到计算机
运行速度快 存储海量数据  读取运算方便

数据存储到计算机什么地方?
存储到内存里面去了

数据是如何存储到内存里面
计算机很大一部分功能存储数据 存储器存储 类似内存条 

内存?
抽象的概念
一个状态 1开启 0关闭
一个房间假设装8个开关 控制灯的打开或者关闭
一个房间我们称它为一个字节 每一个开关称为位
1字节= 8位
房间有个编号18 相当于是门牌号 

计算机以二进制方式保存我们的数据到内存里面
0 1

内存存储数据的单位
1bit
8bit = 1字节
1024字节 = 1k
1024k = 1M
1024M = 1G
1024G = 1T
1024T = 1P

进制:进位的计数

2 进制的分类

生活中最常见的进制----》十进制1,2,3,4,5,6,7......
常见的进制分为:
   二进制
   八进制
   十进制
   十六进制
   
二进制:
任何数据在计算机中都是以二进制的形式存在,二进制早期由电信开关演变而来

2.1 二进制

特点:
    由0,1组成,0b开头,逢二进一
    
 例如:
	0 + 0 = 0
	0 + 1 = 1
	1 + 1 = 10
    11 + 1 = 100

2.2 八进制

八进制:
    有数字0~7组成,逢八进一 ,以0o开头0,1,2,3,4,5,6,7 逢八进一
    
 例如:
    1 + 7 = 10
    1 + 3 = 4

2.3 十进制

特定:
   0~9数字组成,逢十进一,整数的默认是十进制
   1 + 9 = 10
   10 + 3 = 13

2.4 十六进制

特点:
  十六进制的范围0~9   A~F   0,1,2,3,4,5,6,7,8,9,a,b,c,d,e,f
  逢16进1,以0x开头
  1 + f = 10
  

3 进制之间的转换

1.十进制转换为二进制
  做除法,余数逆序
   10(10)---->1010(2)
   10/2 5 0
   5/2  2 1
   2/2  1 0
   1/2  0 1

2.十进制转八进制
10(10)----->12(8)
 10/8 1 2
 1/8 0  1

3.十进制转换为十六进制
直接除以16,余数在10~15之间用a~f表示
10(10)----》a
11(10)-----b

4.二进制转10进制
   当前的数字,乘以2的位数的次方,最后相加
   10进制转换2进制 1010  
   0*2^0 + 1*2^1 + 0*2^2 + 1*2^3 = 10
     
5.八进制转二进制
一转三位,八进制中的1位相当于二进制中的三位,转换的时候按照十进制进行转换

例如:65---->110101
6/2 3 0 
3/2 1 1
1/2 0 1

5/2 2 1
2/2 1 0 
1/2 0 1

6.二进制转换为八进制
三位转1位,从低位取,高位不够补0
110101(2)----》  65(8)

7.十六进制----》二进制
一位转4位
十六进制的一位相当于二进制的4位,转换时按照十进制进行转换
a4(16)----->1010 0100(2)
  a   --->  1010
  4 ----->   0100

   
8.二进制转为十六进制
四转1   从低位取,高位不够补0

补充:
    十进制转换为八进制或则十六进制
    (可以先将10----》2---》8/16)
  0000  1010
1    1   1  1   1  1  1  1    
128  64  32 16  8  4  2  1 

4 进制之间的快速转换

可以使用python中函数实现
下面的符号对应进制数
b   :  二进制
d   :  十进制
o   :   八进制
x   :  十六进制

十进制转换二进制   ----》    bin(10)
十进制转换为八进制 ---》    oct(10)
十进制转换为十六进制  ----》   hex(10)

二进制转换为十进制   -----    eval("0b1010")
八进制转换为十进制 -----    int(参数1,参数2):参数1:需要转换的数,参数2,进制的类型
print(int('0o12',8))
十六进制转十进制 ----    int(参数1,参数2):参数1:需要转换的数,参数2,进制的类型

#将10进制15转换2进制
	print(bin(15))
#将10进制15转换8进制
	print(oct(15))
#将10进制15转换为十六进制
	print(hex(15))

#二进制转换为十进制
	print(eval('0b1010'))
#八进制转换为十进制
	print(int('0o12',8))
#十六进制转十进制
	print(int('0xa',16))

5 原码/反码/补码

概述:
    数据存储:计算机的存储数据,先开辟一个内存空间,在存储数据,计算机中开辟内存的最小单位是字节,二进制表示数据的存储    0和1  用高位标识符符号表示数值符号(+/-),1表示负数  0:正数
    
原码/反码/补码是数值运算的基础,在计算机中,数值运算是基于二进制数,底层是二进制运算,使用高位标识符   1表示负数  0:正数

基础定义:
   原码:
       就是二进制定点表示法,即最高为为符号位,0:正数,1:负数,其余的位数表示数值的大小
       
    通过一个字节   
    
     10      0000 1010
    -10      1000 1010 
       
       
   反码:(负数的反码除符号位以外,按位取反)
      正数的反码和原码相同,负数的反码是对其原码逐位取反(1变0,0变1),但是符号位不变
      
      +10   反码   0000 1010
      -10   反码   1111 0101
						   
   补码:(负数的补码是按位取反,末尾加一)
    正数的补码和原码一样,负数的补码是在其反码的末尾加1
    +10    补码     0000 1010  
    -10    补码     1111 0110
    
    
注意:
   计算机中都是以补码的形式存在
   
 问题:
    在计算机中,为什么不用原码和反码而用补码?
    因为原码和反码不准确,而使用补码才准确
    二进制转为十进制
    
    1.使用原码计算
      10-10   
      +10    0000 1010
      -10    1000 1010
      -----------------------------------
             1001 0100    4+16 =-20
    
    2.使用反码计算
    10-10
    +10    0000 1010
    -10    1111 0101
    --------------------------------
            1111 1111    10000000  ===》   -0
            
    3.使用补码计算
    10-10
    +10   0000 1010
    -10   1111 0110
    ---------------------------
          0000 0000     0
     
练习:
    分别计算以下补码表示的十进制数是多少?
   二进制   
  1.0b0000 1111    ------> 15
  2. 0b1111 1111  -----》(将补码转换反码)0b1111 1110   __---->(反码再转原码)0b1000 0001    -1
  3.0b1000 0001    ---->0b1000 0000  ----->    0b1111 1111    -127
  4.~6取反(1变0,0变1)
  
  6   ----》   二进制   ---》   0000 0110
  取反
  ~6       1111 1001     补码(计算在存储数据时按补码进行存储)
  
  1111 1001   补码
  1111 1000   反码
  1000 0111   原码
  ---------

十、生成器

1 生成器定义

  • Python的生成器是一个返回可以迭代对象的函数。

  • 先看案例:

    #创建一个列表,元素为0--20以内的偶数
        list01 = [2, 4, 6, 8, 10, 12, 14, 16, 18]
        list02 = [x * 2 for x in range(1, 10)]
        Generator01 = (x * 2 for x in range(1, 10))
        print(list01)
        print(list02)
        print(Generator01)
        for i in Generator01:
        print(i, end=",")
    运行输出结果:
    #
        [2, 4, 6, 8, 10, 12, 14, 16, 18]
        [2, 4, 6, 8, 10, 12, 14, 16, 18]
        <generator object <genexpr> at 0x0000014043D37200>
        2,4,6,8,10,12,14,16,18,
    
  • 创建生成器的方式有多种,只要把一个列表生成式的[]改成()

  • 创建list和Generator区别在于外层[],(),list表示一个列表,Generator表示生成器

  • 遍历生成器内容:

    • next()
    • for循环

1.1 next()读取生成器内容

# next
# 定义一个生成器
    Generator = (x * 2 for x in range(5))
    temp = next(Generator)
    print(temp)
    temp = next(Generator)
    print(temp)
    temp = next(Generator)
    print(temp)
    temp = next(Generator)
    print(temp)
    temp = next(Generator)
    print(temp)
    temp = next(Generator)# 注意:如果一直写next()函数,当超出了元素的个数范围的时候会直接报错
    print(temp)
运行输出结果:
    #
    0
    2
    4
    6
    8
    Traceback (most recent call last):
      File "/Day06/Generator_Demo01.py", line 24, in <module>
    temp = next(Generator)
    StopIteration

1.2 for循环遍历生成器内容:

# 循环遍历
    Generator = (x*2 for x in range(5))
    for temp in Generator:
        print(temp)
运行输出结果:
#
    0
    2
    4
    6
    8

1.3 总结:

生成器保存的是一个算法,每次调用next()函数,就能计算出生成器下一个元素的值,直到最后一个元素,
如果超出了元素的最大长度范围,报错,
通过for循环来迭代他,并且不用关心超出界限的问题

2 函数实现生成器(熟悉)

2.1 函数的定义:

格式: def 函数名():

方法体语句

2.2 函数的调用:函数名()

练习:菲波拉锲数列

-  1 1 2 3 5 8 13    除第一个和第二个外,任意的数都是由前两个数相加得到
   a = 0
   b = 0
   c = 1
   while a < 5:
       temp = c
       c = b + c
       b = temp       
      	a += 1
       print(b)
2.2.1函数(方式一)
def fib1():
    a = 0
    b = 0
    c = 1
    while a < 5:
        temp = c
        c = b + c
        b = temp
        a += 1
        print(b)
        
        
fib1()
2.2.2函数(方式二)
def fib2():
  	a = 0
  	b,c = 0,1
  	while a < 5:
        print(c)
        b,c = c , b+ c
        # b = c
        # c = b + c
        a += 1


fib2()

3 生成器–yield(熟悉)

print("-----fib3()---------")
def fib3():
    a = 0
    b , c = 0 ,1
    while a < 5:
        # print(c)
        yield c
        b , c = c, b + c
        a += 1
f = fib3()#生成器
print(f)
print(next(f))
print(next(f))
print(next(f))
print(next(f))
print(next(f))
运行输出结果:
#
-----fib3()---------
    <generator object fib3 at 0x000002352A007360>
    1
    1
    2
    3
    5

yield是一个类似return的关键字,迭代一次遇到yield的时候返回(右侧,后面的值)

总结:

下一次迭代时,从上一次迭代遇到yield后面的代码(下一行)开始执行
	yield返回一个值,并且记住返回值的位置,
	下次迭代的时候就从这个记录的位置开始
输出时注意调用next()的次数,超出内容会报错

十一、迭代器概述

迭代:
	访问集合元素的一种方式
迭代器:
	可以被next()函数调用并且不断的返回下一个值的对象(迭代器 Iterator)
迭代对象:
	是一个可以记住遍历位置的对象
	迭代器对象从集合的第一个元素开始访问,直到所有的元素访问完毕为止
迭代器的特点:
	只能往前,不会后退

1 迭代对象(掌握)

直接可用for循环遍历的数据类型有哪些?

  • 一类:list tuple dict set str
  • 一类:生成器

这些可以直接作用与for循环的对象的统称----》可迭代对象(Iterable)

怎么判断是否可以迭代?

  • 可以使用isinstance()来判断一个对象是否是Iterable,返回值是True或者False
  • 需要使用一个模块collections
    from collections import Iterable
    a = isinstance([],Iterable)
    b = isinstance((),Iterable)
    c = isinstance({},Iterable)
    d = isinstance("aaaa",Iterable)
    e = isinstance(1000,Iterable)#false
    f = isinstance((x for x in range(5)),Iterable)
    print(a)
    print(b)
    print(c)
    print(d)
    print(e)
    print(f)
运行输出结果:
#
    True
    True
    True
    True
    False
    True

2 迭代器(掌握)

迭代器:

可以被next()函数调用并且不断的返回下一个值的对象(迭代器 Iterator)

判断一个元素是不是迭代器:isinstance(ocject, Iterator)

print("--------Iterator---------")
    from collections import Iterator
    a = isinstance([], Iterator)
    b = isinstance((), Iterator)
    c = isinstance({}, Iterator)
    d = isinstance("aaaa", Iterator)
    e = isinstance(1000, Iterator)
    f = isinstance((x for x in range(5)), Iterator)
    print(a)
    print(b)
    print(c)
    print(d)
    print(e)
    print(f)
运行输出结果:

--------Iterator---------
    False
    False
    False
    False
    False
    True
Python中 list、truple、str、dict这些都可以被迭代,但他们并不是迭代器。为什么?

因为和迭代器相比有一个很大的不同,list、truple、map、dict这些数据的大小是确定的,也就是说有多少事可知的。
但迭代器不是,迭代器不知道要执行多少次,所以可以理解为不知道有多少个元素,每调用一次next(),就会往下走一步,是惰性的。

判断是不是可以迭代,用Iterable
判断是不是迭代器,用Iterator

所以,
凡是可以for循环的,都是Iterable
凡是可以next()的,都是Iterator

集合数据类型如list、truple、dict、str都是Itrable不是Iterator,但可以通过iter()函数获得一个Iterator对象

Python中的for循环就是通过next实现的

3 Iter()函数(掌握)

== 生成器都是Iterator对象,但是list、dict、str都是迭代对象但是不是迭代器==

使用iter()函数可以把这些可迭代对象转换为迭代器

案例代码:

print("-----------Iter()-------------")
    from collections import Iterator
    words = [1, 5, 8, 3, 5]
    a = isinstance(iter(words), Iterator)
    b = isinstance(iter(()), Iterator)
    c = isinstance(iter({}), Iterator)
    d = isinstance(iter("hhaha"), Iterator)
    f = isinstance((x for x in range(5)), Iterator)
    print(a)
    print(b)
    print(c)
    print(d)
    print(f)
    words = iter(words)
    print(next(iter(words)))
    print(next(iter(words)))
    print(next(iter(words)))
运行输出结果:
#
-----------Iter()-------------
    True
    True
    True
    True
    True
    1
    5
    8

4 迭代器总结(掌握)

	==1.凡是可以作用与for循环对象都是Iterable类型==
	==2.可以作用与next()函数的对象都是Iterator类型==
	==3.集合数据类型list、tuple、dict、str等是Iterable但不是Iterator==
	==4.集合数据类型list、tuple、dict、str等通过iter()可以将其转换为Iterator==

十二、函数的定义和调用

1 函数的定义

函数定义的格式:
   def 函数名():
   	    代码
例如:
#函数的定义
def printInfo():
    print("----------")
    print("人生苦短,我用python")
    print("----------")
#函数的调用
   格式:
      函数名()
   printInfo()

2 定义函数

def info():
    name = input("请输入你的姓名:")
    age = input("请输入您的年龄:")
    print("您的姓名为:%s,年龄:%s"%(name,age))
#调用函数
info()

3 函数的参数(掌握)

3.1 定义不带参数的函数

定义函数
def addnum():
    a = 33
    b = 22
    c = a + b
    print(c)
调用函数
addnum()

3.2 定义带参数的函数

定义函数
def add2Num(a,b):#形参
    c = a + b
    print(c)
调用函数
add2Num(11,22)#实参

4 调用函数注意事项(掌握)

A:形参和实参必须一一对应

B:函数调用时参数的顺序

def test(a,b):
    print(a,b)
test(1,2)
test(b = 1, a = 2)

5 参数总结(掌握)

  • 形参:定义时小括号中的参数,用来接受参数
  • 实参:调用时小括号中的参数,用来传递给函数使用

做一做:模拟一个简单的两位数的计算器,功能(加减乘除)

#定义一个函数,完成计算器的加法运算
def add(a,b):
    c = a + b
    print(c)
# 定义一个函数,完成计算器的减法运算
def minus(a, b):
    c = a - b
    print(c)
# 定义一个函数,完成计算器的乘法运算
def cheng(a, b):
    c = a + b
    # print(c)
# 定义一个函数,完成计算器的除法运算
def chu(c, d):
    c = c / d
    print(c)

add(1,2)
minus(2,1)
cheng(1,2)
chu(1,2)

6 函数的返回值(掌握)

6.1 函数的返回值概述

  • 定义: 返回值:就是程序中函数完成一件事后将结果返回给调用者

6.2 带有返回值的函数

  • #定义函数
    def add2num(a,b):
    
        c = a + b
        return c
        #或者
        # return a + b
    sum = add2num(1,2)
    print(sum)
    -  保存带有返回值的函数
       #定义函数
       def add2num(a,b):
           c = a + b
           return c
           #或者
           # return a + b
       sum = add2num(1,2)
       print(sum)
    -  函数的类型
    

7 函数的类型(掌握)

函数根据有没有参数,有没有返回值,可以相互组合,一共有4中
无参数,无返回值
无参数,有返回值
有参数,无返回值
有参数,有返回值

7.1 无参数,无返回值

此类函数,不能接受参数,也没有返回值,一般情况下,打印提示灯类似的功能,使用该类函数

#无参数,无返回值
def printInfo():
    print("------------")
    print("人生苦短,我用python")
    print("-----------")

printInfo()

7.2 无参数,有返回值

此类函数,不能接受参数,但是可以返回某个数据,一般情况,像数据采集,

#无参数,有返回值
def getTemp():
    return 24

temp = getTemp()
print("当前的温度为:%d"%temp)

7.3 有参数,无返回值

此类函数可以接受参数,但是不可以返回数据,一般情况适用于变量设置数据,而不需要结果

#有参数,无返回值
def add2num(a,b):
    result = a + b
    print(result)

add2num(11,22)

7.4 有参数,有返回值

此类函数,不仅接受参数,同时可以返回某个数据,

"""
1.是否需要传参
    是   
         需要传几个
                传一个        
2.是否需要返回
    有     return   将数据返回,二次处理
    没有  

"""
def calculateNum(num):
    i = 0
    sum = 0
    while i <= num:
        sum += i
        i += 1
    return sum

result = calculateNum(100)
calculateNum(200)
print(result)

案例2:

#定义一个函数
def get_wendu(a):
    wendu = 22
    print("当前的温度为:%d"%wendu)
    return wendu
def get_wendu_huashi(wendu):
    print("======4========")
    wendu = wendu + 3
    print("=====5=====")
    print("当前的温度为:%d"%wendu)
    print("======6======")
print("====1======")
result = get_wendu(1000)
print("=======2=======")
get_wendu_huashi(result)
print("=======3======")

7.5 总结

  • 函数是否有参数和返回值,决定函数的格式(4种)

8 函数的嵌套调用(掌握)

8.1 概述:

  • 函数的嵌套调用: 一个函数中又调用了另外一个函数

8.2 示例:

def testB():
    print("----testB-----")

def testA():
    print("-----testA-----")
    testB()
    
testA()

想一想:

案例1:
   1.写一个函数打印一条横线(20个“-”)
   2.打印自定义行数的横线

分析:
    是否参数
         需要	传递一个参数   确定“-”号的个数
         不需要   
    是否返回值
         需要	返回给调用者
         不需要    

 内容:
    打印一条横线
         有参   无返回 
            def test(n):
                print(n*"-")
                
         有参   有返回
               def test(n):
                    return n * "-"
                    
         无参  无返回
              def test():
                   print(20*"-")
                   
         无参 有返回
               def test():
                   retrun "-" * 20

代码:

# n:确定-号的个数
#打印一行-号
def printOneLine(n):
    print(n * "-")

# 打印多条横线
def printNumLine(num):
    i = 0 
    while i < num:
        printOneLine(20)
        i += 1

# 调用函数
printOneLine(20)
printNumLine(3)

9 函数的参数的传递(掌握)

具体的细分:

可变对象和不可变对象(值传递,引用传递)

9.1 不可变对象参数的传递

不可变对象

定义:表示该值不能发生变化

不可变的数据类型

String 	tuple  	number
"""
String	tuple	number
"""
def add(num):
    num = num + 10
    return num

d = 2
e = add(d)
print(d)#2
print(e)#12

def fun(num):
    print(id(num))
    num = 10
    print(id(num))
temp = 20
print(id(temp))
fun(temp)
print(temp)

"""

总结:
在python中,对于不可变对象,调用自身的任意函数,并不会改变对象自身的内容

9.2 可变对象

定义:

值发生改变

可变对象的数据类型有哪些?

list 	dict   set
"""
list	dict	set
"""
#以列表为例
def change(num):
    num.append(1)
d = [0]

change(d)
print(d)

def fun(list):
    list[0] = 100

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

a = 10
b = 10
b = 40
print(id(a),id(b))

c = 20
d = 30
print(id(c),id(d))

d = c
print(id(c),id(d))

10 关键字参数(掌握)

Python允许函数调用时参数顺序和定义时不一致
def myPrint(str,age):
    print(str,age)

myPrint("zhangsan","18")
myPrint(age = 18,str = "张三")

**案例2:关键字参数: kw

def person(name,age,**kw):
    print("name:",name,"age:",age,"other:",kw)

person("zhangsan","12")
person("zhangsan",12,city = "北京")
person("张三",15,gender = "M",job = "engineer")

11 默认参数/缺省参数

概述:

python为了简化函数的调用,提供默认参数机制,调用函数时,缺省参数的值如果没有传入,则会被认为是默认值
#定义一个函数
def printInfo(name,age = 35):
    print("name:",name)
    print("age:",age)

printInfo("张三")
printInfo(name = "张三")
printInfo(age = 18,name = "haha")

def pow(x ,n = 2):
    r = 1
    while n > 0:
        r *= x
        n -= 1
    return r   

p = pow(2)
print(p)

def printInfo1(name,sex = "nam",age = 35):
    print(name,sex,age)
    
printInfo1("张三","男")

注意:

#带有默认值的参数一定要位于参数列表的最后面
#必选参数必须在前面
#设置何种参数为默认值,一般将参数值变化较小的设置为默认参数

12 不定长参数(掌握)

概述:
一个函数能够处理比当初声明时更多的参数称为不定长参数,声明时一般不会命名

格式:

def function(args,*args,**kwargs):
加了一个*号的变量args会存放所有未命名的变量参数,相当于  元组
加了**号,存放所有命名的变量参数,相当于表达式  key  =  value   kwargs为字典
print("-" * 20)
# 经典方式
def fun(a, b, *args, **kwargs):
    print("a= ", a)
    print("b= ", b)
    print("args= ", args)
    print("kwargs= ", kwargs)
    print("*" * 30)
    for key, value in kwargs.items():
        print(key, "=", value)
fun(1, 2, 3, 4, 5, 6, 6, 8, 9, m=6, n=7, p=8)
# 另一种方式
c = (3, 4, 5)
d = {"m": 6, "n": 7, "p": 8}
print("_" * 50)
fun(1, 2, *c, **d)
print("_" * 50)
# 再一种方式
fun(1, 2, c, d)
def fun1(*args, **kwargs):
    print(args)
    print(kwargs)

# fun1(1, 2, 3, 4, m=5)

运行输出结果:

--------------------
a=  1
b=  2
args=  (3, 4, 5, 6, 6, 8, 9)
kwargs=  {'m': 6, 'n': 7, 'p': 8}
******************************
m = 6
n = 7
p = 8
__________________________________________________
a=  1
b=  2
args=  (3, 4, 5)
kwargs=  {'m': 6, 'n': 7, 'p': 8}
******************************
m = 6
n = 7
p = 8
__________________________________________________
a=  1
b=  2
args=  ((3, 4, 5), {'m': 6, 'n': 7, 'p': 8})
kwargs=  {}
******************************

13 匿名函数(熟练)

13.1 匿名函数概述

  • 定义:
    • 不使用def这样语句来定义函数
    • 使用lambda来创建一个匿名函数
  • 原则:
    • 用lambda关键字能够创建小型匿名函数,可以省略用def声明函数的标准步骤
  • 格式:
    • lambda[args1,args2…]:expression

匿名函数的基本定义

a = 1
sum = lambda args1,args2:args1 + args2
print(sum(10,20))

特点:

1.lambda只是一个表达式,比函数def声明简单
2.lambda的主体也是一个表达式,而不是代码块,只能在lambda表达式中封装简单的逻辑
3.lambda函数有总计的命名空间,且不能访问自由参数列表以外或者全局命名空间的参数
4.lambda函数能够接受任何数量的参数,只能返回一个表达式的值

13.2 匿名函数的应用场景(熟悉)

  • 作为自定义函数的参数进行传递

    • 类似调用函数中传入的实参
  • 匿名函数的应用场景(作为自定义函数的参数进行传递)

    def fun(a,b,opt):

    print(a)
    print(b)
    print(opt(10,20))
    

    fun(1,2,lambda x,y:x + y)

  • 作为内置函数的参数

    • 字典存储姓名和年龄的数据,把字典内的元素按照姓名或年龄排序

15 装饰器的概述(熟悉)

15.1 装饰器的基本格式

  • @函数名
# 第一波
def foo():
    print("foo")
# foo#表是函数
foo()  # 表示执行foo函数
# 第二波
def foo():
    print("foo")
foo = lambda x: x + 1
foo()

15.2 定义

是一个闭包,把一个函数当作参数,

返回一个替代的函数,一个本质返回函数的函数

15.3 简单的装饰器

def fun01():
    print("fun01")

def fun02(fun):
    def fun03():
        print("fun03")
        fun()
    return fun03

f = fun02(fun01)
f()
运行输出结果:
#
fun03
fun01

15.4 需求

  • 初创公司有N个业务部门,1个基础平台部门,基础平台部门负责底层的功能
    • 如:数据库操作,redis调用,监控API等功能
  • 业务部门使用基础功能,只需要调用基础平台的功能即可

# 定义基础平台的功能
def f1():
    print("f1")
def f2():
    print("f2")
def f3():
    print("f3")
def f4():
    print("f4")
# 业务部门使用基础功能 业务部门第一组
f1()
f2()
f3()
f4()
##业务部门使用基础功能 业务部门第二组
f1()
f2()
f3()
f4()

#老大将任务交给老王同志
def f1():
    #验证1
    #验证2
    #验证3
    print("f1")
def f2():
    #验证1
    #验证2
    #验证3
    print("f2")
def f3():
    #验证1
    #验证2
    #验证3
    print("f3")
def f4():
    #验证1
    #验证2
    #验证3
    print("f4")

#业务部门,第一组
f1()
f2()
f3()
f4()
#业务部门,第二组
f1()
f2()
f3()
f4()

#小王

只对基础平台的代码做重构,其他业务部门不动

def check_login():
    # 验证1
    # 验证2
    # 验证3
    pass

def f1():
    check_login()
    print("f1")
def f2():
    check_login()
    print("f2")
def f3():
    check_login()
    print("f3")
def f4():
    check_login()
    print("f4")


#小小王,


#使用装饰器
def w1(func):
    def inner():
        #验证1
        #验证2
        #验证3
        func()
    return inner

@w1
def f1():
    print("f1")

@w1
def f2():
    print("f2")
@w1
def f3():
    print("f3")
@w1
def f4():
    print("f4")


15.5 @函数名(语法糖)

将执行完的w1函数的返回值赋值给@w1下面f1,
即及那个w1的返回值重新赋值给f1


"""
# new_f1 = def inner():
#              # 验证1
#              # 验证2
#              # 验证3
#              func()
#          return inner


#定义一个函数,完成一个包裹的数据
def makeBold(fn):
    def wrapped():
        return "<b>"+fn()+"</b>"
    return wrapped

#定义一个函数,完成一个包裹的数据
def makeItalic(fn):
    def wrapped():
        return "<i>"+fn()+"</i>"
    return wrapped
@makeBold
def test1():
    return "hello world-1"
@makeItalic
def test2():
    return "hello world-2"

@makeBold
@makeItalic
def test3():
    return "hello world -3"


# print(test1())
# print(test2())
print(test3())


15.5 装饰器的应用场景(掌握)

1.引入日志
2.函数的执行时间统计
3.执行函数前的预备处理
4.函数执行后的清理工作
5.权限的校验
6.缓存


15.6 装饰器的示例(掌握)

from time import ctime, sleep
无参数的函数
def timeFun(func):
    def wrapped():
        print("%s called at %s" % (func.__name__, ctime()))
        func()

    return wrapped
@timeFun
def foo():
    print("i am foo")

# foo()
# sleep(2)
# foo()

f = timeFun(foo)
f()

#被装饰的函数有参数

def timeFun(func):
    def wrapped(a, b):
        print("%s called at %s" % (func.__name__, ctime()))
        func(a, b)

    return wrapped
@timeFun
def foo(a, b):
    print(a + b)
foo(3, 5)
sleep(2)
foo(2, 4)
# 3.被修饰的函数有不定长参数
def timeFun(func):
    def wrapped(*args, **kwargs):
        print("%s called at %s" % (func.__name__, ctime()))
        func(*args, **kwargs)

    return wrapped
@timeFun
def foo(a, b, c):
    print(a + b + c)
foo(3, 5, 7)
#装饰器中的return
def timeFun(func):
    def wrapped():
        print("%s called at %s" % (func.__name__, ctime()))
        func()
    return wrapped
@timeFun
def foo():
    print("i am foo")
@timeFun
def getInfo():
    return "---haha----"
foo()
print(getInfo())

16 偏函数(熟练)

16.1 定义:

* 函数在执行时,要带上所有必须的参数进行调用,但是有时参数可以在函数被调用之前提前获知
* 好处: 一个函数或者多个函数的参数预先就能用上,一边函数能用更少的参数进行调用

16.2 代码实例

    from functools import partial
    def add(a, b):
        return a + b

    add(3, 5)   # 8
    add(4, 7)   # 11
    
    puls = partial(add, 100)
    result = puls(10)
    print(result)

运行输出结果:
    #
    110
# 进制转换
# 案例:
    import functools
    
    
    print(int("1010", base=2), "--> base表示进制")

    # 偏函数
    def int2(str, base=2):  # int(x,base)x-->字符串或者数字  base---》进制数   默认是十进制
        return int(str, base)

    print(int2("1011"))
    int3 = functools.partial(int, base=2)
    print(int3("111"))

16.3 总结:

在这里偏函数表达式的意思就是:

 * 在函数add的调用时,我们已经知道里面其中一个参数,我们通过这个参数,
 * 重新绑定一个函数partial(add,100),然后再去调用

17 回调函数(熟练)

17.1 回调函数的定义

  • 回调函数:
    • 就是通过函数指针调用函数,如果你把函数的指针(地址)作为参数传递给另外一个函数,当这个指针被用来调用其所指向的函数时,------回调函数,
    • 回调函数不是由该函数的实现方直接调用,而是在特定的事件或者条件发生时由另外一方调用,用于对该时间或者条件进行响应

17.2 回调函数使用案例

第一个案例(回调函数无返回值):

def clear1(times):
    """
    模拟宾馆扫地
    :param times:
    :return: None
    """
    print("完成扫地的次数", str(times))
    
def clear2(times):
    """
    模拟宾馆洒水
    :param times:
    :return: None
    """
    print("洒水的次数", str(times))
    
def call_clear(times, function_name):
    """
    相当于控制器,控制方法的调用,实现回调函数的核心
    :param times:   调用函数次数
    :param function_name: 回调函数名称
    :return: 调用函数的结果
    """
    return function_name(times)
    
#函数外部
call_clear(10, clear1)

第二个案例(回调函数有返回值):

"""
生成偶数
1.生成一个2 * K形式的偶数
2.生成一个4 * K形式的偶数
"""
# 回调函数1
def double_2k(x):
    return 2 * x
    
# 回调函数2
def double_4k(x):
    return 4 * x
    
# 控制器
def get_number(k, get_even_number):
    """

    :param k: 传入的基数
    :param get_even_number:  回调函数名称
    :return:   回调返回值
    """
    return get_even_number(k) + 1
    
def main():
    k = 2
    i01 = get_number(k, double_2k)
    i02 = get_number(k, double_4k)
    i03 = get_number(k, lambda x: x * 8)
    print(i01)
    print(i02)
    print(i03)
    
main()

18 递归函数(重点)

18.1 递归函数的定义

定义:
	在函数中不调用其他函数,而是调用自己------》递归函数(自己玩自己)
	凡是循环能做的事,递归都能做  

18.2 递归函数的作用

#形式:
def show():
    print("我叫王二小")
    show()
show()

"""	
例如:

   计算一个阶乘n!
   n! = 1*2*3*4...*n
   1! = 1
   2! = 2*1 2*1!
   3! = 3*2*1 3*2!
   4! = 4*3*2*1 4*3!
   n! = n*(n-1)!
   
   参数
       要   1个   
   返回值
       要   结果    

#方法1
def calnum(num):
    # for temp in range(1,num+1):
    i = 1
    result = 1
    while i <= num:
        # result = result * i
        result *= i
        i += 1
    return result
ret = calnum(3)
print(ret)

#方法2:
def calnum(num):
    if num >=1:
        result = num*calnum(num-1)
    else:
        result = 1
    return result
ret = calnum(3)
print(ret)

注意:防止死循环(递归)

18.3 递归遍历目录

import os

def getAllDirRE(path,sp = ""):
    #得到当前目录下的所有的文件
    filesList = os.listdir(path)
    #处理每一个文件
    sp += "  "
    for fileName in filesList:
        #判断是否是路径(用绝对路径)
        fileAbsPath = os.path.join(path,fileName)
        if os.path.isdir(fileAbsPath):

            print(sp+"目录:",fileName)
            #递归函数
            getAllDirRE(fileAbsPath,sp)
        else:
            print(sp + "普通文件",fileName)
getAllDirRE(r"G:\1806")

十三、栈模拟、队列

1 栈模拟递归遍历目录

模拟栈存储方式获取指定路径下所有文件
栈定义:

又名堆栈

堆栈=列表+函数:

.append()#入栈
.pop()   #出栈

1.1 出栈入栈相关操作

#入栈
stack = []
stack.append("A")
print(stack)
stack.append("B")
print(stack)
stack.append("C")
print(stack)

#出栈
res1 = stack.pop()
print("res1=",res1)
print(stack)
res2 = stack.pop()
print("res1=",res2)
print(stack)
def getAllDirRE(path):

1.2 案列:

import os
stack = []
stack.append(path)
#处理栈,当栈为空的时候结束当前动作
while len(stack) != 0:
    #从栈中取数据
    dirPath = stack.pop()
    filesList = os.listdir(dirPath)
    #得到的数据,如果是普通的文件,直接打印,如果,是目录继续压栈
    for fileName in filesList:
        fileAbsPath = os.path.join(dirPath,fileName)
        if os.path.isdir(fileAbsPath):
            print("目录"+fileName)
            #压栈
            stack.append(fileAbsPath)
        else:
            print("普通"+fileName)


getAllDirRE(r"G:\1806")

2 队列模拟遍历目录(熟练)

模拟队列获取指定路径下所有文件

2.1 队列函数

先进先出   排队

2.2 队列相关操作

collections
append:添加
queue:获取队列
len:获取长度
popleft:出队
listdir:获取当前目录的所有文件
isdir  :判断是否是文件

2.3 队列模拟遍历目录案例

import os
import collections
def getAllDirQu(path):
      #创建一个队列
      queue = collections.deque()
      #进队
      queue.append(path)
      while len(queue) != 0:
          #出队
          dirPath = queue.popleft()
          #获取当前路径下的所有的文件
          filesList = os.listdir(dirPath)

          for fileName in filesList:
              #绝对路径
              fileAbsPath = os.path.join(dirPath,fileName)
              #判断是否是目录(文件夹),如果是进队,不是直接打印
              if os.path.isdir(fileAbsPath):
                  print("目录:"+fileName)
                  queue.append(fileAbsPath)
              else:
                  print("普通文件"+fileName)
getAllDirQu(r"G:\1806")



十四、模块(掌握)

  • 模块就好比一个工具包,要想使用这个工具包中的工具(函数),需要导入这个模块

优点:

1.提高代码的可维护性
2.提高代码的复用性,当一个模块定义完毕,可以被多个地方引用
3.引用其他的模块(内置模块,第三方模块)
注意:
   避免函数名和变量名的冲突

1 导入模块–import(掌握)

在python中用关键字import来引入模块,一般放在代码最前面

格式:
  import module1,module2....

当解释器遇到import 语句,如果模块在当前的搜索路径就会被导入

模块调用函数的基本格式:

模块名.函数名()

思考:

为什么必须加上模块名才能调用?
在多个模块中含有同名的函数,此时如果只是通过函数名来进行调用,解释器就无法知道到底需要调用哪个函数
如果使用import导入模块,在调用的时候必须加上模块名
import math
print(sqrt(2))#错误的
print(math.sqrt(2))

1.1 导入模块部分

使用from…import……导入模块的一部分

只需要用到模块中的某一个函数,此时只需要引入该函数即可,无需引入模块中的所有函数,浪费内存
格式:
from 模块名 import 函数名1,函数名2…

案例:

from  math import sin,cos
math.sin()#报错         	math未定义
sin()
cos()
sqrt()#报错				未导入sqrt函数

思考:
如果想要引入一个math模块中所有的函数

from math import *

1.2 导入模块所有函数

使用from…import * 导入模块所有的内容

from...import*:
把一个模块中所有的内容导入到当前的命名空间
格式:
   from  module import *

1.3 模块重命名import…as(掌握)

as 理解为重命名,将原有的名称替换成一个新的名字

作用:
​ 有时候导入的模块的名字很长或者很难记住简洁

格式:

import modName as newName
   import math as aa(#aa表示math)
import math as aa
math#报错
aa.sin()
aa.ceil()

注意:如果使用as将原有的模块名重命名,原先的将不可用

2 定位模块–搜索路径

当你导入一个模块,python的解释器对模块位置的搜索的顺序:
*	当前目录
*	如果不再当前的目录,python则搜索在shell变量的PYTHONPATH的每一个目录
*	模块的搜索路径存储在system模块的sys.path模块中变量,变量中包含当前的目录,
python path和由安装过程决定的默认的目录

pythonpath 变量----》环境变量

3 标准函数库中的模块

  • math
  • random,
  • os
  • 其他python中自带的标准函数库中的模块

4 使用自定义模块

有些时候,Python自带的模块不能很好的解决我们遇到的问题,我们需要自定义一些具有独特功能的模块来完成代码的编写

"""
求和函数
需要传递两个参数:
a:int
b : int
返回a+b的和的结果
"""
def add(a,b):
    return a + b

4.1 调用自定义模块(掌握)

import test
test.add(1,2)

4.2 测试模块

"""
求和函数
需要传递两个参数:
a:int
b : int
返回a+b的和的结果
"""

def add(a,b):
    return a - b

ret = add(1,-0)
print(ret)

为了解决测试的问题,python在执行一个文件时有个变量__name__
如果直接在test.py模块中可以将print进行修改
print()

if __name__ == "__main__":
     执行语句

5 包(掌握)

  • 定义:
    • 包-----》python中的python package------>文件夹----》容器
  • 问题1:
    • 为什么需要引入包?
      • 将有练习的模块放到一起(便于查找归纳整理)
  • 问题2:
    • 如何将有关系的模块联系到一起----》将其放入同一个文件夹
  • 问题3:
    • 放入到同一个文件夹后如何去导入?
  方式1:
  使用import关键字导入
  格式:
	import 文件.模块
	import day09.test
	# day09.test.add(1,2)
	day09.test.add(1,2)
方式2:
	使用from 文件夹 import 模块
	格式:
    from 文件夹的名字 import 文件名

	from day09 import test

	test.add(1,2)

包使用总结:

总结:
   包将有联系的模块组织在一起,放到同一个文件夹下,
在创建文件夹的时候会自动创建一个__init__.py文件,======》包

想一想

1. __init__.py文件有什么用?
   __init__.py控制着包的导入的行为
2.__init__.py文件为空?
仅仅是把包导入,不会导入该包中的模块

6 安装第三方模块(掌握)

  • https://pypi.org/
  • 不同系统的安装方式:
    • mac-------》无需安装
    • Linux------》无需安装
    • Windows–》pip
  • 比如:pygame 非常强大的游戏开发库

    格式:
    打开命令提示符
    DOS命令
    pip install 第三方的模块名(前提都是要求联网下载)

pip的安装:

pip的安装:
1.到https://pypi.python.org/pypi/pip   下载pip版本tar.gz,下载完成直接到本地解压
2.在DOS命令行进入pip解压的目录,输入python setup.py install进行安装
3.如果安装完成  提示finished   
4.如果出现问题提示pip没有找到该命令,可以将python/Script目录配置到path环境变量中

安装PTL

7 时间相关的模块(熟练)

1、time

import time

2、datetime

import datetime

3、calendar

import calendar

7.1 在python中表示时间

时间戳(timestamp):
	时间戳表示的是从1970年1月1日00:00:00,按秒计算偏移量
clock(),time()

print(type(time.time()))	#返回的是float
print(time.time())
print(time.clock())

7.2 格式化的时间字符串

%a	本地简化的星期的名称
%A	完整的星期的名称
%b	简化的月份的名称
%B	完整的月份的名称
%c	本地对应的日期表示和时间表示
%d	月内中的天数(0~31)
%H	24小时制小时数(0~23)
%m	月份(01~12)
%M	分钟数(00~59)
%w	星期(0~6) 星期天开始

元组:共有9中元素,返回的是struct_time的函数主要有gmtime(),localtime(),strptime()

索引   属性         	值
0     tm_year(年)      2018
1     tm_mon(月)       1~12
2     tm_mday(日)      0~31
3     tm_hour(时)      0~23
4     tm_min(分钟)     0~59
5     tm_sec(秒)       0~61
6     tm_wday(weekday)   0~6(0表示周日) 
7     tm_yday(一年中的第几天)   1~366
8     tm_isdst(是否是夏令时)   默认为-1

UTC :世界协调时间  格林威治天文时间  世界标准时间
	 在中国UTC+8

#localtime():获取当前时间,返回struct_time格式返回
#获取当前的时间

# print(time.localtime())

7.3 获取当天的时间和日期

# 获取当天的时间
print(datetime.datetime.now())
# 当前的日期
print(datetime.date.today())
# 获取昨天的时间
def getYesterday():
    today = datetime.date.today()
    oneday = datetime.timedelta(days=1)
    yesterday = today - oneday
    print(type(today))
    print(type(yesterday))
    return yesterday
yesterday = getYesterday()
print(yesterday)

#获取日历相关的信息

#获取某个月的日历
# 格式:calendar.month(x,y)x:显示的年份,y
# 显示的月份
cal = calendar.month(2015,12)
print(cal)
#设置日历的第一天
calendar.setfirstweekday(calendar.SUNDAY)
cal = calendar.month(2015,12)
print(cal)

#获取某一年的日历:
cal = calendar.calendar(2015)#参数为具体的年份
print(cal)
cal = calendar.HTMLCalendar(calendar.MONDAY)
print(cal.formatmonth(2015,12))

十五、面向对象思想

1 面向对象的思想

思考:
   请用程序描述如下事件:
      A同学报道等级信息
      B同学报道等级信息
      C同学报道等级信息
      A同学做自我介绍
      B同学自我介绍
      c同学自我介绍
"""
请用程序描述如下事件:
      A同学报道等级信息
      B同学报道等级信息
      C同学报道等级信息
      A同学做自我介绍
      B同学自我介绍
      c同学自我介绍
"""
stu_a = {"name":"A","age":21}
stu_b = {"name":"B","age":22}
stu_c = {"name":"C","age":23}

def stu_infor(stu):
    for key,value in stu.items():
        print("key = %s,value = %d"%(key,value))

"""

2 面向过程:

根据业务逻辑从上到下写代码

3 面向对象:

将数据与函数绑定到一起,进行封装,能够更快速的开发程序,减少代码的重写的过程
def 发送邮件(内容):
    # 连接邮箱服务器
    # 发送邮件
    # 关闭连接

4 类和对象(掌握)

  • 类和对象的概述

4.1 对象和类

对象是面向对象思想的核心
在使用对象的过程中,为了将具有共同特征和行为的一组对象抽象定义-----》类
类---》制造飞机的图纸
用它来创建的飞机就相当于对象

4.2 类

具有相似的内部状态和运动规律的实体的集合(抽象)
或者具有相同的属性和行为的统称

定义:
  类  抽象的  在使用的时候通常会找到这个类的具体的存在----》对象
  特点:
     使用这个具体的存在,一个类可以找到多个对象

4.3 对象

概述:
   某一个具体事物的存在,在现实世界中可以看得见摸得着
可以直接使用

总结:
  类和对象之间的关系:
     就像利用玩具模型来创建多种不同的玩具
     类就是创建对象的模板

4.4 区分类和对象

奔驰汽车   类
奔驰smart   类
张三的那辆奔驰smart    对象

狗    类
大黄狗   类
李四家的那只大黄狗    对象

水果    类
苹果   类
红苹果   类   红富士苹果   类
张三嘴里吃了一半的苹果   对象

5 类的构成(掌握)

5.1 类的构成
类(class):由3部分组成
类的名称:类名
类的属性:一组数据
类的方法:允许对其操作的方法(行为)
5.2 设计一个人 类
"""
事物的名称(类名):人(Person)
属性:身高  年龄
方法(行为):跑,吃饭

"""
"""
狗  类
类名:dog
属性:品种,毛色,性别,腿的数量
方法:叫,跑,咬人,摇尾巴
"""

6 类的抽象(掌握)

如何把日常生活中的事物抽象成程序中的类?

类:
    拥有相同属性和行为的对象可以抽取出来-----》类
    
一般名称提炼法
例如:
 1.坦克发射了3颗炮弹炸掉了2架飞机
 坦克----》抽象成类
 炮弹---》抽象成类
 飞机----》抽象成类
 
 2.小明在公车上牵了一条叼着热狗的狗
 小明  -----》	人类
 公车  -----》	交通工具类
 热狗  -----》	食物类
 狗    -----》	狗类

游戏中的类和对象

cf
人
枪

植物大战僵尸:
向日葵   -----》类
    类名:xrk
    属性:颜色,尺寸
    行为:产生阳光
    
豌豆:   ------》   类
    类名:  wd
    属性:颜色,发型
    行为:发射炮弹  
僵尸:
    类名:js
    属性:颜色,
    行为:走,吃植物,啃

7 定义类(掌握)

7.1 定义一个类的格式:

class 类名:
	属性1
	属性2
	属性3
	... ...

	方法1
	方法2
	方法3
	... ...
7.1.1 定义类–猫
"""
猫:
   类名:cat
   属性:毛色,性别
   行为:跑,吃
"""
class Cat:
    #属性

    #方法
    def eat(self):
        print("猫吃鱼....")

    def drink(self):
        print("猫喝可乐....")
7.1.2 定义类–车

"""
车:
   类名:Car
   属性:颜色,
   行为:跑
"""
class Car:
    #方法列表
    def getCarInfo(self):
        print("车的轮子数:%d,颜色%s"%())

    def move(self):
        print("车子在移动....")

8、经典类和新式类

8.1 新式类:
* Python3.X之后对类的定义方式进行了改变
* 在类名后面(object),Car(object)
  • 说明:
    • 定义类的时候有两种,新式类和经典类,上面定义Car为经典类
    • 如class Car(object): 是新式类
    • class Cat: 是经典类

注意:
定义类名时,尽量使用大驼峰命名法则

9 创建对象(掌握)

python中,可以根据已经定义好的类来创建一个一个的对象

  • 创建对象的格式:对象名 = 类名()
9.1 创建一个Car类

#创建一个Car类
class Car(object):
    def move(self):
        print("车子在移动....")
    def toot(self):
        print("车子在鸣笛....")
#创建车子的对象,并用变量进行保存
BMW = Car()
BMW.color = "黑色"#车子的颜色
BMW.wheelNum = 4#车轮的数量
BMW.color = "白色"
BMW.move()
BMW.toot()
print(BMW.color)
print(BMW.wheelNum)
9.2 总结:
BMW = Car():这样就产生了一个Car的实例对象,
此时可以通过实例对象BMW访问属性和行为
BMW--->对象,它拥有属性和行为
9.3 为对象添加属性
  • 下面以Cat类为例子,添加属性

    class Cat:

    def eat(self):
        print("猫在吃鱼.....")
    def drink(self):
        print("猫在和芬达....")
    创建一个Cat对象
    tom = Cat()
    调用tom指向的对象中的方法
    tom.eat()
    tom.drink()
    tom.name = "汤姆"
    tom.age = 3
    
9.4 获取对象的属性
class Cat:
    def eat(self):
        print("猫在吃鱼.....")
    def drink(self):
        print("猫在和芬达....")

#创建一个Cat对象
tom = Cat()
#调用tom指向的对象中的方法
tom.eat()
tom.drink()
tom.name = "汤姆"
tom.age = 3
print("tom的中文名:%s,年龄:%d"%(tom.name,tom.age))

__10 init__方法和self的作用

init方法是初始化函数,用来完成一些对象默认的设置

init方法格式

class 类名:
     #初始化函数,用来完成一些默认的设置
     def __init__(self):
            函数体语句

init()方法调用

下面以汽车类Car示例init方法的调用

10.1 第一种方式

class Car:

# 初始化方法
def __init__(self):
    self.color = "黑色"
    self.wheelNum = 4

# 普通的方法,移动
def move(self):
    print("车子在移动.....")

10.2 创建对象

bmw = Car()
print(“车子的颜色:%s” % bmw.color)
print(“车子的轮子数:%d” % bmw.wheelNum)
bmw1 = Car()
print(“车子的颜色:%s” % bmw1.color)
print(“车子的轮子数:%d” % bmw1.wheelNum)

总结:
当创建Car对象后,在没有调用__init__()函数的前提下,
bmw就默认拥有了两个属性color/wheelNum,
原因是__init__()函数在创建对象后,就立刻默认被调用


  • 还有另一种方式能更灵活的使用init方法

    第二种方式

    class Car:
        #初始化方法
        def __init__(self,newWheelNum,newColor):
            self.wheelNum = newWheelNum
            self.color = newColor
        #普通的方法,移动
        def move(self):
            print("车子在移动.....")
    #创建对象
    bmw = Car(4,"黄色")
    print("车子的颜色:%s"%bmw.color)
    print("车子的轮子数:%d"%bmw.wheelNum)
    bmw1 = Car(6,"绿色")
    print("车子的颜色:%s"%bmw1.color)
    print("车子的轮子数:%d"%bmw1.wheelNum)
    

总结:
init():在创建一个对象的时候默认被调用,不需要手动调用
init(self),默认一个参数名字为self,不需要开发者传递
python 解释器会自动将当前的对象的引用传递进来


11 del()方法(析构方法)

  • 创建对象后,python解释器默认调用__init__()
  • 当删除一个对象的时候,python解释器也会默认调用__del__()

分析下面案例

import sys
class Cat(object):
    def __init__(self):
        self.color = "while"
        self.weight = "8斤"

    def __del__(self):
        print("所有对象被干掉啦")

    def __str__(self):
        return ("颜色%s-体重%s" % (self.color, self.weight))
Tom01 = Cat()
print("Tom01即将被干掉,当前Tom01引用指向地址被引用数量%s" % sys.getrefcount(Tom01))
Tom02 = Tom01
Tom03 = Tom02
print(Tom01)
print(Tom02)
print(Tom03)

print("Tom01即将被干掉,当前Tom01引用指向地址被引用数量%s" % sys.getrefcount(Cat))
print(id(Cat))
del Tom01

print("Tom02即将被干掉,当前Tom02引用指向地址被引用数量%s" % sys.getrefcount(Tom02))
print("Tom02即将被干掉,当前Tom03引用指向地址被引用数量%s" % sys.getrefcount(Tom03))
print("Tom02和Tom03引用指向地址是相同的吗?", Tom02 == Tom03)
del Tom02
print("Tom02被干掉啦")

# del Tom03
# print("Tom03被干掉啦")
print("我是程序结尾的一句话")
print("-" * 30)

print(Tom03)
print(repr(Tom03))
print(eval(repr(Tom03)))

总结

  • 当有1个变量保存了对象的引用,此时对象的引用计数加1
  • 当使用__del__()函数的时候,删除的是变量指向的对象时,
  • 如果对象的引用计数不为1,比如3,那么此时只会让这个引用计数减1
  • 即变为2,当再次调用del 此时会通用删除引用计数,直到变量的引用计数为0
  • 此时才会将变量指向的对象真正删除
  • 获取对象计数:sys.getrefcount(object))

12 创建多个对象(掌握)

==同一个类可以创建多个对象,==比如常见的猫有加菲和Tom

class Cat:
    def eat(self):
        print("猫吃鱼....")
    def drink(self):
        print("猫喝水....")
  
#创建tom 对象       
tom = Cat()
tom.eat()
tom.drink()
#给tom指向的对象添加两个属性
tom.name = "汤姆"
tom.age = 2
jiafei = Cat()
jiafei.eat()
jiafei.drink()
jiafei.name = "加菲"
jiafei.age = 3

同意个类创建的多个对象是相互独立的

13 魔方方法(掌握)

  • 魔方方法:

    • 魔法方法是Python中的特殊方法
    • 魔方方法是指指被包含下划线的方法或者所能调用的方法的统称
    • 这些统方法在特殊的情况下被调用,并且基本没有手动调用它的必要

      下面我们看一下使用Cat类编写的案例

    定义类

    class Car:

    def __init__(self,newWheelNum,newColor):
        self.wheelNum = newWheelNum
        self.color = newColor
    
    def __str__(self):
        msg = "嘿嘿....我的颜色是"+self.color+"我有"+self.wheelNum+"个轮子"
        return msg
    
    def move(self):
    
        print("车子在移动....")
    
    

    创建一个对象

    bmw = Car("4","白色")
    print(bmw)
    

总结:
在python中方法名如果是__XXX__那么就具有特殊的功能,—》魔方
str():
当使用print输出对象,只要定义了__str__()方法,
那么就会返回这个方法中return 的数据


14、str__和__repr()(掌握)

A:str__和__repr()

  • repr()与__str__()函数的功能类似
  • str()用于将数值转化为人阅读的形式
  • repr()转化为python解释器读取的形式

str():在调用print打印对象的时候自动调用,给用户用的,是一个描述对象的方法
repr():给机器用的,供python的解释器读取

注意:
在没有__str__()函数时,有__repr__(),str == repr

import datetime

now = datetime.datetime.now()
print(str(now))
print(repr(now))
print(eval(repr(now)))

B:说明:

datetime python的内置模块,import 加载导入模块
now = datetime.datetime.now()系统当前的时间赋值给now变量
eval函数是把参数当做代码执行,验证repr之后的字符串可以被python识别执行


class Person(object):
    def __init__(self,name,age,height,weight):
        self.name = name
        self.age = age
        self.height = height
        self.weight = weight
    def __str__(self):
        return "%s-%d-%d-%d"%(self.name,self.age,self.height,self.weight)

#创建人的对象
per = Person("hanmeimei",20,170,55)

print(per)
print(repr(per))
# print(eval(repr(per)))#eval函数中的参数为一个字符串,如果不是一个字符串会报错
aa = "hello"
print(repr(aa))
print(eval(repr(aa)))

C:优点:

当一个对象的属性过多,并且还要打印,重写__str__()方法简化代码的书写
可读性强


D:注意:

repr()函数得到的字符串,通常可以用来获得该对象,obj == eval(repr(obj))这个等式是成立的
返回的是一个字符串


15 构造方法(掌握)

定义:

  • 构造方法类似__init__()函数,差别在于一个对象被构建好之后会自定调用该方法

    • python中创建一个构造方法(使用__init__())

      class Cat:
      def init(self):

        初始化属性
      
      

16 重写__init__()和__str__()方法

16.1 概述:

  • Python中所有的类都直接或间接继承object
  • object中有__init__()和__str__()方法
  • object中的这两个方法大部分时间和我们使用时的需求不匹配
  • 我们可以根据自己的需求对方法体进行更改,这就叫做重写
  • 更多内容在明天的知识点继承中

16.2 重写方法使用总结:

  • 当两个关联的类,出现了相同的函数名,在调用该函数时,先在本类中找,
  • 如果有,调用
  • 如果没有,在去父类找,如果有调用,
  • 如果没有,去基类,找不到报错

重写对于类很重要:
尤其对于构造 init

class Bird():
    def __init__(self):
        self.hungry = True

    def eat(self):
        if self.hungry:
            print(".....")
            self.hungry = False
        else:
            print("no thanks")
b = Bird()
b.eat()
b.eat()

16.3 重写的定义:

在子类中定义了一个和父类同名的函数—》重写

17 理解self(掌握)

#定义一个类
class Animal:
    def __init__(self,name):
        self.name = name
    def printName(self):
        print("名字为:%s"%self.name)

#定义一个函数
def myPrint(animal):
    animal.printName()

#创建对象
dog1 = Animal("西西")
myPrint(dog1)

dog2 = Animal("北北")
myPrint(dog2)

  • 总结:
* 所谓self理解为自己,也就是对象自身
* 程序中的self是什么?哪个对象调用了__init__(),self就代表谁

18 应用-烤牛排(掌握)

"""
烤牛排:
类:
    类名:
        牛排:
    属性:
        几成熟
            0--3表示生的,4--6表示半生不熟,7--9表示熟了,10及以上表示糊了
        红酒
        胡椒
        ... ...
    行为:
        烧烤时间
        添加佐料
        __init__()
        __str__()

	"""

class CookSteak:
    def __init__(self):
        self.time = 0
        self.cook_level = 0
        self.cook_string = "生的"
        self.condiments = []

    def cook(self, time):
        self.cook_level += time
        if self.cook_level > 9:
            self.cook_string = "扔了吧,都糊啦"
        elif self.cook_level > 6:
            self.cook_string = "熟了,味道应该很棒"
        elif self.cook_level > 3:
            self.cook_string = "半生不熟,快要熟了"
        elif self.cook_level > 0:
            self.cook_string = "牛排刚放进去,耐性等一会"
        else:
            print("没有这个状态")
        print("牛排已经烤了很久了,现在达到%s成熟了," % self.cook_level)

    def add_cendiments(self, cendiments):
        self.condiments.append(cendiments)

    def __str__(self):
        return "牛排已经烤了很久了,现在达到%s成熟了,添加的佐料有%s" % (self.cook_level, self.condiments)

hui_ling_dun = CookSteak()
hui_ling_dun.cook(1)
hui_ling_dun.cook(1)
hui_ling_dun.cook(1)
hui_ling_dun.cook(1)
hui_ling_dun.add_cendiments("胡椒粉")
hui_ling_dun.cook(1)
hui_ling_dun.cook(1)
hui_ling_dun.add_cendiments("红酒")
hui_ling_dun.cook(1)
print(hui_ling_dun)

19 访问限制(掌握)

  • 如果有一个对象,当需要对其进行修改属性:

    • 方法2种

    • 直接修改 对象名.属性名 = 数据

    • 间接修改 对象名.方法名()

      将属性定义为私有
      格式:
      __属性名

19.1 属性私有案例

# 定义一个类
class Person(object):
    def __init__(self, name):
        self.__name = name

    def __str__(self):
        return self.__name

    def getName(self):
        return self.__name

    def setName(self, newName):
        if len(newName) <= 5:
            self.__name = newName
        else:
            print("名字的长度需要小于等于5")

person = Person("张三")
# print(person)
# #直接修改   对象名.属性名 = 数据
# person.__name = "李四"
# print(person)

# 间接访问   对象名.属性名
# print(person.__name)  #报错

person.setName("李四")
print(person.getName())

person.setName("王五")
print(person.getName())

  • python没有c++或者Java中的public(公有) private(私有)区分公有和私有
  • python以属性的命名方式来进行区分:
    • 如果在属性名前面加上两个下划线“__”,则表明该属性是私有属性
    • 否则就是公有属性(方法的设置同属性设置一致)

19.2 set()和get()方法(掌握)

  • Python私有属性修改
    • 类中的属性私有化之后,外部无法访问
    • 我们可以在类中定义公共的方法提供给外部,让这个公共的方在类内部修改私有属性
      set()和get()使用案例:

class Person(object):
    def __init__(self,name,age,height,weight,money):
        self.name = name
        self.__age__ = age
        self.height = height
        self.weight = weight
        self.__money = money

    def ss(self):
        print(self.__money)

    #通过内部的方法,去修改私有属性
    #通过自定义的方法实现对私有属性的修改
    def getMoney(self):
        return self.__money
    def setMoney(self,money):
        #数据的过滤
        if money < 0:
            money = 0
        self.__money = money

#创建对象
person = Person("张三",12,170,55,100)
# person.age = 15
# person.setMoney(200)
# print(person.getMoney())

# print(person.__money)#外部使用  不ok
print(person.ss)#内部  ok

思考,不能通过对象访问私有属性?
在python的解释器把__money 变成_Person_money.
任然可以使用_Person_money去访问,但是不建议这么做,


"""
person._Person__money = 1
print(person.getMoney())

print(person.__age__)
"""
在python中__XXX__,属于特殊的变量,可以直接访问(公有)
"""

20 继承的介绍(掌握)

  • 继承的概念:

    • 在现实生活中,一般指子女继承父辈的财产
  • 程序中的继承:

    • 继承描述的是事物之间的所属关系,之前的猫,狗----》动物

    • 程序中可以描述猫和狗继承动物

      object
          		动物
      
       猫               狗
      

      加菲 波斯 金毛 二哈

21 单继承(掌握)

  • 生活中的单继承:
    • 孩子只能有一个亲生父亲或者母亲
  • 程序中的单继承:
    • 子类只能有一个父类–》子类只能继承一个父类
21.1 单继承案例:

# 定义一个父类
class Cat(object):
    def __init__(self, name, color):
        self.__name = name
        self.color = color

    def run(self):
        print("%s----在跑" % self.__name)
# 定义一个子类
class Bosi(Cat):
    def setNewName(self, newName):
        self.__name = newName

    def eat(self):
        # print("%s---在吃饭"%self.__name)
        pass
bs = Bosi("波斯", "白色")
# print(bs.__name)
print(bs.color)
bs.eat()

bs.setNewName("加菲")
bs.eat()
bs.run()

说明:

虽然在子类中没有定义__init__()方法
但是父类有,在子类继承父类的时候这个方法也就被继承过来
创建Bosi对象,默认执行那个继承过来的__init__方法


总结:

子类在继承的时候,在定义类的时候,小括号中为父类的名字
父类的公有属性和公有方法会被子类继承


21.2 再赠送一个案例

print("父类中出现私有的情况")
# 定义一个父类
class Animal(object):
    def __init__(self, name="动物", color="白色"):
        self.__name = name
        self.color = color

    def __test(self):
        print(self.__name)
        print(self.color)

    def test(self):
        print(self.__name)
        print(self.color)
# 定义一个子类
class Dog(Animal):

    def Test1(self):
        # print(self.__name)#不能访问父类的私有属性
        print(self.color)

    def dogTest2(self):
        # self.__test()#不能访问父类的私有方法
        self.test()
a = Animal()
# print(a.__name)#报错,不能通过对象访问私有属性
# a.__test()#报错,不能访问私有方法
a.test()
print("--------")

d = Dog(name="小花狗", color="黄色")
print(d.color)
d.Test1()
d.dogTest2()

总结:

私有的属性,不能通过对象直接访问,可以通过方法进行访问

私有方法,不能通过对象直接访问

私有属性,方法都不会被子类继承,也不能被访问

子类继承的是父类公有是属性和方法


22 多继承(掌握)

  • 生活中的例子:

    • 骡子是马和驴的杂交品种
  • 程序中的多继承:

    • 一个子类有多个父类,并且据有他们的特征,这被称为多继承

    定义一个父类

    class A:

    def printA(self):
        print("----A-----")
    
# 定义一个父类
class B:
    def printB(self):
        print("----B-----")
# 多继承
class C(A, B):
    def printC(self):
        print("----C-----")
# 创建C的对象
c = C()
c.printA()
c.printB()
c.printC()

说明:

python中可以多继承

父类中的方法和属性,子类会继承


22.1 多个父类中出现相同的方法案例:

print("多个父类中出现相同的方法")

# 如果父类A和B,有一个同名的方法,
# 那么子类在调用方法的时候,执行哪个父类中的方法
# 定义一个父类
class A:
    def printA(self):
        print("----A-----")
# 定义一个父类
class B:
    def printA(self):
        print("----B-----")
# 多继承
class C(A, B):
    pass
c = C()
c.printA()

print(c)
# 案例:
class base(object):
    def test(self):
        print("base--test")
class D(base):
    def test(self):
        print("D----test")
class E(base):
    def test(self):
        print("E----test")
class F(D, E):
    pass
f = F()
f.test()
print(F.__mro__)  # 可以查看类的对象搜索方法时的先后顺序

练习:

有一个学校,人数为0,入职的老师和学生,人数增加1,
老师要显示姓名和工号,学生要显示姓名和成绩

使用继承<br>
父类   学校<br>
子类   老师   学生

22.2 参考代码:

print("练习题")

# 学校类
class School:
    # 定义默认的人数为0
    schoolNum = 0

    # 初始化数据
    def __init__(self, name):
        self.name = name
        School.schoolNum += 1
        print("学校新加入的成员:%s" % self.name)
        print("学校现有的学生的人数%s" % School.schoolNum)

    # 自我介绍,姓名和工号,成绩
    def sayHello(self):
        print("我叫%s" % self.name)
# 创建老师类
class Teacher(School):
    def __init__(self, name, id):
        a = School(name)
        self.name = name
        self.id = id

    def sayHello(self):
        print("我叫%s,工号为%d" % (self.name, self.id))
# 学生类
class Student(School):
    def __init__(self, name, result):
        self.name = name
        self.result = result
        b = School(name)

    def sayHello(self):
        print("我叫%s,成绩:%d" % (self.name, self.result))
# 创建老师对象
t = Teacher("小明", 1000)
t.sayHello()
s = Student("张三", 99)
s.sayHello()

23 重写和调用父类的方法

  • 重写:
    • 就是子类中,有一个和父类相同名字的方法,在子类中的方法会覆盖父类中的方法
23.1 重写父类方法
#定义一个父类
class Cat(object):
    def sayHello(self):
        print("hello----1")
#定义子类
class Bosi(Cat):
    def sayHello(self):
        print("hello -------2")
#创建子类的对象
bs = Bosi()
bs.sayHello()

想一想:要求打印出hello ------1,该如何实现

23.2 调用父类属性

class Cat(object):
    def __init__(self, name):
        self.name = name
        self.color = "yello"

class Bosi(Cat):
    def __init__(self, name):
        self.name = name
        # 方式1调用父类__init__方法,python2中/python3中
        # Cat.__init__(self,name)
        # 方式2:super(),可以完成对父类__init__()的调用
        # super(Bosi,self).__init__(name)
        # 方式3:super()直接调用__init__()函数
        super().__init__(name)

# super()#一层一层向上
bosi = Bosi("xiaoming")
print(bosi.name)
print(bosi.color)

24 多态(掌握)

  • 多态:
    • 定义的类型和运行时的类型不一样----》多态
  • Python并不支持真正的多态
  • Python中使用伪代码来实现多态

Python多态案例:

class F1(object):
    def show(self):
        print("F1.show")

class S1(F1):
    def show(self):
        print("S1.show")
class S2(F1):
    def show(self):
        # super().show()
        print("s2.show")
        # F1.show(self)
        # super(S2,self).show()

# python  动态的言语

def func(F1):
    print("func接受一个数据类型")
    # print(F1.show())
# func(F1)

# s1 = S1()
# s1.show()
s2 = S2()
s2.show()

25 类属性和实例属性

概述:

类属性就是类对象所拥有的属性,它被所有类对象的实例对象所公有
类属性在内存中只存一个副本对于公有类属性和实例属性在类的外面可以直接被访问

25.1 类属性
  • 类属性:

    • 在类中定义的属性(公有和私有)
      类属性案例:

    定义一个类:

    class People(object):

    name = "xiaoming"  # 公有的属性
    __age = 12  # 私有属性
    
    
# 创建People类的对象
p = People()
print(p.name)  # ok
print(People.name)  # ok
# print(p.__age)    #no ok   不能在类外面通过实例对象访问类的私有属性
print(People.__age)  # no  ok   不能通过类对象访问私有属性

25.2 实例属性

# 定义类
class People(object):
    address = "北京"

    def __init__(self):
        self.name = "xiaoming"  # 实例属性
        self.age = 12  # 实例属性

p = People()
p.age = 20
print(p.age)
print(p.name)
print(p.address)

print(People.address)
# print(People.name)   #类对象访问实例属性
# print(People.age)   #类对象访问实例属性

25.3 实例对象去修改类属性

print("@" * 20)

class People(object):
    country = "china"

    def __init__(self):
        self.name = "hhaa"

print(People.country)
p = People()
print(p.country)
p.country = "chinese"  # 实例属性会屏蔽同名的类属性
print(p.country)
print(People.country)

del p.country
print(p.country)

25.4 总结

如果需要在类外修改类属性,必须通过类对象去引用再进行修改
如果通过实例对象去引用,会产生一个同名的实例属性,
这个方式其实是修改实例属性,不会影响类属性,
并且之后如果需要通过实例对象去引用该同名的属性,
实例属性会强制屏蔽类属性,即引用的是类属性,除非删除该实例属性

26 静态方法和类方法

26.1 类方法

类方法:

类对象所拥有的方法,需要使用到修饰器 @classmethod---->类方法

对于类方法,第一个参数必须是类对象,一般以cls表示作为第一个参数

(当然可以用其他的名字,但是不建议修改)

class People(object):
    country = "china"

    @classmethod
    def getCountry(cls):
        return cls.country

p = People()
print(p.country)
print(p.getCountry())		#通过实例对象进行访问
print(People.country)
print(People.getCountry())  # 通过类对象去引用

print("#" * 20)

class People(object):
    country = "china"

    # 类方法
    @classmethod
    def getCountry(cls):
        return cls.country

    @classmethod
    def setCountry(cls, country):
        cls.country = country

p = People()
print(p.getCountry())  # 可以用实例对象引用
print(People.getCountry())  # 通过类对象的的引用

p.setCountry("chinese")
print(p.getCountry())
print(People.getCountry())

26.2 作用:
  • 类方法可以对类属性进行修改
  • 发现规律:
    • 结果显示在用类方法对类属性进行操作修改之后,通过类对象和实例对象访问都发生了变化
26.3 静态方法
  • 定义:
    • 需要通过修饰器@staticmethod来进行修饰,不需要传参数

print("#" * 20)

class People(object):
    country = "china"

    # def getCountry(self):
    #     return " "
    @staticmethod
    def getCountry():
        return People.country

print(People.getCountry())
p = People()
print(p.getCountry())

26.4 总结

从类方法和实例方法(普通方法)和静态方法
类方法第一个参数是类对象cls,那么通过cls的引用必定是类对象的属性和方法
实例方法第一个参数self,自身,那么通过self引用的可能是类属性,也可以是实例属性(具体分析)

问题?
如果出现相同名称的类属性和实例属性
实例属性优先级更高
静态方法:静态方法中不需要传递任何参数(额外的定义参数),
在静态方法中的引用是类属性,必须通过类对象来引用

print("*" * 30)

import types

class Person(object):
    def __init__(self, name=None, age=None):
        self.name = name
        self.age = age

    def eat(self):
        print("吃饭....")

def run(self, speed):
    print("%s在移动,速度%s" % (self.name, speed))

P = Person("小王","24")
# P.run("220")

P.run = types.MethodType(run,P)#第一个参数L:需要添加的方法,参数二:添加到该类的实例对象
P.run("100")

运行结果:
******************************
小王在移动,速度100

十六、元类

python中的类,类同样也是一种对象,只要使用关键字class

1、创建一个对象

python解释器在执行的时候会创建一个对象

class Test(object):
    pass

test = Test()
print(test)#结果为类创建对象在内存中的地址

判断一个对象是否在某个类中–hasattr(obj,str)

class Test(object):
    pass

test = Test()
print(test)
print(Test)

def info(o):
    print(o)
#可以将类作为参数传递函数
info(test)
#可以为类添加新的的属性
print(hasattr(Test,"new_attribute"))
Test.new_attribute = "haha"
print(hasattr(Test,"new_attribute"))
print(Test.new_attribute)

#将一个类赋值给一个变量
test1 = Test
print(test1)

2 动态创建类 (熟练)

2.1 动态创建类

def choose_name(name):
    if name == "haha":
        class haha(object):
            pass
        return haha
    else:
        class heihei(object):
            pass
        return heihei
myClass = choose_name("haha")
print(myClass)#函数返回的haha --->  类,不是类的实例
print(myClass())#返回类创建的实例,也是对象

python中的内联函数type()

print(type(1))
print(type("1"))
print(type(choose_name("haha")))#类的类型  返回值-->type

2.2 type创建类(熟练)

  • 动态创建类
    • 格式:
      • type(类名,由父类名称组成的元祖(针对继承的情况,可以为空),包含属性的字典(名称和值))

type创建类案例:

Test01 = type("Test01", (), {})
print(Test01)
print(Test01())	

输出结果:
<class '__main__.Test00'>
<__main__.Test00 object at 0x000001360A04C160>

结果:显示和我们学习的类具有一样类型的内存地址

2.3type函数创建带有属性的类

  • type接受一个字典来定义类的属性
  • type(“类名”,(),{“name”:“zhangsan”})

type创建有内容的类

Test01 = type("Test01", (), {"name": "hello", "age": 18})
print(Test01)
print(Test01())
print(Test01().name)
print(Test01().age)

输出结果:
<class '__main__.Test01'>
<__main__.Test01 object at 0x0000025B5773B860>
hello
18

3 type创建带继承关系类

Test01 = type("Test01", (), {"name": "hello", "age": 18})
print(Test01)
print(Test01())
print(Test01().name)
print(Test01().age)
Test02 = type("Test02", (Test01,), {})
print(Test02)
print(Test02())
print(Test02.__mro__)

输出结果:
<class '__main__.Test02'>
<__main__.Test02 object at 0x000002BBD33FBA58>
(<class '__main__.Test02'>, <class '__main__.Test01'>, <class 'object'>)

注意:

type函数中有三个参数,字符串是类名,元祖中是父类的名字,字典中添加属性<br/>
添加的属性是类属性,不是实例属性<br/>
添加的方法可以使普通方法,静态方法,类方法<br/>

4 type动态创建带方法的类

4.1 type添加实例方法

1,添加实例方法
Test01 = type("Test01", (), {"name": "hello", "age": 18})
print(Test01)
print(Test01())
print(Test01().name)
print(Test01().age)
def test(self):
    print("haha")
Test02 = type("Test02", (Test01,), {"test": test})
print(Test02)
print(Test02())
print(Test02().test)
# demo02 = Test02().
Test02().test()
print(Test02.__mro__)

4.2 type添加静态方和类方法

1,添加静态方法
@staticmethod
def test03():
    print("hahaha--test03")
    return "test03"
Test003 = type("Test003", (Test01,), {"test03": test03})
print(Test003)
print(Test003().test03())

2,添加类方法
@classmethod
def test04(cls):
    print("hahaha--test04")
    return "test04"
Test004 = type("Test004", (Test01,), {"test04": test04})
print(Test004)
print(Test004().test04())

总结:

元类是创建类所需要的事物,你创建类就是为了创建类的实例对象

python中类也是对象

元类:就是用来创建这些类(对象)的类----》元类

myclass = myclass()#使用元类长创建一个对象,这个对象称之为类

myobject = myclass()#使用类创建畜类的实例对象

type实际上就是一个元类,是python在幕后创建所有类的元类

5 class(掌握)

class可以查看元素、对象所属的类,功能和type相似

print("-" * 30)
age = 35
print(age.__class__)
name = "zhangsan"
print(name.__class__)
def test():
    pass
print(test.__class__)  # function

class demo:
    pass
print(demo.__class__)  # type
print(age.__class__.__class__)  # type
print(name.__class__.__class__)

输出结果:
------------------------------
<class 'int'>
<class 'str'>
<class 'function'>
<class 'type'>
<class 'type'>
<class 'type'>

6 python是动态语言(掌握)

6.1 动态语言的定义

  • 变量可以任意更改,不用考虑类型
  • 类可以当做参数传递
  • 方法,函数可以动态添加到类中
  • 属性可以动态添加到类中
  • 。。。 。。。

6.2 运行中给对象添加属性

class Person(object):
    def __init__(self, name=None, age=None):
        self.name = name
        self.age = age
P = Person("小明", "22")
P.sex = "male"
print(P.sex)

输出结果:
male

6.3 运行过程中给类绑定属性

class Person(object):
    def __init__(self, name=None, age=None):
        self.name = name
        self.age = age
p = Person("小丽", "23")
Person.sex = None
print(p.sex)

总结:

运行中给对象绑定属性-----》直接通过实例对象设置

运行中给类绑定属性-----》直接通过类对象设置

7 运行中给类绑定方法

7.1 type动态添加方法

print("-" * 30)
class Person(object):
    def __init__(self, name=None, age=None):
        self.name = name
        self.age = age

    def eat(self):
        print("吃饭....")

def run(self, speed):
    print("%s在移动,速度%s" % (self.name, speed))

p = Person("老王", 23)
p.eat()

# p.run()
person = type("person", (Person,), {"run": run})
P = person("小王", "24")
P.run("220")

输出结果:
------------------------------
吃饭....
小王在移动,速度220

7.3 types动态添加方法

	print("*" * 30)
	
	import types

	class Person(object):
	    def __init__(self, name=None, age=None):
	        self.name = name
	        self.age = age
	
	    def eat(self):
	        print("吃饭....")

	def run(self, speed):
	    print("%s在移动,速度%s" % (self.name, speed))
	
	P = Person("小王","24")
	# P.run("220")
	
	P.run = types.MethodType(run,P)#第一个参数L:需要添加的方法,参数二:添加到该类的实例对象
	P.run("100")

	运行结果:
	******************************
	小王在移动,速度100

#### 动态添加一个静态方法
#	
	# 定义一个类方法
	@classmethod
	def testClass(cls):
	    cls.num = 150
	
	
	# 定义一个静态方法
	@staticmethod
	def testStatic():
	    print("----static method-----")
	P = Person("老王",22)
	Person.testClass = testClass    # 把静态方法加入到类中
	Person.testClass()              # 调用类的静态方法,执行方法中的方法体
	print(Person.num)               # 输出调用内容
	
	print("$" * 30)
	# 添加静态方法
	Person.testStatic = testStatic
	Person.testStatic()
	
	输出结果:
	******************************
	150
	$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
	----static method-----





## 13.10_Python语言基础(运行过程中删除属性和方法)(熟练)


* 删除的方法:
   * del  对象.属性名
   * delattr(对象,"属性名")



## 13.11_Python语言基础(__slots__)(熟练)

* 动态语言:可以在运行的过程中,修改带啊没
* 静态语言:便编译时已经确定的代码,运行的时候不能修改

* 如果我们想要限制实例属性?
    * 允许对Person实例中添加name和age属性,
    * python允许再买定义class的时候,定义一个特殊的变量----__slots__
    * __slots__能限制class能够添加的属性 
    
#
	class Person(object):
	    __slots__ = ("name", "age")
	
	P = Person()
	P.name = "老王"
	P.age = 80
	
	
	# P.sex = "male"
	# 试一试这个限制是否对子类起作用
	class Demo(Person):
	    pass
	
	d = Demo()
	d.sex = "male"


>**注意:**<br/>
    使用__slots__定义的属性仅对当前类实例起作用,对继承的子类不起作用
***





## 13.12_Python语言基础(@property)(掌握)

### 私有的属性添加给getter和setter

#
	class Money(object):
	    def __init__(self):
	        self.__money = 0
	
	    def getMoney(self):
	        return self.__money
	
	    def setMoney(self, value):
	        if isinstance(value, int):
	            self.__money = value
	        else:
	            print("error:不是整型")
		# 先后调用两个方法,调用set方法的值,通过set设置
	    money = property(getMoney, setMoney)  

	
	a = Money()
	print(a.money)
	a.money = 100
	print(a.money)
	
	print(a.getMoney())


#### 使用property实现getter 和 setter方法的功能

#
	如何实现set/get------》修饰器-----》@property
	@property--->属性函数,可以对属性赋值时候做必要的检查,并保证代码的原有功能
	作用:
	1.将方法转化为只读
	2.重新实现一个属性的设置和读取方法,可做边界判定

	class Money:
	    def __init__(self):
	        self.__money = 0
	
	    @property
	    def money(self):
	        return self.__money
	
	    @money.setter
	    def money(self, value):
	        if isinstance(value, int):
	            self.__money = value
	        else:
	            print("error....")
	
	
	a = Money()
	print(a.money)
	a.money = 189
	print(a.money)

#### 案例2:
#
	#使用set和get方法
	class Person(object):
	    def __init__(self,name,age):
	        #属性直接对外暴露
	        # self.age = 12
	        #限制属性
	        self.__name = name
	        self.__age = age
	    def getAge(self):
	        return self.__age
	    def setAge(self,age):
	        if age < 0:
	            age = 0
	        self.__age = age

	# 使用修饰器实现set和get功能
	print("*" * 30)
	
	
	class Person:
	    def __init__(self):
	        self.__name = "oo"
	        self.__age = 34
	
	    @property
	    def age(self):
	        return self.__age
	
	    @age.setter
	    def age(self, age):
	        if age > 0 and age < 100:
	            self.__age = age
	
	
	p = Person()
	print(p.age)




## 13.13_Python语言基础(运算符的重载)(熟练)
* 同样的运算符执行不同数据之间的运算时,采用不同的计算方式
#### 运算符的重载案例:
#
	print(1+2)
	print("1"+"2")
#案例2:
#
	class Person(object):
	    def __init__(self,num):
	        self.num = num
	
	    #运算符重载
	    def __add__(self, other):
	        return Person(self.num+other.num)
	    def __str__(self):
	        return "num="+str(self.num)
	per1 = Person(1)
	per2 = Person(2)
	print(per1+per2)#3  ====print(per1.__add__(per2))
	print(per1.__add__(per2))
	print(per1)
	print(per2)

十七、文件概述

1 文件概述:

  • 常见的文件格式: txt avi html zip doc

2 文件的作用

  • 文件作用:把数据存储起来

3 文件打开关闭(掌握)

我们日常中操作文件的过程:
打开一个文件 ,或者新建一个文件
读写数据
关闭文件

4 Python文件的打开

在python中,使用open()函数可以打开一个已经存在的文件,或者创建一个新的文件
格式:
   open(文件名,访问模式)

f = open("test.txt","w")

4.1 访问模式概述

访问模式                  说明
w	打开一个文件只用于写入,如果该文件已经存在则将其覆盖,如果不存在,创建新文件
r   以只读的方式打开一个文件,文件的指针将会在文件的开头位置,默认模式,如果文件不存在会报错
a   打开一个文件用于追加,如果该文件已经存在,文件的指针会放在文件的结尾,即新的内容将会写入已有内容之后,如果文件不存在,如果文件不存在,创建以一个新文件进行写入

rb	以二进制的方式打开一个文件用于只读,文件的指针将会在文件的开头位置,默认模式,如果文件不存在会报错
wb  以二进制的格式打开一个文件只用于写入,如果该文件已经存在则将其覆盖,如果不存在,创建新文件
ab	以二进制方式打开一个文件用于追加,如果该文件已经存在,文件的指针会放在文件的结尾,即新的内容将会写入已有内容之后,如果文件不存在,如果文件不存在,创建以一个新文件进行写入

r+	打开一个文件用于读写,文件的指针放在文件的开头位置
w+	打开一个文件用于读写,如果该文件已经存在将其覆盖,如果文件不存在,创建一个新文件
a+	打开一个文件用于读写,文件的指针放在文件的末尾位置,,即新的内容将会写入已有内容之后,如果文件不存在,如果文件不存在,创建以一个新文件进行写入

rb+	以二进制的方式打开一个文件用于读写,文件的指针放在文件的开头位置
wb+	以二进制的方式打开一个文件用于读写,如果该文件已经存在将其覆盖,如果文件不存在,创建一个新文件
ab+	以二进制的方式打开一个文件用于读写,文件的指针放在文件的末尾位置,,即新的内容将会写入已有内容之后,如果文件不存在,如果文件不存在,创建以一个新文件进行写入

4.2 Python语言中文件的关闭

使用函数:
close()
f = open("test.txt","w")
f.close()

"""

注意:

close()作用---》节省内存

5文件的读写(掌握)

5.1 写数据(write)

使用write()函数可以完成对文件写入内容
格式:
   f.write(str)

f = open("test.txt","w")
f.write("hello world !")
f.close()

注意:

如果文件不存在则创建,如果存在,则先清空,在写入数据

5.2 读取数据

5.2.1 read()函数
1.读取数据使用read()函数,可以从文件中读取数据,
格式:
read(num)
num :  表示要从文件中读取的数据的长度(单位字节),
如果num没有传入,那么表示读取文件的所有数据

"""
# f = open("test.txt")
# content = f.read()
# print(content)
# content1 = f.read(5)
# print(content1)
# f.close()

注意:

如果使用了多次,那么后面读取的数据是从
上一次读取完数据后的位置开始

5.2.2 readlines()函数
  • 使用readlines可以按照行的方式把整个的文件中的内容进行一次性读取,

  • 返回一个列表,其中每一行的数据作为一个元素

    - f = open("test.txt", "r+")
      f.write("hello python \n hello python \n hello python \nhello python ")
      content = f.readlines()
      print(type(content))
      print(content)
      获取列表中所有的内容
      i = 1
      for temp in content:
          print("%d:%s" % (i, temp))
          i += 1
          
      f.close()
      运行输出结果:
      <class 'list'>
      ['hello python \n', ' hello python \n', ' hello python \n', 'hello python ']
      1:hello python 
      2: hello python 
      3: hello python 
      4:hello python 
    
5.2.3 readline()函数

读取指定文件的所有内容:

def Open_File(filename):
    OldFile=open(filename,"r",encoding="GBK")
    readfile=OldFile.readline()
    while readfile!="":
        print(readfile,end="")
        readfile = OldFile.readline()
    OldFile.close()
# C:\Users\Administrator\Desktop\123.txt
filename=input(":")
Open_File(filename)

6 CSV文件

6.1 读取CSV文件

# 导入CSV模块  pdf   图片
import csv
def readCsv(path):
    infoList = []
    with open(path,"r") as f:
        allFileInfo = csv.reader(f)
        # print(type(allFileInfo))
        for row in allFileInfo:
            infoList.append(row)
    return infoList
path = r"E:\Files\上海校区Python基础班\day14\资料\csv\000002.csv"
info = readCsv(path)
print(info)

6.2 写入csv数据

import csv
def writeCsv(path,data):
    with open(path,"w") as f:
        writer = csv.writer(f)
        for rowDate in data:
              writer.writerow(rowDate)
path = r"E:\Files\上海校区Python基础班\day14\资料\000002.csv"
writeCsv(path,[["1","2","3"],["4","5","6"],["7","8","9"]])

7 制作文件的备份(掌握)

  • 任务描述:

    • 输入文件名字,然后程序自动完成对该文件的备份操作:

      分析:
      input()–>string
      open()
      判断用户输入的文件是否存在

         存在 
              1.打开文件
              2.读取数据
              3.关闭文件
         不存在----》错误提示
      

      完成备份:

      1.拿到刚才读取到的数据
      2.创建一个新文件,将刚才读取到的数据写到这个新文件中
      3.关闭文件
      
oldFileName = input("请输入需要备份的文件:")
#打开需要备份的文件
oldFile = open(oldFileName,"r")
#读取需要备份文件的内容
#判断是否打开
if oldFile:
    #提取文件的后缀名
    fileFlagNum = oldFileName.rfind(".")
    if fileFlagNum > 0:
        fileFlag = oldFileName[fileFlagNum]

    #组织新文件的名字
    newFilename = oldFileName[:fileFlagNum]+"[复件]"+fileFlag
    #创建一个新的文件
    newFile = open(newFilename,"w")
    #将旧文件中的数据,一行一行的方式进行复制到新文件中
    for lineContent in oldFile.readlines():
        newFile.write(lineContent)

    #关闭文件
    oldFile.close()
    newFile.close()

8 文件的定位读写 (掌握)

  • 定位:
    • 通俗的【讲就是找到一个位置

8.1 获取当前读写文件的位置

"""
获取当前读写文件的位置
在读取文件的过程中,如果想知道当前的位置,
可以使用函数tell()来获取,是光标开始的位置
"""
# 打开一个文件
f = open("test.txt", "r")
str = f.read(3)
print(str)
# 查找当前光标的位置
position = f.tell()
print(position)
str = f.read(3)
position = f.tell()
print(position)
f.close()

8.2 定为到某一个位置

如果在读写文件的过程中,需要从另外一个位置进行操作,可以使用seek()函数
格式:
seek(offset,from)
offset:偏移量
from:方向
    0:表示文件的开头
    1:表示当前位置
    2:表示文件的末尾
    
案例L:
把位置设置为:从文件的开头,偏移5个字节
"""
#打开一个文件
f = open("test.txt","rb+")
str = f.read(30)
print(str)
#查找光标当前的位置
# position = f.tell()
# print(position)
#重新设置位置
f.seek(-3,2)
position = f.tell()
print(position)
f.close()

注意:
如果打开文件的模式"r",而不是"rb",则会报错
在文本文件中,没有使用b模式选项打开文件,只允许从文件的开头计算相对位置

9 文件的操作 (掌握)

9.1 文件重命名

概述:

需要对文件进行重命名操作,删除,python中有一个模块os模块----》文件的操作

os模块中有 一个函数rename()可以完成对文件名的重新命名
格式和案例:
rename(需要修改的文件名,,新的文件名)

- - import os
  - os.rename("test.txt","毕业论文.txt")



9.2 文件的删除

概述:
os模块中remove()可以完成对文件的删除操作   
格式:
remove(待删除的文件名)
案例:
os.remove("毕业论文.txt")

9.4 创建一个文件夹

概述:
    使用os模块中mkdir()函数
    
 格式:
 mkdir(str)
案例:
import os
os.mkdir("张三")

9.5 获取当前的目录

概述:
   使用os模块中listdir()函数   
格式:
  listdir()
案例:
import os
print(os.listdir("./"))
#结果为当前目录的文件

9.5 删除文件夹

概述:
   使用os模块中的rmdir()函数
 格式:
     rmdir(str)  
     str--->表示需要删除的文件夹名称
案例:
import os
os.rmdir("张三")
应用----批量修改文件名(重命名)

十八、StringIO和BytesIO

1 StringIO

  • 很多时候,数据读写不一定是文件,也可能在内存中读写
  • StringIO:在内存中读写str

2 StringIO案例:

"""
StringIO
"""
from io import StringIO
f = StringIO()
f1 = f.write("hello")#返回的是写入数据的字节数(每次写入的数据)
print(type(f1))
print(f1)#5
f2 = f.write(" ")
print(f2)#1
f3 = f.write("world!")
print(f3)#6
print(f)
print(f.getvalue())

"""
读取StringIO文件,可以用一个str初始化StringIO,
"""
f = StringIO("hello\nhi\ngoodbye!")
while True:
    s = f.readline()
    if s == "":
        break
    print(s.strip())

3 BytesIO

StringIO操作---》str
如果操作二进制数据,需要使用BytesIO
BytesIO实现在内存中读取byte数据

十九、异常概述

1 异常的介绍

print("------test-----1")
open("123.txt","r")
print("-----test------2")

当python检测到一个错误时,解释器就无法继续执行,反而出现错误提示—>异常

2 异常的处理(掌握)

  • 当出现异常的时候如何处理?

    • 捕获异常

      基本的格式:
      try…except…
      try:
      需要捕获的异常代码
      except 异常处理的类型:
      pass

    try:
    print("------test-----1")
    open(“123.txt”,“r”)
    except FileNotFoundError:
    print(“找不到该文件”)
    print("-----test------2")
    print("-----test 3")

  • 程序看不到任何错误,因为用来except,

  • 捕获到FileNotFoundError异常,并添加了处理方法

总结:

把可能出现问题的代码,放在try里面,
把异常处理的代码放在except中

  • 思考:
    • 如果出现多个异常该如何处理?

try:
    print("------test-----1")
    open("123.txt","r")
except (IOError,NameError):
    print("找不到该文件")
print("-----test------2")
print("-----test   3")
"""
报错,异常处理的类型不正确
"""

3 捕获多个异常(掌握)

try:
    print("----test---1----")
    print(AA.aa())
    open("123.txt","r")
    print("-----test-----2")
except (NameError,FileNotFoundError):
    print("----test   3")

  • 当捕获多个异常时,可以把异常的捕获的名字,
  • 放到except中,如果是多个使用元祖的方式进行存储

3.1 获取异常的信息

try:
    open("123.txt","r")
except FileNotFoundError as ss:
    # print("文件不存在....")
    print(ss)

"""
关键字as as后面跟的是错误的描述信息errorMsg
那么它的基本格式:
    except (错误类型) as 错误的描述:
        return 错误描述

3.2 捕获所有的异常

# exception
try:
    # open("133.txt","r")
    # print(AA.aa())
    print(abcd)
    open("134.txt", "r")
    print(AB.aa())
    print(abcdaaa)
except Exception as reslut:
    print(reslut)

4、else(掌握)

  • 概述:

    • 如果没有捕获到异常,那么执行else中的代码

      try:
      num = 300
      print(num)

    except NameError as errormsg:

    print(errormsg)
    
    

    else:

    print("没有捕获到异常,真高兴!")
    
    

5 try…finally(掌握)

  • try…finally:
    • 在程序中,如果一段代码必须要执行,无论异常是否产生都要去执行,那么此时需要使用finally
    • 如:文件的关闭,释放锁,把数据连接返回连接池

6 try嵌套(掌握)

import os

import time

# os.remove("123.txt")
try:
    f = open("test.txt")
    try:
        while True:
            content = f.readline()
            if len(content) == 0:
                break
            try:
                time.sleep(2)
            finally:
                print("haha")
            print(content)
    finally:
        f.close()
        print("文件关闭")
except:
    print("没有该文件")

finally:
    print("最后的finally")

6.1 函数嵌套中调用

class A(object):
    pass

def test1():
    print("----test1----1")
    print(A.hello())
    print("------test1-----2")
def test2():
    print("----test2----1")
    test1()
    print("------test2-----2")

def test3():
    try:
        print("----test3----1")
        test1()
        print("------test3-----2")
    except Exception as reslut:
        print(reslut)
    finally:
        print("nihao")

test3()

7 抛出自定义异常(掌握)

  • 如何定义一个自定义的异常

    • 需要使用raise语句用来引发异常
    • 异常和错误对象必须有一个名字,并且是error或者是exception的子类
  • raise语句的基本的格式

  • raise 自定义的异常类的对象

    自定义的异常类

    class ShortInputException(Exception):

    def __init__(self,length,atleast):
        self.length = length
        self.atleast = atleast
    
    

    aa = ShortInputException()

    def main():

    try:
        str = input("请输入....")
        if len(str) < 3:
            raise ShortInputException(len(str),3)
    except ShortInputException as reslut:
        print("ShortInputException:输入的长度是%d,长度应该大于%d"%(reslut.length,reslut.atleast))
    
    else:
        print("没有异常的发生")
    
    

    main()

8 异常处理中抛出异常

class Test(object):
    def __init__(self,switch):
        self.switch = switch

    def calc(self,a,b):
        try:
            return a/b
        except Exception as reslut:
            if self.switch:
                print("捕获开启,已经捕获到异常,信息如下:")
                print(reslut)
            else:
                #重新抛出异常,此时不会被这个异常给捕获到,从而去触发默认的异常处理
                raise

a = Test(True)
# a.calc(11,0)
a.switch = False
a.calc(11,0)

二十、Python实现英汉字典

1 Python实现英汉字典

# 打开英汉字典文件
file = open("dict.txt", "r", encoding="utf-8")
# 读取字符串
lines = file.readlines()
# 创建字典
dictionary = {}
# 字典添加内内容
for i in lines:
    line_list = i.split("\t")
    dictionary[line_list[0]] = line_list[1]
# 单词查询功能
while True:
    print("请输入要查询的单词,输入0退出:")
    eng = input()
    if eng == "0":
        break
    if eng in dictionary.keys():
        print(eng + ":\t" + dictionary[eng])
    else:
        print("您查询的词尚未收录,敬请期待")

2 tkinter概述(熟练)

  • tkinter是python的一个标准GUI(图形化界面)
  • 扩展:
    • wxpython;开源软件(免费,原码),是一个python优秀的图形库
    • jython:java swing AWT SWT

3 图形化界面(熟练)

  • 使用方式:

    • 1.导入tkinter
    • 2.创建控件
    • 3.指定这个控件的master,即这个控件属于谁
      1. 通知GM(geometry,manager)执行
    import  tkinter
    创建主窗口
    window = tkinter.Tk()
    设置标题
    window.title("英汉词典")
    设置窗口的大小和位置400×400:宽高   200+20   初始化时候窗口的位置
    window.geometry("400x400+200+20") # 符号为(x)小写矮科斯
    显示内容
    window.mainloop()
    

3.1 控件lable(熟练)

  • 定义:
    • 标签控件可以显示文本
      lable控件:
import tkinter
#创建主窗口
window = tkinter.Tk()
#设置标题
window.title("英汉词典")
#设置窗口的大小和位置400×400:大小宽高   200  20   初始化时候窗口所在的位置
window.geometry("400x400+200+20")
"""
window:父窗体
text:显示的文本内容
bg:背景
fg:字体颜色
wrapLength :指定text文本中多宽进行换行
justify:设置换行后的对齐方式
anchor: 位置  n 北   e  东  s南   w  西   center  居中
"""
label = tkinter.Label(window,text="1806",
              bg="blue",fg="red",
              font=("黑体",20),width="10",
              height="4",wraplength= 100,
              justify="left",anchor = "center")

# 管理控件
label.pack()#pack是一个布局管理器,一个弹性的容器

# 循环消息
window.mainloop()

3.2 控件Button(熟练)

  • button定义:
    • button理解为按钮
  • 按钮的功能:
    • 当点击按钮时发生对应的事
      按钮显示和控制:
import tkinter
# 创建窗口
from tkinter import Frame

window = tkinter.Tk()
# 设置窗口
window.title("英汉词典")
window.geometry("500x500")
# 控制台输出信息的方法
def show_info():
    print("666")
btn_show = tkinter.Button(window, text="查询", command=show_info)
btn_show.pack(side="left")

# 退出按钮
btn_exit = tkinter.Button(window, text="退出", command=window.quit)
btn_exit.pack(side="right")

# 按钮布局
btn_frame = Frame(window, height=30)
btn_frame.pack()
#
# # 显示按钮
# btn_show = tkinter.Button(btn_frame, text="查询", command=show_info)
# btn_show.pack(side="left")
#
# # 退出按钮
# btn_exit = tkinter.Button(btn_frame, text="退出", command=window.quit)
# btn_exit.pack(side="right")

# 消息循环
window.mainloop()

3.3 Text控件(熟练)

  • Text:

    • 显示文本信息
      文本显示框:
    import tkinter
    from tkinter import *
    创建窗口
    window = tkinter.Tk()
    配置窗口
    window.title("英汉词典")
    window.geometry("500x300")
    window.resizable(width=True, height=False)
    文本显示框
    text = Text(window, width=68, height=20)
    text.pack(side="bottom")
    文本框插入内容
    word = "hello hello hello hello hello hello hello hello hello"
    text.insert(tkinter.INSERT, word)
    消息循环
    window.mainloop()
    

3.4 文本输入框(熟练)

  • 输入文本内容的控件
    • 通过get()方法可以获取到输入内容
    • 通过set()方法可以预设内容
      文本输入框:
import tkinter
# 创建窗口
window = tkinter.Tk()
# 设置窗口
window.title("英汉词典")
window.geometry("500x500")

# 输入框
entry = tkinter.Entry(window)
entry.pack()
# 控制台输出内容
def show_info():
    print(entry.get())
# 按钮
button = tkinter.Button(window, text="查询", command=show_info)
button.pack()

# 消息循环
window.mainloop()

3.5 文本输入框关联文本显示框

  • 用户在文本输入框书写内容
  • 内容显示在文本显示框
  • 通过按钮点击事件关联
    获取内容并显示:

import tkinter
from tkinter import *
# 显示信息
def show_info():
    text.insert("1.0", entry.get() + "\n")
    # 创建窗口
window = tkinter.Tk()

# 配置窗口
window.title("英汉词典")
window.geometry("500x300")
window.resizable(width=True, height=False)

# 输入框布局
input_frame = Frame(window, width=30, height=30)
input_frame.pack(side="top")

# 输入框
entry = Entry(input_frame, width=30)
entry.pack(side="left")

# 查询按钮
btn_search = Button(input_frame, text="查询", command=show_info)
btn_search.pack(side="left")

# 退出按钮
btn_search = Button(input_frame, text="退出", command=window.quit)
btn_search.pack(side="right")

# 文本
text = Text(window, width=68, height=20)
text.pack(side="bottom")

# 循环消息
window.mainloop()

3.6 进度条(熟练)

  • 文本内容超出文本显示框一页容量时,内容将无法完全展示
  • 拖动进度条可显示全部内容
    进度条案例:
    import tkinter
    from tkinter import *

    # 显示信息
    def show_info():
        text.insert("1.0", entry.get() + "\n")

    # 创建窗口
    window = tkinter.Tk()
    
    # 配置窗口
    window.title("英汉词典")
    window.geometry("500x300")
    window.resizable(width=True, height=False)
    
    # 输入框布局
    input_frame = Frame(window, width=30, height=30)
    input_frame.pack(side="top")
    
    # 输入框
    entry = Entry(input_frame, width=30)
    entry.pack(side="left")
    
    # 查询按钮
    btn_search = Button(input_frame, text="查询", command=show_info)
    btn_search.pack(side="left")
    
    # 退出按钮
    btn_search = Button(input_frame, text="退出", command=window.quit)
    btn_search.pack(side="right")
    
    # 滚动条
    scroll = tkinter.Scrollbar()
    scroll.pack(side="right", fill=tkinter.Y)
    
    # 文本
    text = Text(window, width=68, height=20)
    text.pack(side="bottom")
    
    # 关联滚动条和文字
    text.config(yscrollcommand=scroll.set)
    scroll.config(command=text.yview)
    
    # 循环消息
    window.mainloop()

3.7 单选按钮(熟练)

  • 只可以选中一个选项,比如性别,毕业状况等信息

单选按钮:

import tkinter
# 创建窗口
from tkinter import Checkbutton, IntVar, Radiobutton

window = tkinter.Tk()

# 设置窗口参数
window.title("英汉词典")
window.geometry("500x500")

# 一组按钮绑定一个变量
check_box = tkinter.BooleanVar()
# 接收显示结果
def send_result():
    print(check_box.get())
# 创建单选按钮
radio_man = Radiobutton(window, text="man", value=True, variable=check_box, command=send_result)
radio_woman = Radiobutton(window, text="woman", value=False, variable=check_box, command=send_result)

# 管理控件
radio_man.pack()
radio_woman.pack()

# 循环消息
window.mainloop()

3.8 多选按钮(熟练)

  • 只可以选中多个选项,比如情趣爱好等信息

多选按钮示例:

import tkinter
from tkinter import Checkbutton, StringVar, BooleanVar
# 创建窗口
window = tkinter.Tk()

# 设置窗口参数
window.title("英汉词典")
window.geometry("500x500")
# 存放选中信息
hobby_list = set()
# 获取选中信息
def update_info():
    if check_01.get():
        hobby_list.add("篮球")
    else:
        if "篮球" in hobby_list:
            hobby_list.remove("篮球")

    if check_02.get():
        hobby_list.add("足球")
    else:
        if "足球" in hobby_list:
            hobby_list.remove("足球")

    if check_03.get():
        hobby_list.add("排球")
    else:
        if "排球" in hobby_list:
            hobby_list.remove("排球")

    print(hobby_list)
    # 给每一个选项创建一个变量
check_01 = BooleanVar()
check_02 = BooleanVar()
check_03 = BooleanVar()

# 复选框
check_box_01 = Checkbutton(window, text="篮球", variable=check_01, command=update_info)
check_box_02 = Checkbutton(window, text="足球", variable=check_02, command=update_info)
check_box_03 = Checkbutton(window, text="排球", variable=check_03, command=update_info)

# 管理控件
check_box_01.pack()
check_box_02.pack()
check_box_03.pack()

# 循环消息
window.mainloop()

4 布局

4.1 绝对布局(熟练)

  • 绝对布局
    • 使用place方法可以通过坐标的方式确定控件的位置
    • 其他控件的变化(增加或删除)不会影响自身的位置
      绝对布局 案例
import tkinter
from tkinter import Label
# 创建窗口
window = tkinter.Tk()

# 设置窗口参数
window = tkinter.Tk()
window.title("英汉词典")
window.geometry("500x500")

# 创建控件
label_01 = Label(window, text="label_01", bg="blue")
label_02 = Label(window, text="label_02", bg="green")
label_03 = Label(window, text="label_03", bg="red")

# 管理控件
label_01.place(x=10, y=10)
label_02.place(x=50, y=50)
label_03.place(x=100, y=100)

# 循环消息
window.mainloop()

4.2 相对布局(熟练)

  • 相对布局
    • 相对布局的控件会参照上一个控件的位置摆放自己
    • 其他控件的变化(增加或删除)会影响自身的位置
      相对布局案例:
import tkinter
from tkinter import Label
# 创建窗口
window = tkinter.Tk()

# 设置窗口参数
window = tkinter.Tk()
window.title("英汉词典")
window.geometry("500x500")

# 创建控件
label_01 = Label(window, text="label_01", bg="blue")
label_02 = Label(window, text="label_02", bg="green")
label_03 = Label(window, text="label_03", bg="red")

# 管理控件
label_01.pack(fill=tkinter.Y, side=tkinter.LEFT)
label_02.pack(fill=tkinter.X, side=tkinter.TOP)
label_03.pack(fill=tkinter.X, side=tkinter.LEFT)

# 循环消息
window.mainloop()

4.3 表格布局(熟练)

  • 参照表格中的位置摆放
    • 参数row表示行数
    • 参数column表示列数
      表格布局案例
import tkinter
from tkinter import Label
# 创建窗口
window = tkinter.Tk()

# 设置窗口参数
window = tkinter.Tk()
window.title("英汉词典")
window.geometry("500x500")

# 创建控件
label_01 = Label(window, text="label_01", bg="blue")
label_02 = Label(window, text="label_02", bg="green")
label_03 = Label(window, text="label_03", bg="red")
label_04 = Label(window, text="label_01", bg="yellow")
label_05 = Label(window, text="label_02", bg="orange")
label_06 = Label(window, text="label_03", bg="pink")

# 管理控件
label_01.grid(row=1, column=1)
label_02.grid(row=2, column=2)
label_03.grid(row=3, column=3)
label_04.grid(row=1, column=4)
label_05.grid(row=2, column=5)
label_06.grid(row=3, column=6)

# 循环消息
window.mainloop()

4.4 浮雕布局(熟练)

  • 浮雕布局可以让控件以3D的效果呈现
  • 浮雕布局属性为relief,共有五种类型:
    • FLAT —平的
    • RAISED —凸起的
    • RIDGE —脊状边缘
    • SUNKEN —凹陷
    • GROOVE —沟状
      浮雕布局案例
import tkinter
from tkinter import Label, GROOVE, SUNKEN, RAISED, FLAT, RIDGE
# 创建窗口
window = tkinter.Tk()

# 设置窗口参数
window.title("英汉词典")
window.geometry("500x500")

"""
relief:3D效果
FLAT    ---平的
RAISED  ---凸起的
RIDGE   ---脊状边缘
SUNKEN  ---凹陷
GROOVE  ---沟状
"""

# 创建控件
label_01 = Label(window, text="label_01", bg="blue", relief=GROOVE)
label_02 = Label(window, text="label_02", bg="green", relief=SUNKEN)
label_03 = Label(window, text="label_03", bg="red", relief=RAISED)
label_04 = Label(window, text="label_04", bg="yellow", relief=FLAT)
label_05 = Label(window, text="label_05", bg="orange", relief=RIDGE)

# 管理控件
label_01.grid(row=1, column=1)
label_02.grid(row=2, column=2)
label_03.grid(row=3, column=3)
label_04.grid(row=4, column=4)
label_05.grid(row=5, column=5)

# 循环消息
window.mainloop()

5 带界面的字典(熟练)

结合以上知识,编写代码实现带界面的字典

import  tkinter

window=tkinter.Tk()
window.title("英汉字典")
window.geometry("500x500")
def printf_info():
    DictionaryPath = r"C:\Users\Administrator\PycharmProjects\PythonText\ModularText\Files\dict.txt"
    DictList = {}
    DictionaryFile = open(DictionaryPath, "r", encoding="utf-8-sig")
    ReadDictionaryFile = DictionaryFile.readlines()

    for R_line in ReadDictionaryFile:
        Dictionary = R_line.split("\t")
        DictList[Dictionary[0]] = Dictionary[1]

    Word = entry.get()
    text.delete(0.0,tkinter.END)
    if Word in DictList:
        info=Word+ ":"+ DictList[Word]
        text.insert(tkinter.INSERT,info)
    elif Word=="":
        info = "输入为空,重新输入。"
        text.insert(tkinter.INSERT, info)
    else:
        info="无该单词!"
        text.insert(tkinter.INSERT,info)
    DictionaryFile.close()

frame=tkinter.Frame(window,width=30)
frame.pack()

label=tkinter.Label(frame,text="输入单词:",font=("黑体",15))
label.pack(side="left")

entry=tkinter.Entry(frame,font=("黑体",15))
entry.pack(side="left")

# 点击打印按钮,执行printf_info()函数,
button=tkinter.Button(frame,text="翻译",font=("黑体",15),command=printf_info)
button.pack(side="right")

# 显示结果的text,将对这输入显示翻译结果呢
text=tkinter.Text(window,font=("黑体",15))
text.pack()

window.mainloop()

二十一、正则符号以及函数

1 字符

字符      功能
.        匹配任意1个字符(除\n)
[]       匹配[]中列举的字符
\d       匹配数字(0~9)
\D       匹配非数字,即不是数字
\s       匹配空白   空格  tab
\S       匹配非空白
\w       匹配单词字符,a~z A~Z 0~9 _
\W       匹配非单词字符

字符        功能
*      表示匹配前一个字符出现0次或者无限次,即可有可无
+      表示匹配前一个字符出现1次或者无限次,即至少一次
?     表示匹配前一个字符出现1次或则0次,   即,要么一次,要么没有

{m}    表示匹配前一个字符出现m次
{m,}   表示前一个字符至少出现m次
{m,n}   表示匹配字符出现从m到n次

字符         功能
^        匹配字符串的开头
$        匹配字符串的结尾
\b      表示匹配一个单词的边界

字符        	功能
|       	匹配左右任意一个表达式
(ab)    	将括号中字符作为分组
\num     	引用分组num匹配到字符串

2 正则函数

re.match

尝试从字符串的起始位置匹配一个模式,如果不是起始位置匹配成功的话,match()就返回""()None。

re.search

匹配成功re.search方法返回一个匹配的对象,否则返回None。(不限制第一个字符)

re.match与re.search的区别
re.match只匹配字符串的开始,如果字符串开始不符合正则表达式,则匹配失败,函数返回None,而re.search匹配整个字符串,直到找到一个匹配。

import re
pattern = re.compile(r'\d+')                    
m = pattern.match('one12twothree34four') 
print(m)

re.compile

用于编译正则表达式,生成一个正则表达式( Pattern )对象,供 match() 和 search() 这两个函数使用。

re.findall (返回空列表)

在字符串中找到正则表达式所匹配的所有子串,并返回一个列表,如果没有找到匹配的,则返回空列表。

re.finditer(返回迭代器)

和 findall 类似,在字符串中找到正则表达式所匹配的所有子串,并把它们作为一个迭代器返回。 

re.split(可扩展)

 split 方法按照能够匹配的子串将字符串分割后返回列表, 

3 检索与替换(删除)

语法:
re.sub(pattern, repl, string, count=0, flags=0)
参数:
pattern : 正则中的模式字符串。
repl : 替换的字符串,也可为一个函数。
string : 要被查找替换的原始字符串。
count : 模式匹配后替换的最大次数,默认 0 表示替换所有的匹配

4 正则表达式对象

re.RegexObject

re.compile() 返回 RegexObject 对象。

re.MatchObject

group() 返回被 RE 匹配的字符串。

start() 返回匹配开始的位置

end() 返回匹配结束的位置

span() 返回一个元组包含匹配 (开始,结束) 的位置

字符串中必须含有每个()中的一个参数

import re
word="123_qwe_QQWE"
#********一下的为一行********
result=re.match(
    "(?=.*[a-zA-Z])(?=.*[0-9])"
    "(?=.*[_@\.!#%&])"
    "[a-zA-Z_0-9@\.!@#%&]{6,20}$"
    "",word).group()
#********以上的为一行********   
print(result)

二十二、网络协议、编程

1 TCP/IP概述

  • 对互联网大家都很熟悉,实际上计算机网络的出现比互联网要早很多。

1.1 通讯协议

计算机为了联网,就必须规定通信协议,,都是由各厂商自己规定早期的计算机网络一套协议
IBM、Apple和Microsoft都有各自的网络协议,互不兼容,这就好比一群人有的说英语,
有的说中文,有的说德语,说同一种语言的人可以交流,不同的语言之间就不行了。

为了把全世界的所有不同类型的计算机都连接起来,就必须规定一套全球通用的协议,
为了实现互联网这个目标,互联网协议簇(Internet Protocol Suite)就是通用协议标准。
Internet是由inter和net两个单词组合起来的,原意就是连接“网络”的网络,
有了Internet,任何私有网络,只要支持这个协议,就可以联入互联网。

1.2 TCP\IP协议

因为互联网协议包含了上百种协议标准,但是最重要的两个协议是TCP和IP协议,
所以,大家把互联网的协议简称TCP/IP协议。

1.3 通讯原理

通信的时候,双方必须知道对方的标识,好比发邮件必须知道对方的邮件地址。
互联网上每个计算机的唯一标识就是IP地址,类似123.123.123.123。
如果一台计算机同时接入到两个或更多的网络,比如路由器,它就会有两个或多个IP地址,
所以,IP地址对应的实际上是计算机的网络接口,通常是网卡。

1.4 IP协议

IP协议负责把数据从一台计算机通过网络发送到另一台计算机。
数据被分割成一小块一小块,然后通过IP包发送出去。
由于互联网链路复杂,两台计算机之间经常有多条线路,
因此,路由器就负责决定如何把一个IP包转发出去。
IP包的特点是按块发送,途径多个路由,但不保证能到达,也不保证顺序到达。

1.5 TCP协议

TCP协议则是建立在IP协议之上的。TCP协议负责在两台计算机之间建立可靠连接,保证数据包按顺序到达。
TCP协议会通过握手建立连接,然后,对每个IP包编号,确保对方按顺序收到,如果包丢掉了,就自动重发。

许多常用的更高级的协议都是建立在TCP协议基础上的,比如用于浏览器的HTTP协议、发送邮件的SMTP协议等。

1.6 端口

一个IP包除了包含要传输的数据外,还包含源IP地址和目标IP地址,源端口和目标端口。
端口有什么作用?在两台计算机通信时,只发IP地址是不够的,因为同一台计算机上跑着多个网络程序。
一个IP包来了之后,到底是交给浏览器还是QQ,就需要端口号来区分。
每个网络程序都向操作系统申请唯一的端口号,
这样,两个进程在两台计算机之间建立网络连接就需要各自的IP地址和各自的端口号。
一个进程也可能同时与多个计算机建立链接,因此它会申请很多端口。

2 网络编程(了解)

Socket又称"套接字",应用程序通常通过"套接字"向网络发出请求或者应答网络请求,
使主机间或者一台计算机上的进程间可以通讯。
Socket是网络编程的一个抽象概念。通常我们用一个Socket表示“打开了一个网络链接”,而打开一个Socket需要知道目标计算机的IP地址和端口号,再指定协议类型即可。

Python 中,我们用 socket()函数来创建套接字,语法格式如下:
socket.socket([family[, type[, proto]]])
family: 套接字家族可以使AF_UNIX或者AF_INET
type: 套接字类型可以根据是面向连接的还是非连接分为SOCK_STREAM或SOCK_DGRAM
protocol: 一般不填默认为0.

socket编程有UDP和TCP两种传输协议

3 UDP编程(熟练)

UDP则是面向无连接的协议。
使用UDP协议时,不需要建立连接,只需要知道对方的IP地址和端口号,就可以直接发数据包。
但是,能不能到达就不知道了。
虽然用UDP传输数据不可靠,但它的优点是速度快(和TCP比),对于不要求可靠到达的数据,就可以使用UDP协议。
我们来看看如何通过UDP协议传输数据。使用UDP的通信双方分为客户端和服务器。
服务器首先需要绑定端口:

UDP编程步骤要简单许多,分别如下:

3.1 UDP服务器端步骤

	"""
  1、创建一个socket,用函数socket(); 
  2、设置socket属性,用函数setsockopt();* 可选 
  3、绑定IP地址、端口等信息到socket上,用函数bind(); 
  4、循环接收数据,用函数recvfrom(); 
  5、关闭网络连接;
	"""

3.2 UDP客户端的client写法

import socket

  • 创建socket对象
    • server_udp = socket.socket(type=socket.SOCK_DGRAM)
  • 绑定地址和端口号
    • ip_port = (“172.16.5.236”, 10086)
    • server_udp.bind(ip_port)
  • 接收数据
    • data, addr = server_udp.recvfrom(1024)
    • print(str(data, encoding=“utf-8”))
  • 断开连接
    • server_udp.close()

3.3 UDP编程的客户端步骤

	"""
  1、创建一个socket,用函数socket(); 
  2、设置socket属性,用函数setsockopt();* 可选 
  3、绑定IP地址、端口等信息到socket上,用函数bind();* 可选 
  4、设置对方的IP地址和端口等属性; 
  5、发送数据,用函数sendto(); 
  6、关闭网络连接;
	"""

3.4 UDP客户端的client写法

import socket

  • 创建socket,设置socket属性
    • client_udp = socket.socket(type=socket.SOCK_DGRAM)
  • 设置对方的IP地址和端口等属性;
    • ip_port = (“172.16.5.236”, 10086)
  • 发送数据,用函数sendto();
    • msg = input(“请输入要发送的信息:”)
    • client_udp.sendto(bytes(msg, encoding=“utf-8”), ip_port)
  • 断开连接
    • client_udp.close()

4 TCP编程(熟练)

4.1 TCP服务端server过程

* 创建 socket 套接字:
* bind 绑定 
* listen 监听
* accept 接受请求连接
* 接收数据
* 断开连接

创建 socket 套接字:

server_tcp = socket.socket()

bind 绑定

ip_port = (“172.16.5.236”, 10086)

server_tcp.bind(ip_port)

  • listen 监听
    • server_tcp.listen(5)
  • accept 接受请求连接
    • conn, addr = server_tcp.accept()
  • 接收数据
    • data = conn.recv(1024)
    • print(str(data, encoding=“utf-8”))
  • 断开连接
    • conn.close()

4.2 TCP客户端的client写法

* 创建socket对象
* 确定IP
* 建立客户端连接
* 发送消息
* 断开连接
  • 创建socket对象
    • client_tcp = socket.socket()
  • 确定IP
    • ip_port = (“172.16.5.236”, 10086)
  • 建立客户端连接
    • client_tcp.connect(ip_port)
  • 发送消息
    • msg = input(“请输入消息:”)
    • client_tcp.sendall(bytes(msg, encoding=“utf-8”))
  • 断开连接
    • client_tcp.close()

5 TCP编程加强版(熟练)

5.1 客户端加强版

import socket

# 创建socket对象
client_tcp = socket.socket()
ip_port = ("172.16.5.236", 10086)
# 建立客户端连接
client_tcp.connect(ip_port)

while True:
    # 发送消息
    msg = input("请输入消息:")
    if len(msg) == 0:
        continue
    elif msg == "exit":
        break
    client_tcp.sendall(bytes(msg, encoding="utf-8"))

    # 接收消息
    data = client_tcp.recv(1024)
    print(str(data, encoding="utf-8"))

# 断开连接
client_tcp.close()

5.2 服务端加强版

import socket

# 创建socket对象
server_tcp = socket.socket()
# 主机地址和端口号
ip_port = ("172.16.5.236", 10086)
# 绑定主机地址和端口号
server_tcp.bind(ip_port)
# 监听
server_tcp.listen(5)
# 建立客户端连接
conn, addr = server_tcp.accept()

while True:
    # 接收消息
    data = conn.recv(1024)
    if not data:
        break
    else:
        print(str(data, encoding="utf-8"))
    # 回复消息
    msg = input("请回复:").strip()
    if len(data) == 0:
        continue
    conn.sendall(bytes(msg, encoding="utf-8"))

# 断开连接
conn.close()

6 TCP和UDP比较(熟练)

6.1基于连接与无连接

对系统资源的要求(TCP较多,UDP少) 
UDP程序结构较简单 
流模式与数据报模式 
TCP保证数据正确性,UDP可能丢包 
TCP保证数据顺序,UDP不保证 
部分满足以下几点要求时,应该采用UDP 面向数据报方式 网络数据大多为短消息 
拥有大量Client 
对数据安全性无特殊要求 
网络负担非常重,但对响应速度要求高 
具体编程时的区别 socket()的参数不同 
UDP Server不需要调用listen和accept 
UDP收发数据用sendto/recvfrom函数 
TCP:地址信息在connect/accept时确定 
UDP:在sendto/recvfrom函数中每次均 需指定地址信息 
UDP:shutdown函数无效

6.2编程区别

UDP和TCP编程步骤也有些不同,如下:

TCP编程的服务器端一般步骤是:

1、创建一个socket,用函数socket(); 
2、设置socket属性,用函数setsockopt(); * 可选 
3、绑定IP地址、端口等信息到socket上,用函数bind(); 
4、开启监听,用函数listen(); 
5、接收客户端上来的连接,用函数accept(); 
6、收发数据,用函数send()和recv(),或者read()和write(); 
7、关闭网络连接; 
8、关闭监听;

TCP编程的客户端一般步骤是:

1、创建一个socket,用函数socket(); 
2、设置socket属性,用函数setsockopt();* 可选 
3、绑定IP地址、端口等信息到socket上,用函数bind();* 可选 
4、设置要连接的对方的IP地址和端口等属性; 
5、连接服务器,用函数connect(); 
6、收发数据,用函数send()和recv(),或者read()和write(); 
7、关闭网络连接;
  • 与之对应的UDP编程步骤要简单许多,分别如下:

UDP编程的服务器端一般步骤是:

1、创建一个socket,用函数socket(); 
2、设置socket属性,用函数setsockopt();* 可选 
3、绑定IP地址、端口等信息到socket上,用函数bind(); 
4、循环接收数据,用函数recvfrom(); 
5、关闭网络连接;

UDP编程的客户端一般步骤是:

1、创建一个socket,用函数socket(); 
2、设置socket属性,用函数setsockopt();* 可选 
3、绑定IP地址、端口等信息到socket上,用函数bind();* 可选 
4、设置对方的IP地址和端口等属性; 
5、发送数据,用函数sendto(); 
6、关闭网络连接;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值