Python基础

目录

一、基础部分

1、内置函数

(1)input() – BIF

函数概述:
input()函数用于接收用户的输入。返回值为str类型。

函数解析:
input() 函数从标准输入流中读取一行数据,将其转换为字符串(末尾的换行符将被舍弃)后并返回。
如果读取到 EOF,则抛出 EOFError 异常。

函数原型:

input([prompt])

参数解析:

参数含义
prompt如果指定该参数,那么将在标准输出中将参数的内容显示出来(末尾不会自动追加换行)

返回值:
该函数将读取到的输入转换成字符串(末尾的换行符将被舍弃)并返回。

基本用法:

>>> input("你的名字:")
你的名字:小由鱼
'小由鱼'

(2)int() – BIF

函数概述:
int() 用于将指定的值转换成整数。

函数解析:
int() 如果读取到一个无法转换为整数的参数,则抛出 ValueError 的异常。

函数原型:

class int(x, base=10)

参数解析:

参数含义
x指定待转换的数字或字符串
base指定 x 参数的基数(默认值是 10[进制])

注:如果需要指定 base 参数,则 x 参数的值必须是字符串、字节或者字节数组

返回值:

  1. 将 x 参数指定的值转换为整数并返回;
  2. 如果不传递任何参数,返回值是 0;
  3. 如果传递的是一个浮点数,那么小数点后的数字将被截掉。

基本用法:

>>> # 不传递任何参数
>>> int()
0
>>> # 将字符串转换为整数
>>> int("5201314")
5201314
>>> # 将浮点数转换为整数
>>> int(3.14)
3
>>> # 指定基数为2(二进制)
>>> int("110", 2)
6
>>> # 指定基数为16(十六进制)
>>> int("FF", 16)
255
>>> # 指定的参数无法转换为整数
>>> int("FishC")
Traceback (most recent call last):
  File "<pyshell#23>", line 1, in <module>
    int("FishC")
ValueError: invalid literal for int() with base 10: 'FishC'

(3)range() – BIF

函数概述:
range 类型表示一个不可变的数字序列,通常用于配合 for 循环指定循环的次数。

函数解析:
range() 有三种参数的组合使用方式,但无论选择哪一种,其参数类型仅能为整数。
如果 step 参数忽略,那么默认的步进跨度值为 1。

函数原型:

class range(stop)
class range(start, stop[, step])

参数解析:

参数含义
stop将生成一个从 0 开始,到 stop 结束的整数数列
start, stop将生成一个从 start 开始,到 stop 结束的整数数列
start, stop, step将生成一个从 start 开始,到 stop 结束,并且步进跨度为 step 的整数数列

注:stop 参数指定的数值不包含在内,即 range(10) -> 0, 1, 2, 3, 4, 5, 6, 7, 8, 9。

基本用法:

>>> Demo One
>>> for i in range(10):
...     print(i, end=' ')
0 1 2 3 4 5 6 7 8 9

>>> Demo Two
>>> for i in range(5, 10):
...     print(i, end=' ')       
5 6 7 8 9

>>> Demo Three
>>> for i in range(5, 10, 2):
...     print(i, end=' ')
5 7 9

>>> Demo Four
>>> for i in range(10, 5, -2):
...     print(i, end=' ')  
10 8 6

偷偷告诉你:与常规列表或元组相比,range 类型的优势在于,range 对象将始终占用相同或更少的内存空间,而不管它表示的范围大小(因为它只存储开始、停止和步进跨度值,并根据需要计算单个项和子范围)。

(4)complex() – BIF

函数概述:
complex() 用于将指定的值转换成复数。

函数解析:
当参数是字符串时,+ 或 - 的两边必须不能有空格,例如 complex('1+2j')是合法的,但 complex('1 + 2j')则会触发 ValueError 异常。

函数原型:
class float([x])

参数解析:

参数含义
x指定待转换的数字或字符串

注:如果需要指定 base参数,则x 参数的值必须是字符串、字节或者字节数组。

返回值:
返回值是 real + imag*1j格式的复数。

基本用法:

>>> # 不传递任何参数
>>> complex()
0j
>>> # 将字符串转换为复数
>>> complex("1+2j")
(1+2j)
>>> # 将整数转换为复数
>>> complex(520)
(520+0j)
>>> # 将浮点数转换为复数
>>> complex(-3.14j)
(-0-3.14j)
>>> # 字符串的中间不能有空格噢
>>> complex("1 + 2j")
Traceback (most recent call last):
  File "<pyshell#9>", line 1, in <module>
    complex("1 + 2j")
ValueError: complex() arg is a malformed string

2、random模块

Python中的random模块用于生成随机数。下面介绍一下random模块中最常用的几个函数。

random.random
random.random()用于生成一个0到1的随机符点数: 0 <= n < 1.0

random.uniform
  random.uniform的函数原型为:random.uniform(a, b),用于生成一个指定范围内的随机符点数,两个参数其中一个是上限,一个是下限。如果a > b,则生成的随机数n: a <= n <= b。如果 a <b, 则 b <= n <= a。

print random.uniform(10, 20)  
print random.uniform(20, 10)  
#---- 结果(不同机器上的结果不一样)  
#18.7356606526  
#12.5798298022  

print random.uniform(10, 20) print random.uniform(20, 10) #---- 结果(不同机器上的结果不一样) #18.7356606526 #12.5798298022

random.randint
  random.randint()的函数原型为:random.randint(a, b),用于生成一个指定范围内的整数。其中参数a是下限,参数b是上限,生成的随机数n: a <= n <= b

print random.randint(12, 20)  #生成的随机数n: 12 <= n <= 20  
print random.randint(20, 20)  #结果永远是20  
#print random.randint(20, 10)  #该语句是错误的。下限必须小于上限。  
print random.randint(12, 20) #生成的随机数n: 12 <= n <= 20 print random.randint(20, 20) #结果永远是20 #print random.randint(20, 10) #该语句是错误的。下限必须小于上限。

random.randrange
  random.randrange的函数原型为:random.randrange([start], stop[, step]),从指定范围内,按指定基数递增的集合中 获取一个随机数。如:random.randrange(10, 100, 2),结果相当于从[10, 12, 14, 16, … 96, 98]序列中获取一个随机数。random.randrange(10, 100, 2)在结果上与 random.choice(range(10, 100, 2) 等效。

random.choice
  random.choice从序列中获取一个随机元素。其函数原型为:random.choice(sequence)。参数sequence表示一个有序类型。这里要说明 一下:sequence在python不是一种特定的类型,而是泛指一系列的类型。list, tuple, 字符串都属于sequence。有关sequence可以查看python手册数据模型这一章。下面是使用choice的一些例子:

print random.choice("学习Python")   
print random.choice(["JGood", "is", "a", "handsome", "boy"])  
print random.choice(("Tuple", "List", "Dict"))  
print random.choice("学习Python") print random.choice(["JGood", "is", "a", "handsome", "boy"]) print random.choice(("Tuple", "List", "Dict"))

random.shuffle
  random.shuffle的函数原型为:random.shuffle(x[, random]),用于将一个列表中的元素打乱。如:

p = ["Python", "is", "powerful", "simple", "and so on..."]  
random.shuffle(p)  
print p  
#---- 结果(不同机器上的结果可能不一样。)  
#['powerful', 'simple', 'is', 'Python', 'and so on...']  
p = ["Python", "is", "powerful", "simple", "and so on..."] random.shuffle(p) print p #---- 结果(不同机器上的结果可能不一样。) #['powerful', 'simple', 'is', 'Python', 'and so on...']

random.sample
  random.sample的函数原型为:random.sample(sequence, k),从指定序列中随机获取指定长度的片断。sample函数不会修改原有序列。

list = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]  
slice = random.sample(list, 5)  #从list中随机获取5个元素,作为一个片断返回  
print slice  
print list #原有序列并没有改变。  
随机整数:
>>> import random
>>> random.randint(0,99)
21

随机选取0到100间的偶数:
>>> import random
>>> random.randrange(0, 101, 2)
42

随机浮点数:
>>> import random
>>> random.random() 
0.85415370477785668
>>> random.uniform(1, 10)
5.4221167969800881

随机字符:
>>> import random
>>> random.choice('abcdefg&#%^*f')
'd'

多个字符中选取特定数量的字符:
>>> import random
random.sample('abcdefghij',3) 
['a', 'd', 'b']

多个字符中选取特定数量的字符组成新字符串:
>>> import random
>>> import string
>>> string.join(random.sample(['a','b','c','d','e','f','g','h','i','j'], 3)).r
eplace(" ","")
'fih'

随机选取字符串:
>>> import random
>>> random.choice ( ['apple', 'pear', 'peach', 'orange', 'lemon'] )
'lemon'

洗牌:
>>> import random
>>> items = [1, 2, 3, 4, 5, 6]
>>> random.shuffle(items)
>>> items
[3, 2, 5, 6, 4, 1]

3、换行输入

(1)反斜杠 \ 不能放在字符串末尾。想换行的话,可以先按一个 \ 再按Enter,这样就不会因为想换行写而执行代码:

print(" \n\
    *   \n\
   ***  \n\
  ***** \n")

(2)或者是前后分别加3个单引号或者双引号(三引号字符串不赋值的情况下,通常当做跨行注释使用):

>>>f='''
123
木头人
'''
>>>f="""
123
木头人
"""

(3)或者是用括号:

>>>str3=('东都霞色好,'
'西湖烟波渺。')

4、type() 和 isinstance()

平常用type( ),因为会返回变量的类型。 isinstance(),它的返回结果比较直接,另外 type() 其实并没有你想象的那么简单,我们后边会讲到。

>>> p=56
>>> l='5'
>>> type(p)
<class 'int'>
>>> type(l)
<class 'str'>

>>> a="小鱿鱼"
>>> isinstance(a,str)
True
>>> isinstance(320.25,float)
True

5.逻辑运算符

运算符含义
and左边和右边同时为True,结果为True
or左边和右边其中一个为True,结果为True
not如果操作数为True,结果为False;如果操作数为False,结果为True

4.运算符优先级

这个表格从低到高列出了 Python 的运算符优先级:

优先级运算符描述
1lambdaLambda表达式
2if - else条件表达式
3or布尔“或”
4and布尔“与”
5not x布尔“非”
6in, not in, is, is not, <, <=,>, >=, !=, ==成员测试,同一性测试,比较
7|按位或
8^按位异或
9&按位与
10<<, >>移位
11+, -加法,减法
12*, @, /, //, %乘法,矩阵乘法,除法,地板除,取余数
13+x,-x, ~x正号,负号,按位翻转
14**指数
15await xAwait表达式
16x[index], x[index:index],x(arguments…), x.attribute下标,切片,函数调用,属性引用
17(expressions…), [expressions…],{key: value…}, {expressions…}绑定或元组显示,列表显示,字典显示,集合显示

1是比2小的,从低到高,上面是低的

17、流程图

在这里插入图片描述

11.数学函数

操作结果
x//yx除以y的结果(地板除:若结果不是整数就向下取整(取比目标结果小的最大整数即不大于本身的数))
abs( x )x的绝对值(复数返回的是模)
float( x )将x转换成浮点数
complex( re,im )返回一个复数,re是实部,im是虚部
divmod( x,y )返回( x//y,x%y )
pow( x,y )计算x的y次方
x**y计算x的y次方

12、real和imag

通过x.real来获取他的这个实部的值,
通过x.imag来获取他的这个虚部的值

>>> x=1+2j
>>> x.real
1.0
>>> x.imag
2.0

13、decimal类型

浮点数的存储规则不精确,因为0.1 转换为二进制是无限循环的。在内存中规定,多余部分截断。所以在计算浮点型或者精度要求比较的时候,使用Deciaml 模块。 或者转为整型来计算,在把计算结果转回去。要创建Decimals,必须先导入decimal模块。

Decimal('66.89')
>>> import decimal
>>> a=decimal.Decimal('0.1')
>>> b=decimal.Decimal('0.2')
>>> print(a+b)
0.3

设置小数点位数

>>> import decimal
>>> decimal.Decimal(66.88888).quantize(decimal.Decimal("0.00")) # 小数点后两位

Decimal('66.89')

14、center()函数

描述: 返回一个长度为width,两边用fillchar(单字符)填充的字符串,即字符串str居中,两边用fillchar填充。若字符串的长度大于width,则直接返回字符串str

语法: str.center(width , “fillchar”) -> str 返回字符串 注意:引号不可省

程序示例:

str = "i love python"
print(str.center(20,"*"))
print(str.center(1,"*"))
print(str.center(20,"8"))

程序运行结果:

***i love python****
i love python
888i love python8888

15、 使用模块中的函数

模块是 Python 程序架构的一个核心概念

  • 模块 就好比是 工具包,要想使用这个工具包中的工具,就需要 导入 import 这个模块
  • 每一个以扩展名 py 结尾的 Python 源代码文件都是一个 模块
  • 在模块中定义的 全局变量 、 函数 都是模块能够提供给外界直接使用的工具

二、分支和循环

1.结果为False的情况

定义为False的对象:None False
值为0的数字类型:0 0.0 0j Decimal(0) Fraction(0,1)
空的序列和集合:"" '' () [] {} set() range(0)

2、三目运算符

条件表达式(三元操作符)
条件成立时执行的语句 if 条件 else 条件不成立是执行的语句

>>>a=3
>>> b=5
>>> samll=a if a>b else b
>>> print(b)
5
>>> score=66
>>> level = ('D' if 0<=score<60 else
	     'C' if 60<=score<80 else
	     'B' if 80<=score<90 else
	     'A' if 90<=score<100 else
	     'S' if score==100 else
	     "请输入 0~100 之间的分值^_^")
>>> print(level)
C

3、for循环

for 变量 in 可迭代对象 :

>>>for aa in "Fish666":
>>>    print(aa)
   F
   i
   s
   h
   6
   6
   6

in是成员资格运算符

4、断言assert

assert,这个关键字,我们称之为“断言”,当这个关键字后边的条件为假的时候,程序自动崩溃,并抛出AssertionError的异常。
举个例子:

>>>assert 3>4

什么情况下我们会需要这样的代码呢?当我们在测试程序的时候就很好用,因为与其让错误的条件导致程序今后莫名其妙地崩溃,不如在错误条件出现的那一瞬间我们实现“自爆”。
一般来说我们可以用Ta再程序中置入检查点,当需要确保程序中的某个条件一定为真才能让程序正常工作的话,assert关键字就非常有用了。

5、range( )–BIF

语法: range( [start,] stop [,step=1] )
这个BIF有三个参数,其中用括号括起来的两个表示这两个参数是可选的。
step=1表示第三个参数的值默认值是1,表示间隔多少。
range这个BIF的作用是生成一个从start参数的值开始到stop参数的值结束的数字序列。

>>> for i in range(4):
	print(i)	
0
1
2
3
>>> for i in range(0,2):
	print(i)	
0
1
>>> for i in range(0,4,2):
	print(i)	
0
2

二、数组

1、列表的各种方法大合集

下表列举了列表对象所有支持的方法:

方法含义
s.append(x)将 x 元素添加到 s 列表的末尾,相当于 s[len(s):] = [x]
s.extend(iterable)将可迭代对象中的每个元素依次添加到 s 列表的末尾,相当于 s[len(s):] = iterable
s.insert(i, x)将 x 元素插入到 s 列表中的 i 位置(其它元素依次往后递推)。所以,s.insert(0, x) 是将 x 元素插入到 s 列表的开头;s.insert(len(s), x)则是将 x 元素插入到 s 列表的末尾,等同于 s.append(x)
s.remove(x)删除 s 列表中第一个 x 元素;如果列表中不存在 x 元素,则抛出 ValueError 异常
s.pop(i)删除 s 列表中第 i 个元素,并将其返回;如果没有指定 i 参数,s.pop() 将删除最后一个元素并返回
s.clear()删除 s 列表中的所有元素,相当于 del a[:]
s.index(x[, start[, end]])返回 x 元素位于 s 列表的索引值(start 和 end 可选,指定开始和结束位置,不过返回的索引值仍然是以序列开始位置计算的);如果找不到,则返回 ValueError 异常
s.count(x)返回 x 元素在 s 列表中出现的次数
s.sort(key=None, reverse=False)对列表中的元素进行原地排序(key 参数用于指定一个用于比较的函数;reverse 参数用于指定排序结果是否反转)
s.reverse()原地反转列表中的元素(第一个与最后一个互换,第二个与倒数第二个互换,第三个与倒数第三个互换,…)
s.copy()返回 s 列表的一个浅拷贝,相当于 s[:]

基本用法:
增:

>>> heros=["钢铁侠","绿巨人"]
>>> heros.append("黑寡妇")
>>> heros
['钢铁侠', '绿巨人', '黑寡妇']

>>> heros.extend(["鹰眼","灭霸","雷神"])
>>> 
>>> heros
['钢铁侠', '绿巨人', '黑寡妇', '鹰眼', '灭霸', '雷神']

>>> s=[1,2,3,4,5]
>>> s[len(s):]=[6]
>>> s
[1, 2, 3, 4, 5, 6]

>>> s=[1,3,4,5]
>>> s.insert(1,2)
>>> s
[1, 2, 3, 4, 5]

删:

>>> heros.remove("灭霸")
>>> heros
['钢铁侠', '绿巨人', '黑寡妇', '鹰眼', '雷神']

>>> heros.pop(2)
'黑寡妇'
>>> heros
['钢铁侠', '绿巨人', '鹰眼', '雷神']

>>> heros.clear()
>>> heros
[]

改:

>>> heros=['蜘蛛侠', '绿巨人', '黑寡妇', '鹰眼', '灭霸', '雷神']
>>> heros[4]="钢铁侠"
>>> heros
['蜘蛛侠', '绿巨人', '黑寡妇', '鹰眼', '钢铁侠', '雷神']

>>> heros[3:]=["武松","林冲","李逵"]
>>> heros
['蜘蛛侠', '绿巨人', '黑寡妇', '武松', '林冲', '李逵']

>>> nums=[3,1,9,6,8,3,5,3]
>>> nums.sort()
>>> nums
[1, 3, 3, 3, 5, 6, 8, 9]

>>> cc=[5,9,5,3,7,1,6]
>>> cc.reverse()
>>> cc
[6, 1, 7, 3, 5, 9, 5]

查:

>>> heros
['李逵', '林冲', '武松', '黑寡妇', '绿巨人', '蜘蛛侠']
>>> heros.index("绿巨人")
4
>>> heros[heros.index("绿巨人")]="神奇女侠"
>>> heros
['李逵', '林冲', '武松', '黑寡妇', '神奇女侠', '蜘蛛侠']


>>> fruits = ['orange', 'apple', 'pear', 'banana', 'kiwi', 'apple', 'banana']
>>> fruits.count('apple')
2
>>> fruits.count('tangerine')
0
>>> fruits.index('banana')
3
>>> fruits.index('banana', 4)  #从索引值 4 开始查找 banana
6
>>> fruits.reverse()
>>> fruits
['banana', 'apple', 'kiwi', 'banana', 'pear', 'apple', 'orange']
>>> fruits.append('grape')
>>> fruits
['banana', 'apple', 'kiwi', 'banana', 'pear', 'apple', 'orange', 'grape']
>>> fruits.sort()
>>> fruits
['apple', 'apple', 'banana', 'banana', 'grape', 'kiwi', 'orange', 'pear']
>>> fruits.pop()
'pear'

复制:

>>> nums=[3,1,9,6,8,3,5,3]
>>> nums1=nums.copy()
>>> nums1
[3, 1, 9, 6, 8, 3, 5, 3]

>>> nums2=nums[3:]
>>> nums2
[6, 8, 3, 5, 3]

>>> dd=nums
>>> dd
[3, 1, 9, 6, 8, 3, 5, 3]

2、负数索引

列表内容132978
正常下标012345
负数下标-6-5-4-3-2-1

正常索引是从左到右索引,负数索引是从右到左。

>>>list[-3:-1] 
[9, 7]

3、列表推导式

看表达式:

>>> [i*i for i in range(10)]
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

居然分别打印了0到9各个数的平方,然后还放在列表里边了有木有?!

列表推导式(List comprehensions)也叫列表解析,灵感取自函数式编程语言 Haskell。Ta 是一个非常有用和灵活的工具,可以用来动态的创建列表,语法如:[有关A的表达式 for A in B]3

例如:

>>> list1 = [x**2 for x in range(10)]
>>> list1
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

相当于:

list1 = []
for x in range(10):
    list1.append(x**2)
>>> list1 = [(x, y) for x in range(10) for y in range(10) if x%2==0 if y%2!=0]
#上面那句还原如下:
list1 = []
for x in range(10):
    for y in range(10):
        if x%2 == 0:
            if y%2 != 0:
                list1.append((x, y))

4、枚举函数

使用枚举函数同时拿到列表中的下标和元素内容

myList=["a","b","c","d"]

for i,x in enumerate(myList):
    print(i,x)

=========*****=========
0 a
1 b
2 c
3 d

5、面试题 —— +=

  • 在 python 中,列表变量调用 += 本质上是在执行列表变量的 extend 方法,不会修改变量的引用

三、元组

元组 能够使用的函数如下:
.count
.index

元组是一种不可改变的类型,不可被修改。戴上了枷锁的列表。
元组的元素不可变,但可以包含可变的对象,如列表list。

1、创建和访问一个元组

可用下标查看元素

>>> tuple1
(1, 2, 3, 4, 5, 6, 7, 8)
>>> tuple[1]
2

决定元组的符号是 , 逗号是关键,小括号不是关键。

>>> temp=(1)
>>> temp
1
>>> type(temp)
<class 'int'>
>>> temp2=2,3,4
>>> type(temp2)
<class 'tuple'> #元组类型

>>> tuple3=1,
>>> tuple3
(1,)
>>> type(tuple3)
<class 'tuple'>

不过创建一个空元组的话用()就行

>>> temp3=()
>>> type(temp3)
<class 'tuple'>

注意:

>>> 8*(8)
64
>>> 8*(8,)
(8, 8, 8, 8, 8, 8, 8, 8)

2、更新和删除一个元组

更新元组

>>> temp=("小甲鱼","黑夜","迷途","小布丁")
>>> temp=temp[:2]+('怡静',)+temp[2:] #重新拼接
>>> temp
('小甲鱼', '黑夜', '怡静', '迷途', '小布丁')

删除元组

>>> del temp

3、应用场景

  • 尽管可以使用 for in 遍历 元组
  • 但是在开发中,更多的应用场景是:
    • 函数的 参数返回值,一个函数可以接收 任意多个参数,或者 一次返回多个数据
    • 格式字符串,格式化字符串后面的 () 本质上就是一个元组
    • 让列表不可以被修改,以保护数据安全

info = (“zhangsan”, 18)
print("%s 的年龄是 %d" % info)

4、元组和列表之间的转换

  • 使用 list 函数可以把元组转换成列表
    list(元组)

  • 使用 tuple 函数可以把列表转换成元组
    tuple(列表)

四、字符串

1、字符串的方法及注释

capitalize()把字符串的第一个字符改为大写
casefold()把整个字符串的所有字符改为小写
center(width)将字符串居中,并使用空格填充至长度 width 的新字符串
count(sub[, start[, end]])返回 sub 在字符串里边出现的次数,start 和 end 参数表示范围,可选。
encode(encoding=‘utf-8’, errors=‘strict’)以 encoding 指定的编码格式对字符串进行编码。
endswith(sub[, start[, end]])检查字符串是否以 sub 子字符串结束,如果是返回 True,否则返回 False。start 和 end 参数表示范围,可选。
expandtabs([tabsize=8])把字符串中的 tab 符号(\t)转换为空格,如不指定参数,默认的空格数是 tabsize=8。
find(sub[, start[, end]])检测 sub 是否包含在字符串中,如果有则返回索引值,否则返回 -1,start 和 end 参数表示范围,可选。
index(sub[, start[, end]])跟 find 方法一样,不过如果 sub 不在 string 中会产生一个异常。
isalnum()如果字符串至少有一个字符并且所有字符都是字母或数字则返回 True,否则返回 False。
isalpha()如果字符串至少有一个字符并且所有字符都是字母则返回 True,否则返回 False。
isdecimal()如果字符串只包含十进制数字则返回 True,否则返回 False。
isdigit()如果字符串只包含数字则返回 True,否则返回 False。
islower()如果字符串中至少包含一个区分大小写的字符,并且这些字符都是小写,则返回 True,否则返回 False。
isnumeric()如果字符串中只包含数字字符,则返回 True,否则返回 False。
isspace()如果字符串中只包含空格,则返回 True,否则返回 False。
istitle()如果字符串是标题化(所有的单词都是以大写开始,其余字母均小写),则返回 True,否则返回 False。
isupper()如果字符串中至少包含一个区分大小写的字符,并且这些字符都是大写,则返回 True,否则返回 False。
join(sub)以字符串作为分隔符,插入到 sub 中所有的字符之间。
ljust(width)返回一个左对齐的字符串,并使用空格填充至长度为 width 的新字符串。
lower()转换字符串中所有大写字符为小写。
lstrip()去掉字符串左边的所有空格
partition(sub)找到子字符串 sub,把字符串分成一个 3 元组 (pre_sub, sub, fol_sub),如果字符串中不包含 sub 则返回 (‘原字符串’, ‘’, ‘’)
replace(old, new[, count])把字符串中的 old 子字符串替换成 new 子字符串,如果 count 指定,则替换不超过 count 次。
rfind(sub[, start[, end]])类似于 find() 方法,不过是从右边开始查找。
rindex(sub[, start[, end]])类似于 index() 方法,不过是从右边开始。
rjust(width)返回一个右对齐的字符串,并使用空格填充至长度为 width 的新字符串。
rpartition(sub)类似于 partition() 方法,不过是从右边开始查找。
rstrip()删除字符串末尾的空格。
split(sep=None, maxsplit=-1)不带参数默认是以空格为分隔符切片字符串,如果 maxsplit 参数有设置,则仅分隔 maxsplit 个子字符串,返回切片后的子字符串拼接的列表。
splitlines(([keepends]))在输出结果里是否去掉换行符,默认为 False,不包含换行符;如果为 True,则保留换行符。。
startswith(prefix[, start[, end]])检查字符串是否以 prefix 开头,是则返回 True,否则返回 False。start 和 end 参数可以指定范围检查,可选。
strip([chars])删除字符串前边和后边所有的空格,chars 参数可以定制删除的字符,可选。
swapcase()翻转字符串中的大小写。
title()返回标题化(所有的单词都是以大写开始,其余字母均小写)的字符串。
translate(table)根据 table 的规则(可以由 str.maketrans(‘a’, ‘b’) 定制)转换字符串中的字符。
upper()转换字符串中的所有小写字符为大写。
zfill(width)返回长度为 width 的字符串,原字符串右对齐,前边用 0 填充。

分割字符串方法:

>>> a='小甲鱼:啊啊啊'
>>> f=a.split(':',1)
>>> f
['小甲鱼', '啊啊啊']
>>> (g,h)=a.split(':',1)
>>> g
'小甲鱼'
>>> h
'啊啊啊'
>>> (g,h)
('小甲鱼', '啊啊啊')
>>> data='1000,小甲鱼,男'
>>> MyDict={}
>>> (MyDict['id'],MyDict['name'],MyDict['sex'])=data.split(',')
>>> print('ID: '+MyDict['id'])
ID: 1000

2、format函数

(1)基本用法

>>> "{0} love {1}.{2}".format("I","FishC","com")
'I love FishC.com'

{0} {1} {2}分别用花括号括起来表示字段,通过位置参数"I" "FishC" "com"传递给format方法,然后再有format方法对字符串进行格式化处理,得到结果。这个例子是用的是(综合)位置参数。

>>> "{a} love {b}.{c}".format(a="I",b="FishC",c="com")
'I love FishC.com'

上面用的是关键字参数。

>>> "{0} love {b}.{c}".format("I",b="FishC",c="com")
'I love FishC.com'

综合位置参数和关键字参数也可以一起使用,但要注意:位置参数必须在关键字参数之前。

>>> "{{0}}".format("不打印")
'{0}'

要想打印花括号,需要用花括号 把花括号 括起来,"不打印"没有字段可以输出,上面的 0 已经被解释掉了(已经不是关键字或者位置参数),所以不打印。

>>> '{0:.1f}{1}'.format(27.658,'GB')
'27.7GB'

在替换域中,冒号表示格式化符号的开始,冒号后面接的就是格式化符号

(2)字符串格式化符号

符号说明
%c格式化字符及其 ASCII 码
%s格式化字符串
%d格式化整数
%o格式化无符号八进制数
%x格式化无符号十六进制数
%X格式化无符号十六进制数(大写)
%f格式化浮点数字,可指定小数点后的精度(默认6位)
%e用科学计数法格式化浮点数
%E作用同 %e,用科学计数法格式化浮点数
%g根据值的大小决定使用 %f 或 %e
%G作用同 %g,根据值的大小决定使用 %f 或者 %E

十进制转换二进制可以用bin( )这个参数

>>> print('十进制 -> 十六进制 : %d -> 0x%x' % (108, 108))
十进制 -> 十六进制 : 108 -> 0x6c

>>> print('十进制 -> 八进制 : %d -> 0o%o' % (108, 108))
十进制 -> 八进制 : 108 -> 0o154

>>> print('十进制 -> 二进制 : %d -> ' % num, bin(108))
十进制 -> 二进制 : 108 ->  0b1101100
>>> '%c' % 97
'a'
>>> '%c %c %c' %(97,98,99)
'a b c'

>>> '%s' % 'I' ' love'
'I love'

>>> '%d+%d=%d' %(4,5,4+5)
'4+5=9'

>>> '%o' % 10
'12'

(3)格式化操作符辅助命令

符号说明
m.nm 是显示的最小总宽度,n 是小数点后的位数
-用于左对齐
+在正数前面显示加号(+)
#在八进制数前面显示 ‘0o’,在十六进制数前面显示 ‘0x’ 或 ‘0X’
0显示的数字前面填充 ‘0’ 取代空格
>>> '%5.1f' % 27.658
' 27.7'

>>> '%.2e' % 27.658
'2.77e+01'

>>> '%-10d' % 5
'5         '

>>> '%#o' % 10 #打印8进制10
'0o12'

>>> '%010d'% 5
'0000000005'

(4)其他地方的

它增强了字符串格式化的功能。基本语法是通过 {} 和 : 来代替以前的 % 。format 函数可以接受不限个参数,位置可以不按顺序。

例一: format 函数可以接受不限个参数,位置可以不按顺序。

"{} {}".format("hello", "world")    # 不设置指定位置,按默认顺序
运行结果:'hello world'

 "{0} {1}".format("hello", "world")  # 设置指定位置
运行结果:'hello world'

"{1} {0} {1}".format("hello", "world")  # 设置指定位置
运行结果:'world hello world'

例二: 也可以设置参数。

print("网站名:{name}, 地址 {url}".format(name="菜鸟教程", url="www.runoob.com"))

# 通过字典设置参数
site = {"name": "菜鸟教程", "url": "www.runoob.com"}
print("网站名:{name}, 地址 {url}".format(**site))

# 通过列表索引设置参数
my_list = ['菜鸟教程', 'www.runoob.com']
print("网站名:{0[0]}, 地址 {0[1]}".format(my_list))  # "0" 是必须的
运行结果:
网站名:菜鸟教程, 地址 www.runoob.com
网站名:菜鸟教程, 地址 www.runoob.com
网站名:菜鸟教程, 地址 www.runoob.com

例三: 也可以向 str.format() 传入对象:

class AssignValue(object):
    def __init__(self, value):
        self.value = value
my_value = AssignValue(6)
print('value 为: {0.value}'.format(my_value))  # "0" 是可选的
输出结果为:
value 为: 6

例四: 下表展示了 str.format() 格式化数字的多种方法

print("{:.2f}".format(3.1415926));
3.14

数字格式化方法

数字格式输出描述
3.1415926{:.2f}3.14保留小数点后两位
3.1415926{:+.2f}+3.14带符号保留小数点后两位
-1{:+.2f}-1.00带符号保留小数点后两位
2.71828{:.0f}3不带小数
5{:0>2d}05数字补零 (填充左边, 宽度为2)
5{:x<4d}5xxx数字补x (填充右边, 宽度为4)
10{:x<4d}10xx数字补x (填充右边, 宽度为4)
1000000{:,}1,000,000以逗号分隔的数字格式
0.25{:.2%}25.00%百分比格式
1000000000{:.2e}1.00e+09指数记法
13{:10d}13右对齐 (默认, 宽度为10)
13{:<10d}13左对齐 (宽度为10)
13{:^10d}13中间对齐 (宽度为10)
‘{:b}’.format(11)1011
‘{:d}’.format(11)11
11的进制‘{: o}’.format(11)13
‘{:x}’.format(11)b
‘{:#x}’.format(11)0xb
‘{:#X}’.format(11)0XB

^, <, > 分别是居中、左对齐、右对齐,后面带宽度, : 号后面带填充的字符,只能是一个字符,不指定则默认是用空格填充。

+表示在正数前显示+,负数前显示 -(空格)表示在正数前加空格

bdox 分别是二进制、十进制、八进制、十六进制。

例五:
给你一个字典:
t={‘year’:’2013’,’month’:’9’,’day’:’30’,’hour’:’16’,’minute’:’45’,’second’:’2’}
请按这样的格式输出:2013-09-30 16:45:02

def data_to_str(d):
    '''
    :param d: 日期字典
    :return: str 格式化后的日期
    '''

    s1='{} {:>02} {:>02}'.format(t['year'],t['month'],t['day'])
    s2='{} {:>02} {:>02}'.format(t['hour'],t['minute'],t['second'])
    print(s1,s2)
    print('-'.join(s1.split()),end=' ')
    print(':'.join(s2.split()))
    return 0
t={'year':'2013','month':'9','day':'30','hour':'16','minute':'45','second':'2'}
print(data_to_str(t))
运行结果:
2013 09 30 16 45 02
2013-09-30 16:45:02

3、转义字符

符号说明
\\反斜杠( \ )
\’单引号( ’ )
\"双引号( " )
\a发出系统响铃声( BEL )
\b退格符( BS )
\n换行符( LF )
\t横向制表符( TAB )
\v纵向制表符( VT )
\r回车符( CR )
\f换页符( FF )
\oooooo八进制数
\xhhhh为十六进制数
\0表示一个空字符

# end = “”,表示输出结束后,不换行
# “\t” 可以在控制台输出一个制表符,协助在输出文本时对齐
print("%d * %d = %d" % (col, row, row * col), end="\t")
\t 在控制台输出一个 制表符,协助在输出文本时 垂直方向 保持对齐

4.成员资格运算符 in和not in

Python 有一个成员资格运算符:in,用于检查一个值是否在序列中,如果在序列中返回 True,否则返回 False。

>>> name = '小甲鱼'
>>> '鱼' in name
True
>>> '肥鱼' in name
False

5、 原始字符串

前面加上 r就说明字符串是一个原始字符串(每一个字符都没有特殊含义),转义字符将不再有效:

>>> print(r"D:\one\two\three")
D:\one\two\three

如果非要在原始字符串结尾输入反斜杠,可以如何灵活处理?

>>>str = r'C:\Program Files\FishC\Good''\\'
//注意这是两个单引号

???:

symbols=r' ~!@#$%^&*()_=-/,.?<>;:[]{}|\ '              #''之间加上空格
symbols = r'''`!@#$%^&*()_+-=/*{}[]\|'";:/?,.<>'''     #用三个单引号

6、ASCII码

在这里插入图片描述

五、序列

序列(列表、元组和字符串)中的方法

1、list方法

>>> a=list()  #没有参数就创建一个新的列表
>>> a
[]

>>> b='I love FishC.com'
>>> b=list(b)  #迭代
>>> b
['I', ' ', 'l', 'o', 'v', 'e', ' ', 'F', 'i', 's', 'h', 'C', '.', 'c', 'o', 'm']

>>> c=(1,1,2,3,5,8,13,21,34)
>>> c=list(c)  #变成了列表
>>> c
[1, 1, 2, 3, 5, 8, 13, 21, 34]

2、tuple([iterable])方法

把一个可迭代对象转换为元组,接上个小节

>>> c=tuple(c)
>>> c
(1, 1, 2, 3, 5, 8, 13, 21, 34)

3、max()和min()

返回序列或者参数集合中的最大值/最小值

4、sum(iterable[, start=0])

返回序列iterable和可选参数start的总和。

>>> numbers=[1,18,13,0,-98,34,54,76,32]
>>> sorted(numbers)  #和sort差不多
[-98, 0, 1, 13, 18, 32, 34, 54, 76]
>>> reversed(numbers)  #和reverse差不多,不能单独用,必须加上list,见下
<list_reverseiterator object at 0x0306B7F0>
>>> list(reversed(numbers))
[32, 76, 54, 34, -98, 0, 13, 18, 1]

5、enumerate( )

>>> list(enumerate(numbers))
[(0, 1), (1, 18), (2, 13), (3, 0), (4, -98), (5, 34), (6, 54), (7, 76), (8, 32)]

6、zip( )

返回由各个参数的序列组成的元组

>>> a=[1,2,3,4,5,6,7,8]
>>> b=[4,5,6,7,8]
>>> list(zip(a,b))
[(1, 4), (2, 5), (3, 6), (4, 7), (5, 8)]

五~六、变量进阶

1、变量的引用

  • 变量 和 数据 都是保存在 内存 中的
  • 在 Python 中 函数 的 参数传递 以及 返回值 都是靠 引用 传递的

1.1 引用的概念

在 Python 中

  • 变量数据 是分开存储的
  • 数据 保存在内存中的一个位置
  • 变量 中保存着数据在内存中的地址
  • 变量记录数据的地址,就叫做 引用
  • 使用 id() 函数可以查看变量中保存数据所在的 内存地址

注意:如果变量已经被定义,当给一个变量赋值的时候,本质上是 修改了数据的引用

  • 变量 不再 对之前的数据引用
  • 变量 改为 对新赋值的数据引用

1.2 变量引用 的示例

在 Python 中,变量的名字类似于 便签纸 贴在 数据 上

1.3 函数的参数和返回值的传递

在 Python 中,函数的 实参/返回值 都是是靠 引用 来传递来的

2、可变和不可变类型

  • 不可变类型,内存中的数据不允许被修改:
    – 数字类型 int, bool, float, complex, long(2.x)
    – 字符串 str
    – 元组 tuple
  • 可变类型,内存中的数据可以被修改:
    – 列表 list
    – 字典 dict

哈希 (hash)

  • Python 中内置有一个名字叫做 hash(o) 的函数
    – 接收一个 不可变类型 的数据作为 参数
    – 返回 结果是一个 整数
  • 哈希 是一种 算法,其作用就是提取数据的 特征码(指纹)
    – 相同的内容 得到 相同的结果
    – 不同的内容 得到 不同的结果
  • 在 Python 中,设置字典的 键值对 时,会首先对 key 进行 hash 已决定如何在内存中保存字典的数据,以方便 后续 对字典的操作:增、删、改、查
    – 键值对的 key 必须是不可变类型数据
    – 键值对的 value 可以是任意类型的数据

六、函数

定义好函数之后,表示这个函数封装了一段代码而已,如果不主动调用函数,函数是不会主动执行的。

1、函数文档

我们看到在函数开头写下的字符串Ta是不会打印出来的,但Ta会作为函数的一部分存储起来,这个我们称之为函数文档字符串,Ta的功能跟注释是一样的。

>>> def MyFirstFunction(name):
	    '这双单引号里面是函数文档'
        #函数文档只是一个形式,占据一个参数位置
       print('输入的字符是:'+name)
       
>>> MyFirstFunction('函数文档')
输入的字符是:函数文档

查看函数文档的2种方法:

>>> MyFirstFunction.__doc__
'这双单引号里面是函数文档'

>>> help(MyFirstFunction)
Help on MyFirstFunction in module __main__:
MyFirstFunction(name)
      这双单引号里面是函数文档

第二种方法:函数的文档注释

  • 在开发中,如果希望给函数添加注释,应该在 定义函数 的下方,使用 连续的三对引号
  • 在 连续的三对引号 之间编写对函数的说明文字
  • 在 函数调用 位置,使用快捷键 CTRL + Q 可以查看函数的说明信息

  • 第三种:
  • 光标移动到函数那一行,然后选择点击下图蓝色的
    在这里插入图片描述
    之后在分别注释,就会:
    在这里插入图片描述
    按Ctrl+Q:
    在这里插入图片描述

2、收集参数param

>>> def test(*params):               #收集参数/可变参数
		print('参数的长度是:',len(params));
		print('第二个参数是:',params[1]);	
>>> test(1,'小甲鱼',3.14,5,6,7,8)    #可传任意类型参数
参数的长度是: 7
第二个参数是: 小甲鱼
>>> def test(*params,exp):
		print(exp)
		print('参数的长度是:',len(params));
		print('第二个参数是:',params[1]);
>>> test(1,'小甲鱼',3.14,5,6,7,8,exp=8)   #设置其他参数
8
参数的长度是: 7
第二个参数是: 小甲鱼
>>> def test(*params,exp=8):  #也可以设置上默认参数

3、global关键字

描述:
Python中定义函数时,若想在函数内部(定义的局部变量与外部全局变量名字相同时)对函数外的(全局)变量进行操作,就需要在函数内部声明其为global。

实例:

>>> x = 1
>>> def fun1():
        x = 2
       
>>> fun1()
>>> print(x)
1            # 解析:在fun1函数中并未在x前面加global,所以fun1函数无法将x赋为2,无法改变x的值
>>> x = 1
>>> def fun1():
        global x
        x = 2
       
>>> fun1()
>>> print(x)
2            # 解析:global需要在函数内部声明,若在函数外声明,则函数依然无法操作x

4、闭包

全部代码:

>>> def funX(x):
		def funY(y):
			return x*y
		return funY

>>> temp=funX(8)
>>> temp(5)
40

要知道 当函数名带上括号时候,函数返回的是函数运行的结果
当函数名不带括号时候,函数返回的是一个函数体

>>>def funX(x):
    	def funY(y):
        	return x*y
    	return funY

因为你定义的 funX 函数返回的是funY ,当函数不带括号时候就代表一个函数体,也就是这funY 一整个函数

>>>temp=funX(8)

所以你这里 temp= funX(8) ,带上括号,所以是把 x = 8 传入后调用函数运行的结果,就可以看成:

>>>def funX(8):
		def funY(y):
        	 return 8*y
		return funY

又因为返回的是funY不带括号,是整个函数体,所以实际上 temp= funX(8) 就等于了 temp = funY 即代码可以看成这样:

def funY(y):
    return 8*y

此时你在对 temp(5)那么就是 将funYy 参数赋值为5

>>> temp(5)
40

所以最后返回的结果是 return 8 * 5

第一次是对 x 传入参数,因为第一次调用返回的是个函数,则第二次传入的参数就是返回后函数的参数值了,即第一次 x = 8,第二次 y = 5

5、nonlocal关键字

在内部函数中你只能对外部函数的局部变量进行访问,但不能对其修改。
举例:
这样会报错

>>> def Fun1():
		x=5             #非全局变量的外部变量      
		def Fun2():
			x*=x
			return x
		return Fun2()
>>> Fun1()

放到容器里,内部函数访问外部函数的局部变量才不会报错,如下:

>>> def Fun1():
		x=[5]
		def Fun2():
			x[0]*=x[0]
			return x[0]
		return Fun2()
>>> Fun1()
25

或者用nonlocal关键字,把他强制声明为不是一个局部变量(上一级的)

>>> def Fun1():
	x=5
		def Fun2():
			nonlocal x
			x*=x
			return x
		return Fun2()
>>> Fun1()
25

6、lambda表达式

Python写一些执行脚本时,使用lambda就可以省下定义函数的过程,使用lambda就可以使得代码更加精简。
对于一些比较抽象并且整个程序执行下来只需要调用一两次的函数,使用lambda就不需要考虑命名的问题了。
简化代码的可读性。

>>> def ds(x):
	return 2*x+1
>>> ds(5)
11

>>> g=lambda x:2*x+1  #单个参数 #匿名函数
>>> g(5)
11

>>> h=lambda x,y:x+y  #多个参数
>>> h(3,4)

7、filter( )函数:过滤器

filter(内置函数)有两个参数,第一个参数可以是函数或者None对象,第二个参数是可迭代的数据:
filter( function or None,iterable)
如果第一个参数是一个函数的话,将第二个可迭代数据里的每一个元素作为函数的参数进行计算,把返回True的值筛选出来,变成一个列表。
如果第一个参数为None,则将第二个参数里面的True的值筛选出来。

>>> filter(None,[1,0,False,True])
<filter object at 0x03CFCFE8>                #这样会出现不明字符
>>> list(filter(None,[1,0,False,True]))      #可以用list()返回一个列表
[1, True]

返回奇数:

>>> def add(x):
	return x%2

>>> temp=range(10)
>>> show=filter(add,temp)
>>> list(show)
[1, 3, 5, 7, 9]

或者用上节课的lambda简化:

>>> list(filter(lambda x:x%2 , range(10)))
[1, 3, 5, 7, 9]

8、map( )–BIF函数:映射

map()(内置函数):也有两个参数,仍然是一个函数和可迭代序列。可迭代序列也可是两个。
将序列的每一个元素作为函数的参数进行运算加工,直到可迭代对象的每一个元素都加工完毕,返回所有加工后的元素构成的新序列。

>>> list(map(lambda x:x*2,range(10)))
[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]

9、函数返回元组(多个值)

示例 —— 温度和湿度测量

  • 假设要开发一个函数能够同时返回当前的温度和湿度

  • 在利用 元组 在返回温度的同时,也能够返回 湿度

  • 改造如下:

      def measure():
      """返回当前的温度"""
      
     	print("开始测量...")
      	temp = 39
      	wetness = 10
      	print("测量结束...")
    
        return (temp, wetness)
    

提示:如果一个函数返回的是元组,括号可以省略
技巧

  • 在 Python 中,可以 将一个元组 使用 赋值语句 同时赋值给 多个变量
  • 注意:变量的数量需要和元组中的元素数量保持一致
    可以使用多个变量一次接受函数的返回结果。
    result = temp, wetness = measure()
    temp= 第0个元素,wetness=第1个元素

10、 缺省参数

(1)定义

  • 定义函数时,可以给 某个参数 指定一个默认值,具有默认值的参数就叫做 缺省参数
  • 调用函数时,如果没有传入 缺省参数 的值,则在函数内部使用定义函数时指定的 参数默认值
  • 函数的缺省参数,将常见的值设置为参数的缺省值,从而 简化函数的调用
  • 例如:对列表排序的方法
    gl_num_list = [6, 3, 9]
    
    # 默认就是升序排序,因为这种应用需求更多
    gl_num_list.sort()
    print(gl_num_list)
    
    # 只有当需要降序排序时,才需要传递 `reverse` 参数
    gl_num_list.sort(reverse=True)
    print(gl_num_list)

(2)缺省参数的注意事项

  1. 缺省参数的定义位置
    必须保证 带有默认值的缺省参数
    在参数列表末尾所以,以下定义是错误的!
    def print_info(name, gender=True, title):
  2. 调用带有多个缺省参数的函数
    在 调用函数时,如果有 多个缺省参数,需要指定参数名,这样解释器才能够知道参数的对应关系!
    def print_info(name, title="", gender=True):
        """
    
        :param title: 职位
        :param name: 班上同学的姓名
        :param gender: True 男生 False 女生
        """
    
        gender_text = "男生"
    
        if not gender:
            gender_text = "女生"
    
        print("%s%s 是 %s" % (title, name, gender_text))
    
    
    # 提示:在指定缺省参数的默认值时,应该使用最常见的值作为默认值!
    print_info("小明")
    print_info("老王", title="班长")
    print_info("小美", gender=False)

小明 是 男生
班长老王 是 男生
小美 是 女生

(3)多值参数(知道)

定义支持多值参数的函数

  • 有时可能需要 一个函数 能够处理的参数 个数 是不确定的,这个时候,就可以使用 多值参数
  • python 中有 两种 多值参数:
    – 参数名前增加 一个 * 可以接收 元组
    – 参数名前增加 两个 * 可以接收 字典
  • 一般在给多值参数命名时,习惯使用以下两个名字
    – *args —— 存放 元组 参数,前面有一个 *
    – **kwargs —— 存放 字典 参数,前面有两个 *
  • args 是 arguments 的缩写,有变量的含义
  • kw 是 keyword 的缩写,kwargs 可以记忆 键值对参数
def demo(num, *args, **kwargs):
    
    print(num)
    print(args)
    print(kwargs)
       
demo(1, 2, 3, 4, 5, name="小明", age=18, gender=True)

1
(2, 3, 4, 5)
{‘name’: ‘小明’, ‘age’: 18, ‘gender’: True}

多值参数案例 —— 计算任意多个数字的和

  1. 定义一个函数 sum_numbers,可以接收的 任意多个整数
  2. 功能要求:将传递的 所有数字累加 并且返回累加结果
    def sum_numbers(*args):
    
        num = 0
        # 遍历 args 元组顺序求和
        for n in args:
            num += n
    
        return num
    
    print(sum_numbers(1, 2, 3))

4、元组和字典的拆包(知道)

  • 在调用带有多值参数的函数时,如果希望:
    – 将一个 元组变量,直接传递给 args
    – 将一个 字典变量,直接传递给 kwargs
  • 就可以使用 拆包,简化参数的传递,拆包 的方式是:
    – 在 元组变量前,增加 一个 *
    – 在 字典变量前,增加 两个 *
    def demo(*args, **kwargs):
    
        print(args)
        print(kwargs)
    
    
    # 需要将一个元组变量/字典变量传递给函数对应的参数
    gl_nums = (1, 2, 3)
    gl_xiaoming = {"name": "小明", "age": 18}
    
    # 会把 num_tuple 和 xiaoming 作为元组传递个 args
    demo(gl_nums, gl_xiaoming)
    demo(*gl_nums, **gl_xiaoming)

((1, 2, 3), {‘name’: ‘小明’, ‘age’: 18})
{}

(1, 2, 3)
{‘name’: ‘小明’, ‘age’: 18}

七、递归

1、递归

>>> def recursion():
		return recursion()    #返回值值调用它自己
>>>recursion()        #会报错

python3.? 默认递归深度100层,但可自己设置深度:

>>>import sys
>>>sys.setrecursionlimit(10000)  #设置10000层深度

2、汉诺塔

def hanoi(n, x, y, z):
    if n == 1:
        print(x, ' --> ', z)
    else:
        hanoi(n-1, x, z, y) # 将前n-1个盘子从x移动到y上
        print(x, ' --> ', z) # 将最底下的最后一个盘子从x移动到z上
        hanoi(n-1, y, x, z) # 将y上的n-1个盘子移动到z上

n = int(input('请输入汉诺塔的层数:'))
hanoi(n, 'X', 'Y', 'Z')

八、字典

字典,不属于序列类型,而是属于映射类型,用{}表示他是一个字典。
字典是无序的,只能通过键来索引。

1、基础

下面是所有创建的方法

>>> a=dict(one=1,two=2,three=3)
>>> b={'one':1,'two':2,'three':3}
>>> c=dict(zip(['one','two','three'],[1,2,3]))
>>> d=dict([('two',2), ('three',3),('one',1)])
>>> e=dict({'three':3,'one':1,'two':2})

字典是另一种可变容器模型,且可存储任意类型对象。
字典的每个键值(key=>value)对用冒号(:)分割,每个对之间用逗号(,)分割,整个字典包括在花括号({})中 ,格式如下所示:

d = {key1 : value1, key2 : value2 }

键必须是唯一的,但值则不必。
值可以取任何数据类型,但键必须是不可变的,如字符串,数字或元组。
一个简单的字典实例:

dict = {'Alice': '2341', 'Beth': '9102', 'Cecil': '3258'}

也可如此创建字典:

dict1 = { 'abc': 456 }
dict2 = { 'abc': 123, 98.6: 37 }

也可:

>>> ss=dict((('F',70),('i',105),('s',115)))
>>> ss
{'F': 70, 'i': 105, 's': 115}
>>> type(ss)
<class 'dict'>
>>> ss['i']
105

也可:

>>>dict()                        # 创建空字典
{}
>>> dict(a='a', b='b', t='t')     # 传入关键字
{'a': 'a', 'b': 'b', 't': 't'}

>>> dict(zip(['one', 'two', 'three'], [1, 2, 3]))   # 映射函数方式来构造字典
{'three': 3, 'two': 2, 'one': 1} 

>>> dict([('one', 1), ('two', 2), ('three', 3)])    # 可迭代对象方式来构造字典
{'three': 3, 'two': 2, 'one': 1}

2、dict()函数

描述
dict() 函数用于创建一个字典。
语法

class dict(**kwarg)
class dict(mapping, **kwarg)
class dict(iterable, **kwarg)

返回值
返回一个字典。

实例

>>>dict()                        # 创建空字典
{}
>>> dict(a='a', b='b', t='t')     # 传入关键字
{'a': 'a', 'b': 'b', 't': 't'}

>>> dict(zip(['one', 'two', 'three'], [1, 2, 3]))   # 映射函数方式来构造字典
{'three': 3, 'two': 2, 'one': 1} 

>>> dict([('one', 1), ('two', 2), ('three', 3)])    # 可迭代对象方式来构造字典
{'three': 3, 'two': 2, 'one': 1}

3、访问字典里的值

把相应的键放入到方括号中,如下实例:

dict = {'Name': 'Runoob', 'Age': 7, 'Class': 'First'}
print ("Name键的内容: ", dict['Name'])
print ("Age键的内容: ", dict['Age'])

Name键的内容: Runoob
Age键的内容: 7

如果用字典里没有的键访问数据,会输出错误

4、修改字典

向字典添加新内容的方法是增加新的键/值对,修改或删除已有键/值对如下实例:

dict = {'Name': 'Runoob', 'Age': 7, 'Class': 'First'}

dict['Age'] = 8               # 更新 Age
dict['School'] = "菜鸟教程"  # 添加信息


print ("Age键的内容: ", dict['Age'])
print ("School键的内容:", dict['School'])
以上实例输出结果:
Age键的内容:  8
School键的内容:  菜鸟教程

5、fromkeys()方法

描述
Python 字典 fromkeys() 函数用于创建一个新字典,以序列 seq 中元素做字典的键,value 为字典所有键对应的初始值。

语法

dict.fromkeys(seq[, value])

参数
seq – 字典键值列表。
value – 可选参数, 设置键序列(seq)对应的值,默认为 None。

返回值
该方法返回一个新字典

实例

>>> dict1={}
>>> dict1.fromkeys((1,2,3))           #只设置了seq参数的值(1,2,3),对应的键默认值是None
{1: None, 2: None, 3: None}

>>> dict1.fromkeys((1,2,3),'Number')         #设置为Number都将改为Number
{1: 'Number', 2: 'Number', 3: 'Number'}

>>> dict1.fromkeys((1,2,3),('one','two','three'))    #会把整个元组当成一个值
{1: ('one', 'two', 'three'), 2: ('one', 'two', 'three'), 3: ('one', 'two', 'three')}

>>> dict1.fromkeys((1,3),'数字')       #不会只修改制定的键,而是重新创建一个新的字典
{1: '数字', 3: '数字'} 

6、keys()函数

得到所有的键(列表),返回字典键的引用
描述
Python3 字典 keys() 方法返回一个可迭代对象,可以使用 list() 来转换为列表。

返回值
返回一个迭代器。

实例

>>> dict1 = {1: '一', 2: '二'}
>>> dict1.keys()
dict1_keys([1, 2])
>>> list(dict1.keys())             # 转换为列表
[1, 2]


>>> for eachKey in dict1.keys():
	print(eachKey)	
1
2

6、value()方法

和keys()函数对应,返回的是键对应的值。

7、items()方法

描述
Python 字典 items() 方法以列表返回可遍历的(键, 值) 元组数组。

语法
dict.items()

返回值
返回可遍历的(键, 值) 元组数组。

实例

>>> for eachKey in dict1.items():
	print(eachKey)
	
(1, '一')
(2, '二')

8、get()方法

描述
Python 字典 get() 函数返回指定键的值,如果值不在字典中返回默认值。

语法
dict.get(key, default=None)

参数
key – 字典中要查找的键。
default – 如果指定键的值不存在时,返回该默认值值。

返回值
返回指定键的值,如果值不在字典中返回默认值 None。

查找的时候如果没有,会返回None而不会报错。

>>> dict1.get(3)
>>> print(dict1.get(3))
None

如果找不到,可设置默认返回的参数

>>> dict1.get(3,'没有')
'没有'
>>> dict1.get(1,'没有')
'一'

9、判断键有无

可以用成员资格运算符in / not in

>>>2 in dict1
True

10、clear()方法–删除

Python 字典 clear() 函数用于删除字典内所有元素(清空字典)。

>>> dict1.clear()
>>> dict1
{}

11、copy()方法

返回一个字典的浅拷贝(复制)。相当于一个新的字典(指向的位置不同)

>>> a={1:'one',2:'two',3:'three'}
>>> b=a.copy()
>>> c=a
>>> a
{1: 'one', 2: 'two', 3: 'three'}
>>> b
{1: 'one', 2: 'two', 3: 'three'}
>>> c
{1: 'one', 2: 'two', 3: 'three'}
>>> id(a)    #位置不同
66060112
>>> id(b)
61184752
>>> id(c)
66060112
>>> c[4]='four'
>>> c
{1: 'one', 2: 'two', 3: 'three', 4: 'four'}
>>> a
{1: 'one', 2: 'two', 3: 'three', 4: 'four'}
>>> b
{1: 'one', 2: 'two', 3: 'three'}

12、pop()方法–删除

描述
Python 字典 pop() 方法删除字典给定键 key 所对应的值,返回值为被删除的值。key值必须给出。 否则,返回default值。

语法
pop(key[,default])

参数
key: 要删除的键值
default: 如果没有 key,返回 default 值

返回值
返回被删除的值。

>>> a.pop(2)
'two'
>>> a
{1: 'one', 3: 'three', 4: 'four'}

13、popitem()方法

描述
Python 字典 popitem() 方法随机返回并删除字典中的最后一对键和值。
如果字典已经为空,却调用了此方法,就报出KeyError异常。

语法
popitem()

参数

返回值
返回一个键值对(key,value)形式,按照 LIFO(Last In First Out 后进先出法) 顺序规则,即最末尾的键值对。

>>> a.popitem()             #随机弹出来
(4, 'four')
>>> a
{1: 'one', 3: 'three'}

14、setdefault() 方法

描述
Python 字典 setdefault() 方法和 get()方法 类似, 如果键不已经存在于字典中,将会添加键并将值设为默认值。

语法
dict.setdefault(key, default=None)

参数
key – 查找的键值。
default – 键不存在时,设置的默认键值。

返回值
如果 key 在 字典中,返回对应的值。如果不在字典中,则插入 key 及设置的默认值 default,并返回 default ,default 默认值为 None。

实例

>>> a.setdefault('小白')
>>> a
{1: 'one', 3: 'three', '小白': None}
>>> a.setdefault(5,'five')
'five'
>>> a
{1: 'one', 3: 'three', '小白': None, 5: 'five'}

15、update() 方法

根据映射关系更新字典
描述
Python 字典 update() 函数把字典参数 dict2 的 key/value(键/值) 对更新到字典 dict 里。

语法
dict.update(dict2)

参数
dict2 – 添加到指定字典dict里的字典。

返回值 该方法没有任何返回值。

实例

>>> a
{1: 'one', 3: 'three', '小白': None, 5: 'five'}
>>> b={'小白':'狗'}
>>> a.update(b)
>>> a
{1: 'one', 3: 'three', '小白': '狗', 5: 'five'}

16、循环遍历

遍历 就是 依次 从 字典 中获取所有键值对

# for 循环内部使用的 `key 的变量` in 字典
for k in xiaoming:
    print("%s: %s" % (k, xiaoming[k]))

提示:在实际开发中,由于字典中每一个键值对保存数据的类型是不同的,所以针对字典的循环遍历需求并不是很多

九、集合

集合是无序的,不能用下标的方式访问。

>>> num={}
>>> type(num)
<class 'dict'>
>>> num2={1,2,3,4,5}
>>> type(num2)          #{}并不是决定它是字典的因素
<class 'set'>

集合里面所有的元素都是唯一的,具有唯一性。

>>> num2={1,2,3,4,5,5,4,3,2}
>>> num2
{1, 2, 3, 4, 5}

不支持索引,会报错

>>> num2[2]
Traceback (most recent call last):
  File "<pyshell#114>", line 1, in <module>
    num2[2]
TypeError: 'set' object is not subscriptable

set={1,1.0}:
集合内容是{1.0},因为在PYthon的哈希函数会将相同的值的元素计算得到相同的地址,所以1和1.0是等值的。

1、创建集合set()

一种是直接把一堆元素用花括号括起来
一种是使用set( )工厂函数

>>> set1=set([1,2,3,4,5,5])
>>> set1
{1, 2, 3, 4, 5}

2、去除列表重复元素set()

未学集合前,只能这样:

>>> num1=[1,2,3,4,5,5,3,1,0]
>>> temp=[]
>>> for each in num1:
	if each not in temp:
		temp.append(each)
>>> temp
[1, 2, 3, 4, 5, 0]

学了集合之后:(先变成集合,在变成列表,不过不能保证原来列表的顺序了,因为先转为集合的时候是无序的)

>>> num1=list(set(num1))
>>> num1
[0, 1, 2, 3, 4, 5]

3、访问集合中的值

可以使用for把集合中的数据一个个读取出来
可以通过in和not in判断一个元素是否在集合中已经存在

>>> num2
{1, 2, 3, 4, 5}
>>> 1 in num2
True

其他:

>>> num2
{1, 2, 3, 4, 5}
>>> num2.add(6)
>>> num2
{1, 2, 3, 4, 5, 6}
>>> num2.remove(5)
>>> num2
{1, 2, 3, 4, 6}

4、不可变集合frozen

这样创建的集合是不能改变的。
添加元素会报错:

>>> num3=frozenset([1,2,3,4,5])
>>> num3.add(0)

5、集合类型内建方法

集合(s).方法名等价符号方法说明
s.issubset(t)s <= t子集测试(允许不严格意义上的子集):s 中所有的元素都是 t 的成员
s < t子集测试(严格意义上):s != t 而且 s 中所有的元素都是 t 的成员
s.issuperset(t)s >= t超集测试(允许不严格意义上的超集):t 中所有的元素都是 s 的成员
s > t超集测试(严格意义上):s != t 而且 t 中所有的元素都是 s 的成员
s.union(t)s | t合并操作:s “或” t 中的元素
s.intersection(t)s & t交集操作:s “与” t 中的元素
s.differences - t差分操作:在 s 中存在,在 t 中不存在的元素
s.symmetric_difference(t)s ^ t对称差分操作:s “或” t 中的元素,但不是 s 和 t 共有的元素
s.copy()返回 s 的拷贝(浅复制)
以下方法仅适用于可变集合
s.updates |= t将 t 中的元素添加到 s 中
s.intersection_update(t)s &= t交集修改操作:s 中仅包括 s 和 t 中共有的成员
s.difference_update(t)s -= t差修改操作:s 中包括仅属于 s 但不属于 t 的成员
s.symmetric_difference_update(t)s ^= t对称差分修改操作:s 中包括仅属于 s 或仅属于 t 的成员
s.add(obj)加操作:将 obj 添加到 s
s.remove(obj)删除操作:将 obj 从 s 中删除,如果 s 中不存在 obj,将引发异常
s.discard(obj)丢弃操作:将 obj 从 s 中删除,如果 s 中不存在 obj,也没事儿_
s.pop()弹出操作:移除并返回 s 中的任意一个元素
s.clear()清除操作:清除 s 中的所有元素

十、文件

1、打开文件open()

open() 方法用于打开一个文件,并返回文件对象,在对文件进行处理过程都需要使用到这个函数,如果该文件无法被打开,会抛出 OSError。

**注意:**使用 open() 方法一定要保证关闭文件对象,即调用 close() 方法。
open() 函数常用形式是接收两个参数:文件名(file)和模式(mode)。

open(file, mode='r')

完整的语法格式为:

open(file, mode='r', buffering=-1, encoding=None, errors=None, newline=None, closefd=True, opener=None)

参数说明:
file: 必需,文件路径(相对或者绝对路径)/文件名。
mode: 可选,文件打开模式
buffering: 设置缓冲
encoding: 一般使用utf8
errors: 报错级别
newline: 区分换行符
closefd: 传入的file参数类型
opener:
如果read()方法报错,在open函数的最后加一个参数,encoding=‘utf-8’

2、文件打开模式

打开模式执行操作
‘r’以只读的方式打开文件(默认)
‘w’以写入的方式打开文件,会覆盖已存在的文件
‘x’以写入的方式打开文件,如果文件已经存在,使用此模式打开将引发异常
‘a’以写入模式打开,如果文件存在,则在末尾追加写入
‘b’以二进制模式打开文件
‘t’以文本模式打开(默认)
‘+’可读写模式(可添加到其他模式中使用)
‘U’通用换行符支持

3、文件对象方法

文件对象方法执行操作
f.close()关闭文件
f.read([size=-1])从文件读取size个字符,当未给定size或给定负值的时候,读取剩余的所有字符,然后作为字符串返回
f.readline([size=-1])从文件中读取并返回一行(包括行结束符),如果有size有定义则返回size个字符
f.write(str)将字符串str写入文件
f.writelines(seq)向文件写入字符串序列seq,seq应该是一个返回字符串的可迭代对象
f.seek(offset, from)在文件中移动文件指针,从from(0代表文件起始位置,1代表当前位置,2代表文件末尾)偏移offset个字节
f.tell()返回当前在文件中的位置(当前文件指针的位置)
f.truncate([size=file.tell()])截取文件到size个字节,默认是截取到文件指针当前位置

(1)读取文件

read(10)将返回从文件指针开始(注意这里并不是文件头哦)的连续10个字符。

>>> f=open('D:\\2000\\B.txt',encoding='utf-8')
>>> f.read()
'上山打老虎a1,\n老虎不吃面b2.'       #此时指针位置已经在最后了,所以继续read(2)的话,并不会返回前两个字符。
>>> f.read(2)
''               #''内啥也没有

>>> f=open('D:\\2000\\B.txt',encoding='utf-8')
>>> f.read(5)
'上山打老虎'

>>> f.tell()        #此时返回上面5个字符后的位置
15

>>> f.seek(15,0)      #这里的第一个参数,由于一开始定义的是utf8编码,不能卡在一个字符中间比如14,会报错。
15
>>> f.readline()
'a1,\n'
①迭代打印出问价对象 f 中的每一行数据:
>>> f.seek(0,0)       #可以直接用for一行行读取
0
>>> for each_line in f:
	print(each_line)
上山打老虎a1,

老虎不吃面b2.
②将一个文件对象 f 中的数据存放进列表中:
>>> list( f )

(2)写入文件

注意: 写入时一定要把文件对象设置成可写入。

>>> f=open('D:\\2000\\D.txt','w')
>>> f.write('我爱小脑斧!')
6                     #写入了6个字符
>>> f.close()         #关闭缓存才会写入

2、练习

任务:将文件(record.txt)中的数据进行分割并按照以下规律保存起来:
——小甲鱼的对话单独保存为boy_.txt的文件(去掉“小甲鱼:”)
——小客服的对话单独保存为girl_
.txt的文件(去掉“小客服:”)
——文件中总共有三段对话,分别保存为boy_1.txt,girl_1.txt,boy_2.txt,girl_2.txt,boy_3.txt,girl_3.txt共有6个文件(提示:文件中不同的对话间已经使用“==========”分割)

def save_file(boy,girl,count):
    file_name_boy='boy_'+str(count)+'.txt'
    file_name_girl='girl_'+str(count)+'.txt'

    boy_file=open(file_name_boy,'w') #以写入的方式打开
    girl_file=open(file_name_girl,'w')

    boy_file.writelines(boy)
    girl_file.writelines(girl)

    boy_file.close()
    girl_file.close()

def split_file(file_name):
    f=open(file_name)

    boy=[]
    girl=[]
    count=1

    for each_line in f:
        if each_line[:6]!='======':
            (role,line_spoken)=each_line.split(':',1)
            #'='后面的意思是用split()方法对每行进行切片,
            #返回包含两个元素的列表。再将这两个元素分别赋
            #值给role和line_spoken这两个变量。
            if role=='小甲鱼':
                boy.append(line_spoken)
            if role=='小客服':
                girl.append(line_spoken)
        else:
            save_file(boy,girl,count)

            boy=[]
            girl=[]
            count+=1

    save_file(boy,girl,count)

    #打开的文件还没有关闭,所以要关闭
    f.close()
    
split_file('D:/2000/record.txt')

3、文件系统 OS模块

模块是一个包含所有你定义的函数和变量的文件,其后缀名是.py。模块可以被别的程序引入,以使用该模块中的函数等功能。
OS模块
OS: Operating System操作系统
Python是跨平台的语言,也即是说同样的源代码在不同的操作系统不需要修改就可以同样实现。
因此Python的作者就倒腾了OS模块这么一个玩意儿出来,有了OS模块,我们不需要关心什么操作系统下使用什么模块,OS模块会帮你选择正确的模块并调用。
os模块中关于文件/目录常用的函数使用方法

函数名使用方法
getcwd()返回当前工作目录
chdir(path)改变工作目录(参数是字符串)
listdir(path=’.’)列举指定目录中的文件名(’.‘表示当前目录,’…'表示上一级目录)
mkdir(path)创建单层目录,如该目录已存在抛出异常
makedirs(path)递归创建多层目录,如该目录已存在抛出异常,注意:'E:\a\b’和’E:\a\c’并不会冲突
remove(path)删除文件
rmdir(path)删除单层目录,如该目录非空则抛出异常
removedirs(path)递归删除目录,从子目录到父目录逐层尝试删除,遇到目录非空则抛出异常
rename(old, new)将文件old重命名为new
system(command)运行系统的shell命令
walk(top)遍历top路径以下所有的子目录,返回一个三元组:(路径, [包含目录], [包含文件])【具体实现方案请看:第30讲课后作业_
以下是支持路径操作中常用到的一些定义,支持所有平台
os.curdir指代当前目录(’.’)
os.pardir指代上一级目录(’…’)
os.sep输出操作系统特定的路径分隔符(Win下为’\’,Linux下为’/’)
os.linesep当前平台使用的行终止符(Win下为’\r\n’,Linux下为’\n’)
os.name指代当前使用的操作系统(包括:‘posix’, ‘nt’, ‘mac’, ‘os2’, ‘ce’, ‘java’)

os.path模块中关于路径常用的函数使用方法

函数名使用方法
basename(path)去掉目录路径,单独返回文件名
dirname(path)去掉文件名,单独返回目录路径
join(path1[, path2[, …]])将path1, path2各部分组合成一个路径名
split(path)分割文件名与路径,返回(f_path, f_name)元组。如果完全使用目录,它也会将最后一个目录作为文件名分离,且不会判断文件或者目录是否存在
splitext(path)分离文件名与扩展名,返回(f_name, f_extension)元组
getsize(file)返回指定文件的尺寸,单位是字节
getatime(file)返回指定文件最近的访问时间(浮点型秒数,可用time模块的gmtime()或localtime()函数换算)
getctime(file)返回指定文件的创建时间(浮点型秒数,可用time模块的gmtime()或localtime()函数换算)
getmtime(file)返回指定文件最新的修改时间(浮点型秒数,可用time模块的gmtime()或localtime()函数换算)
以下为函数返回 True 或 False
exists(path)判断指定路径(目录或文件)是否存在
isabs(path)判断指定路径是否为绝对路径
isdir(path)判断指定路径是否存在且是一个目录
isfile(path)判断指定路径是否存在且是一个文件
islink(path)判断指定路径是否存在且是一个符号链接
ismount(path)判断指定路径是否存在且是一个挂载点
samefile(path1, paht2)判断path1和path2两个路径是否指向同一个文件
>>>time.gmtime(os.path.getatime('E:\\text.txt'))
>>>time.localtime(os.path.getatime('E:\\text.txt'))

4、永久存储

pickle模块 (存放:pickling 读取:unpickling)
pickle提供了一个简单的持久化功能。可以将对象以文件的形式存放在磁盘上。
pickle模块只能在python中使用,python中几乎所有的数据类型(列表,字典,集合,类等)都可以用pickle来序列化,
pickle序列化后的数据,可读性差,人一般无法识别。

pickle.dump(obj, file[, protocol]):序列化对象,并将结果数据流写入到文件对象中。参数protocol是序列化模式,默认值为0,表示以文本的形式序列化。protocol的值还可以是1或2,表示以二进制的形式序列化。

pickle.load(file):反序列化对象。将文件中的数据解析为一个Python对象。
其中要注意的是,在load(file)的时候,要让python能够找到类的定义,否则会报错。

#把列表做成泡菜
>>> import pickle
>>> my_list=[123,3.1]
>>> my_list=[123,3.14,'小甲鱼',['another list']]

>>> pickle_file=open('my_list.pkl','wb')    #后缀名可随意起,文件打开模式为wb
>>> pickle.dump(my_list,pickle_file)     #倒进缸里
>>> pickle_file.close()       #此时问价打开是乱码,因为是用二进制保存的

>>> pickle_file=open('my_list.pkl','rb')    #重新打开以可读的方式
>>> my_list2=pickle.load(pickle_file)     #load()是读取
>>> print(my_list2)          #又恢复了
[123, 3.14, '小甲鱼', ['another list']]

十一、异常处理

1、Python标准异常总结

AssertionError断言语句(assert)失败
AttributeError尝试访问未知的对象属性
EOFError用户输入文件末尾标志EOF(Ctrl+d)
FloatingPointError浮点计算错误
GeneratorExitgenerator.close()方法被调用的时候
ImportError导入模块失败的时候
IndexError索引超出序列的范围
KeyError字典中查找一个不存在的关键字
KeyboardInterrupt用户输入中断键(Ctrl+c)
MemoryError内存溢出(可通过删除对象释放内存)
NameError尝试访问一个不存在的变量
NotImplementedError尚未实现的方法
OSError操作系统产生的异常(例如打开一个不存在的文件)
OverflowError数值运算超出最大限制
ReferenceError弱引用(weak reference)试图访问一个已经被垃圾回收机制回收了的对象
RuntimeError一般的运行时错误
StopIteration迭代器没有更多的值
SyntaxErrorPython的语法错误
IndentationError缩进错误
TabErrorTab和空格混合使用
SystemErrorPython编译器系统错误
SystemExitPython编译器进程被关闭
TypeError不同类型间的无效操作
UnboundLocalError访问一个未初始化的本地变量(NameError的子类)
UnicodeErrorUnicode相关的错误(ValueError的子类)
UnicodeEncodeErrorUnicode编码时的错误(UnicodeError的子类)
UnicodeDecodeErrorUnicode解码时的错误(UnicodeError的子类)
UnicodeTranslateErrorUnicode转换时的错误(UnicodeError的子类)
ValueError传入无效的参数
ZeroDivisionError除数为零

2、Python 内置异常类的层次结构:

BaseException
+-- SystemExit
+-- KeyboardInterrupt
+-- GeneratorExit
+-- Exception
      +-- StopIteration
      +-- ArithmeticError
      |    +-- FloatingPointError
      |    +-- OverflowError
      |    +-- ZeroDivisionError
      +-- AssertionError
      +-- AttributeError
      +-- BufferError
      +-- EOFError
      +-- ImportError
      +-- LookupError
      |    +-- IndexError
      |    +-- KeyError
      +-- MemoryError
      +-- NameError
      |    +-- UnboundLocalError
      +-- OSError
      |    +-- BlockingIOError
      |    +-- ChildProcessError
      |    +-- ConnectionError
      |    |    +-- BrokenPipeError
      |    |    +-- ConnectionAbortedError
      |    |    +-- ConnectionRefusedError
      |    |    +-- ConnectionResetError
      |    +-- FileExistsError
      |    +-- FileNotFoundError
      |    +-- InterruptedError
      |    +-- IsADirectoryError
      |    +-- NotADirectoryError
      |    +-- PermissionError
      |    +-- ProcessLookupError
      |    +-- TimeoutError
      +-- ReferenceError
      +-- RuntimeError
      |    +-- NotImplementedError
      +-- SyntaxError
      |    +-- IndentationError
      |         +-- TabError
      +-- SystemError
      +-- TypeError
      +-- ValueError
      |    +-- UnicodeError
      |         +-- UnicodeDecodeError
      |         +-- UnicodeEncodeError
      |         +-- UnicodeTranslateError
      +-- Warning
           +-- DeprecationWarning
           +-- PendingDeprecationWarning
           +-- RuntimeWarning
           +-- SyntaxWarning
           +-- UserWarning
           +-- FutureWarning
           +-- ImportWarning
           +-- UnicodeWarning
           +-- BytesWarning
           +-- ResourceWarning

3、try-except语句

try:
	检测范围
except Exception[as reason]:   #Exception是异常的名字(也可以把多个异常名字括起来,只要其中一个异常发生就会弹出).[]里面的是出错原因参数
	出现异常(Exception)后的处理代码

例如:

try:
    f=open('文件.txt')   #实际上这个文件并不存在
    print(f.read())
    f.close()
except OSError:
    print('文件出错啦T_T')
    
>>> 
=========================== RESTART: D:\python\测试.py ===========================
文件出错啦T_T
try:
    f=open('文件.txt')   #实际上这个文件并不存在
    print(f.read())
    f.close()
except OSError as reason:
    print('文件出错啦T_T\n出错的原因是:'+str(reason))


>>> 
=========================== RESTART: D:\python\测试.py ===========================
文件出错啦T_T
出错的原因是:[Errno 2] No such file or directory: '文件.txt'
try:
    sum=1+'1'
    f=open('文件.txt')   #实际上这个文件并不存在
    print(f.read())
    f.close()
except (OSError,TypeError):
    print('出错啦')
    
>>> 
=========================== RESTART: D:\python\测试.py ===========================
出错啦

4、try-finally语句

try:
	检测范围
except Exception[as reason]:   #Exception是异常的名字(也可以把多个异常名字括起来,只要其中一个异常发生就会弹出).[]里面的是出错原因参数
	出现异常(Exception)后的处理代码
finally:
	无论如何都会被执行的代码

finally可以做善后工作,比如关闭文件,清理内存之类的

try:
    f=open('文件.txt','w')   
    print(f.write('我存在了!'))
    sum=1+'1'             #这个地方会出错不会继续执行下去,但把关闭缓存close放在finally里面,无论如何都会执行,就能把'我存在了!'写入到'文件.txt'
except (OSError,TypeError):
    print('出错啦')
finally:
    f.close()


=========================== RESTART: D:\python\测试.py ===========================
5
出错啦

5、raise语句

自己定义的异常

>>> raise ZeroDivisionError('除数为零的异常')
Traceback (most recent call last):
  File "<pyshell#3>", line 1, in <module>
    raise ZeroDivisionError('除数为零的异常')
ZeroDivisionError: 除数为零的异常

十二、else和with语句

1、丰富的else语句

try:
    int('abc')
except ValueError as reason:
    print('出错啦:'+str(reason))
else:
    print('没有任何异常!')


>>> 
=========================== RESTART: D:\python\测试.py ===========================
出错啦:invalid literal for int() with base 10: 'abc'
try:
    int('123')
except ValueError as reason:
    print('出错啦:'+str(reason))
else:
    print('没有任何异常!')


>>> 
=========================== RESTART: D:\python\测试.py ===========================
没有任何异常!

2、简洁的with语句

有一些任务,可能事先需要设置,事后做清理工作。对于这种场景,Python的with语句提供了一种非常方便的处理方式。其中一个很好的例子是文件处理,你需要获取一个文件句柄,从文件中读取数据,然后关闭文件句柄。
如果不用with语句,代码如下:

file = open("/tmp/foo.txt")
data = file.read()
file.close()

这里有两个问题。一是可能忘记关闭文件句柄;二是文件读取数据发生异常,没有进行任何处理。下面是处理异常的加强版本:

file = open("/tmp/foo.txt")
try:
    data = file.read()
finally:
    file.close()

这段代码运行良好,但是太冗长。这时候with便体现出了优势。 除了有更优雅的语法,with还可以很好的自动处理上下文环境产生的异常。下面是with版本的代码:

with open("/tmp/foo.txt") as file:
    data = file.read()

其他例子:

try:
    f=open('date.txt','w')  #因为这个文件本来就不存在,所以打开会出错
    for each_line in f:
        print(each_line)
except OSError as reason:
    print('出错啦!'+str(reason))
finally:
    f.close()

>>> 
=========================== RESTART: D:\python\测试.py ===========================
出错啦!not readable

用with后:with open 结束了会自动执行f.close()

try:
    with open('date.txt','w') as f: #因为这个文件本来就不存在,所以打开会出错
        for each_line in f:
            print(each_line)
except OSError as reason:
    print('出错啦!'+str(reason))

>>> 
=========================== RESTART: D:\python\测试.py ===========================
出错啦!not readable

十三、类和对象

1、面向对象编程

Python的self相当于C++的this指针。
self代表类的实例,而非类。


构造方法:(魔法方法:init())

def __init__(self,name):
		self.name=name

name mangling:名字改编,名字重整

  • 在python中定义私有变量只需要在变量名或函数名前加上"__"两个下划线,那么这个函数或变量就会为私有的了。
  • _类名__变量名
>>> class Person:
	__name='小甲鱼'
	def getName(self):
		return self.__name

	
>>> p=Person()
>>> p.__name
Traceback (most recent call last):
  File "<pyshell#14>", line 1, in <module>
    p.__name
AttributeError: 'Person' object has no attribute '__name'
>>> p.getName()
'小甲鱼'
>>> p._Person__name  ###########实际上是伪私有
'小甲鱼'

2、继承

如果子类中定义与父类同名的方法或属性,则会自动覆盖父类对应的方法或属性。

class DerivedClassName(BaseClassName):
      —————子类—————   ————父类——————
	......

多重继承:

class DerivedClassName(Base1,Base2,Base3):
	......

继承后如果想重写构造方法:调用未绑定的父类方法 / 使用super函数。

import random as r

class Fish:
    def __init__(self):
        self.x=r.randint(1,10)
        self.y=y.randint(1,10)
    def move(self):
        self.x-=1
        print("我的位置是:",self.x,self.y)

class Shark(Fish):####################################调用未绑定的父类方法
    def __init__(self):
        Fish.__init__(self)
        self.hungry=True
        
class Shark(Fish):#################################### 使用super函数
    def __init__(self):
        super.__init__()
        self.hungry=True        

3、组合

把类的实例化,放到一个新类里面,就把旧类组合进去了

class Turtle:
    def __init__(self,x):
        self.num=x

class Fish:
    def __init__(self,x):
        self.num=x

class Pool:
    def __init__(self,x,y):
        self.turtle=Turtle(x)
        self.fish=Fish(y)
    def print_num(self):
        print("水池里总共有乌龟%d只,小鱼%d条!"%(self.turtle.num,self.fish.num))
-----------------------------------------------------------------------------------------------
>>> pool=Pool(1,10)

>>> pool.print_num()
水池里总共有乌龟1只,小鱼10条!

4、类、类对象、实例对象

实例对象比较特别。类对象创建后,只有在程序退出的时候才会消失。

>>> class C:
	count=0
_____________________
>>> a=C()
>>> b=C()
>>> c=C()
>>> 
>>> a.count
0
>>> b.count
0
>>> c.count
0
_____________________
>>> c.count += 10   ##对c的属性进行赋值,就相当于生成了一个count来覆盖了类对象的count
>>> c.count
10
>>> a.count
0
_____________________
>>> C.count += 100   ##对上面c的属性进行赋值,就相当于生成了一个count来覆盖了类对象的count
>>> a.count
100
>>> b.count
100
>>> c.count    ##所以才是10
10
类定义               C           类中定义的属性都是静态属性,相当于java语言里的static
                     |
类对象               C           类属性和类对象是相互绑定的,并不会依赖下面的实例对象
             |```````|```````|
实例对象     a       b       c   所以c.count += 10的时候,并不会影响上面的C,它只是改变的它自身,+10的时候多出了个count属性,这是实例属性把类属性给覆盖了。

如果属性的名字跟方法名字相同,属性会把方法覆盖掉

>>> class C:
	def x(self):
		print("X-man!")

		
>>> c=C()
>>> c.x()
X-man!
>>> c.x=1  #创建一个属性,属于c,这个实例对象的属性
>>> c.x
1
>>> c.x()  ###出现错误

5、一些相关的BIF

>>> class A:
	pass

>>> class B(A):
	pass

>>> class C():
	pass
  • issubclass(class,classinfo):判断一个类是否为另一个类的子类。第一个参数是第二个参数的子类就返回True。
    ①一个类被认为是其自身的子类
    ②classinfo可以是类对象组成的元组,只要class与其中任何一个候选类的子类,则返回True
>>> issubclass(B,A)
True
>>> issubclass(B,B)
True
>>> issubclass(B,object)
True
>>> issubclass(B,C)
False
  • isinstance(object,classinfo):判断对象 a 是否为 类 A 的实例对象。检查一个实例对象是否属于一个类,第一个参数传入一个实例对象,第二个参数传入一个类(也可以传入一个元组,一个个的去检查),有的话返回True。
    ①如果第一个参数不是对象,则永远返回False
    ②如果第二个参数不是类或者由类对象组成的元组,会抛出一个TypeError异常
>>> b1=B()
>>> isinstance(b1,B)
True
>>> isinstance(b1,A)
True
>>> isinstance(b1,C)
False
>>> isinstance(b1,(A,B,C))
True
  • hasattr(object, 'name'):判断属性是否存在。第一个参数object对象,第二个参数属性名,第二个属于第一个中的就返回True
    getattr(object, 'name'[,default]):设置 default 参数。返回对象的指定属性值
    上面那俩方法:避免访问对象不存在的属性(不产生异常)

setattr(object, 'name',value):与getattr对应,可以设定对象中指定属性的值,若指定的属性不存在,那么他会新建一个新的属性,并给他赋值。
delattr(object, 'name'):与setattr相反,是用于删除对象中指定的属性,若指定的属性不存在,那么他会抛出AttributeError的异常。(delattr(x,‘foobar’)相当于del x.foobar)

>>> class C:
	def __init__(self,x=0):
		self.x=x

		
>>> c1=C()
>>> hasattr(c1,'x')
True
>>> getattr(c1,'x')
0
>>> getattr(c1,'y',"您所访问的属性不存在...")
'您所访问的属性不存在...'
>>> setattr(c1,'y','FishC')
>>> getattr(c1,'y',"您所访问的属性不存在...")
'FishC'
>>> delattr(c1,'y')
>>> delattr(c1,'y')
Traceback (most recent call last):
  File "<pyshell#79>", line 1, in <module>
    delattr(c1,'y')
AttributeError: y
  • property(fget=None,fset=None,fdel=None,doc=None): 通过属性来设置(定义好的)属性 ,第一个参数是获取属性的方法,第二个参数设是置属性的方法,第三个参数是删除属性的方法,
>>> class C:
	def __init__(self,size=10):
		self.size=size
	def getSize(self):
		return self.size
	def setSize(self,value):
		self.size=value
	def delSize(self):
		del self.size
	x=property(getSize,setSize,delSize)#返回值是一个属性所以 x=

	
>>> c1=C()
>>> c1.getSize()
10
>>> c1.x
10
>>> c1.x=18
>>> c1.x
18
>>> c1.size
18
>>> c1.getSize()
18
>>> del c1.x

十四、魔法方法

1、构造和析构

  • 魔法方法总是被双下划线包围,例如__init__
    init(self[, …])

  • 第一个被调用的其实是__new__(cls[ , …]):第一个参数是这个类,通常返回class这个类的实例对象
    继承不可变类型的、又不可修改的时候重写,一般不重写。
    将字符串全部转换成大写:

>>> class CapStr(str):
	def __new__(cls,string):
		string = string.upper()
		return str.__new__(cls,string)

	
>>> a=CapStr("I love FishC.com!")
>>> a
'I LOVE FISHC.COM!'
  • del(self):析构器,当方法要销毁的时候,这个方法就自动被调用

2、算数运算魔法方法详解

魔法方法含义
基本的魔法方法
__new__(cls[, ...])1. new 是在一个对象实例化的时候所调用的第一个方法 2. 它的第一个参数是这个类,其他的参数是用来直接传递给 init 方法 3. new 决定是否要使用该 init 方法,因为 new 可以调用其他类的构造方法或者直接返回别的实例对象来作为本类的实例,如果 new 没有返回实例对象,则 init 不会被调用 4. new 主要是用于继承一个不可变的类型比如一个 tuple 或者 string
__init__(self[, ...])构造器,当一个实例被创建的时候调用的初始化方法
__del__(self)析构器,当一个实例被销毁的时候调用的方法
__call__(self[, args...])允许一个类的实例像函数一样被调用:x(a, b) 调用 x.call(a, b)
__len__(self)定义当被 len() 调用时的行为
__repr__(self)定义当被 repr() 调用时的行为
__str__(self)定义当被 str() 调用时的行为
__bytes__(self)定义当被 bytes() 调用时的行为
__hash__(self)定义当被 hash() 调用时的行为
__bool__(self)定义当被 bool() 调用时的行为,应该返回 True 或 False
__format__(self, format_spec)定义当被 format() 调用时的行为
有关属性
__getattr__(self, name)定义当用户试图获取一个不存在的属性时的行为
__getattribute__(self, name)定义当该类的属性被访问时的行为
__setattr__(self, name, value)定义当一个属性被设置时的行为
__delattr__(self, name)定义当一个属性被删除时的行为
__dir__(self)定义当 dir() 被调用时的行为
__get__(self, instance, owner)定义当描述符的值被取得时的行为
__set__(self, instance, value)定义当描述符的值被改变时的行为
__delete__(self, instance)定义当描述符的值被删除时的行为
比较操作符
__lt__(self, other)定义小于号的行为:x < y 调用 x.lt(y)
__le__(self, other)定义小于等于号的行为:x <= y 调用 x.le(y)
__eq__(self, other)定义等于号的行为:x == y 调用 x.eq(y)
__ne__(self, other)定义不等号的行为:x != y 调用 x.ne(y)
__gt__(self, other)定义大于号的行为:x > y 调用 x.gt(y)
__ge__(self, other)定义大于等于号的行为:x >= y 调用 x.ge(y)
`算数运算符
__add__(self, other)定义加法的行为:+
__sub__(self, other)定义减法的行为:-
__mul__(self, other)定义乘法的行为:*
__truediv__(self, other)定义真除法的行为:/
__floordiv__(self, other)定义整数除法的行为://
__mod__(self, other)定义取模算法的行为:%
__divmod__(self, other)定义当被 divmod() 调用时的行为
__pow__(self, other[, modulo])定义当被 power() 调用或 ** 运算时的行为
__lshift__(self, other)定义按位左移位的行为:<<
__rshift__(self, other)定义按位右移位的行为:>>
__and__(self, other)定义按位与操作的行为:&
__xor__(self, other)定义按位异或操作的行为:^
__or__(self, other)定义按位或操作的行为:
反运算
__radd__(self, other)(与上方相同,当左操作数不支持相应的操作时被调用)
__rsub__(self, other)(与上方相同,当左操作数不支持相应的操作时被调用)
__rmul__(self, other)(与上方相同,当左操作数不支持相应的操作时被调用)
__rtruediv__(self, other)(与上方相同,当左操作数不支持相应的操作时被调用)
__rfloordiv__(self, other)(与上方相同,当左操作数不支持相应的操作时被调用)
__rmod__(self, other)(与上方相同,当左操作数不支持相应的操作时被调用)
__rdivmod__(self, other)(与上方相同,当左操作数不支持相应的操作时被调用)
__rpow__(self, other)(与上方相同,当左操作数不支持相应的操作时被调用)
__rlshift__(self, other)(与上方相同,当左操作数不支持相应的操作时被调用)
__rrshift__(self, other)(与上方相同,当左操作数不支持相应的操作时被调用)
__rand__(self, other)(与上方相同,当左操作数不支持相应的操作时被调用)
__rxor__(self, other)(与上方相同,当左操作数不支持相应的操作时被调用)
__ror__(self, other)(与上方相同,当左操作数不支持相应的操作时被调用)
增量赋值运算
__iadd__(self, other)定义赋值加法的行为:+=
__isub__(self, other)定义赋值减法的行为:-=
__imul__(self, other)定义赋值乘法的行为:*=
__itruediv__(self, other)定义赋值真除法的行为:/=
__ifloordiv__(self, other)定义赋值整数除法的行为://=
__imod__(self, other)定义赋值取模算法的行为:%=
__ipow__(self, other[, modulo])定义赋值幂运算的行为:**=
__ilshift__(self, other)定义赋值按位左移位的行为:<<=
__irshift__(self, other)定义赋值按位右移位的行为:>>=
__iand__(self, other)定义赋值按位与操作的行为:&=
__ixor__(self, other)定义赋值按位异或操作的行为:^=
__ior__(self, other)定义赋值按位或操作的行为:
一元操作符
__pos__(self)定义正号的行为:+x
__neg__(self)定义负号的行为:-x
__abs__(self)定义当被 abs() 调用时的行为
__invert__(self)定义按位求反的行为:~x
类型转换
__complex__(self)定义当被 complex() 调用时的行为(需要返回恰当的值)
__int__(self)定义当被 int() 调用时的行为(需要返回恰当的值)
__float__(self)定义当被 float() 调用时的行为(需要返回恰当的值)
__round__(self[, n])定义当被 round() 调用时的行为(需要返回恰当的值)
__index__(self)1. 当对象是被应用在切片表达式中时,实现整形强制转换 2. 如果你定义了一个可能在切片时用到的定制的数值型,你应该定义 `index 3. 如果 index 被定义,则 int 也需要被定义,且返回相同的值
上下文管理(with 语句)
__enter__(self)1. 定义当使用 with 语句时的初始化行为 2. enter 的返回值被 with 语句的目标或者 as 后的名字绑定
__exit__(self, exc_type, exc_value, traceback)1. 定义当一个代码块被执行或者终止后上下文管理器应该做什么 2. 一般被用来处理异常,清除工作或者做一些代码块执行完毕之后的日常工作
容器类型
__len__(self)定义当被 len() 调用时的行为(返回容器中元素的个数)
__getitem__(self, key)定义获取容器中指定元素的行为,相当于 self[key]
__setitem__(self, key, value)定义设置容器中指定元素的行为,相当于 self[key] = value
__delitem__(self, key)定义删除容器中指定元素的行为,相当于 del self[key]
__iter__(self)定义当迭代容器中的元素的行为
__reversed__(self)定义当被 reversed() 调用时的行为
__contains__(self, item)定义当使用成员测试运算符(in 或 not in)时的行为

3、一些魔法方法

__str__方法:

>>> class A():
	def __str__(self):
		return "小甲鱼是帅哥!"

	
>>> a=A()
>>> print(a)
小甲鱼是帅哥!

__repr__方法

>>> class B():
	def __repr__(self):
		return "小甲鱼是帅哥!"

	
>>> b=B()
>>> b
小甲鱼是帅哥!

4、属性访问

  • __getattr__(self,name):定义当用户试图获取一个不存在的属性时的行为。
  • __getattribute__(self,name):定义当该类的属性被访问时的行为。
  • __setattr__(self,name,value):定义当一个属性被设置时的行为。
  • __delattr__(self,name):定义当一个属性被删除时的行为。
>>> class C:
	def __getattribute__(self,name):
		print("getattribute")
		return super().__getattribute__(name)
	def __getattr__(self,name):
		print("getattr")
	def __setattr__(self,name,value):
		print("setattr")
		super().__setattr__(name,value)
	def __delattr__(self,name):
		print("delattr")
		super().__delattr__(name)

		
>>> c=C()
>>> c.x
getattribute
getattr
>>> c.x=1
setattr
>>> c.x
getattribute
1
>>> del c.x
delattr

5、描述符

描述符的作用是用来代理一个类的属性,描述符是一种类,我们把实现了__get__()、set()和__delete__()中的其中任意一种方法的类称之为描述符。

  • 描述符就是将某种特殊类型的类的实例指派给另一个类的属性。下面是属于描述符属性的方法
  • __get__(self,instance,owner):用于访问属性,它返回属性的值
  • __set__(self,instance,value):将在属性分配操作中调用,不返回任何内容
  • __delete__(self,instance):控制删除操作,不返回任何内容

###########能够被实例化,我们就说MyDecriptor是描述符#############:

>>> class MyDecriptor:
	def __get__(self,instance,owner):
		print("getting...",self,instance,owner)
	def __set__(self,instance,owner):
		print("setting...",self,instance,owner)
	def __delete__(self,instance):
		print("deleting...",self,instance)

		
>>> class Test:
	x=MyDecriptor() ###########能够被实例化,我们就说MyDecriptor是描述符#############

property其实就是一个描述符类,自己写一个property:

>>> class MyProperty:
	def __init__(self,fget=None,fset=None,fdel=None):
		self.fget=fget
		self.fset=fset
		self.fdel=fdel
	def __get__(self,instance,owner):
		return self.fget(instance)
	def __set__(self,instance,value):
		self.fset(instance,value)
	def __delete__(self,instance):
		self.fdel(instance)

		
>>> class C:
	def __init__(self):
		self._x=None#下划线是不希望被外部访问
	def getX(self):
		return self._x
	def setX(self,value):
		self._x=value
	def delX(self):
		del self._x
	x=MyProperty(getX,setX,delX)

	
>>> c=C()
>>> c.x='X-man'
>>> c.x
'X-man'
>>> c._x
'X-man'
>>> del c.x

上面解读:
1、这里其实触发了一连串的反应
2、以getX()方法为例,首先将类对象C中的getX()函数赋给了MyProperty中的fget
3、当调用实例对象c中的x(c.x)时,触发MyProperty中的__get__
4、随即触发类对象C中的getX()
5、而__get__()中的instance,就是getX()中的self
练习:

  • 先定义一个温度类,然后定义两个描述符类用于描述摄氏度和华氏度两个属性。
  • 要求两个属性会自动进行转换,也就是说你可以给摄氏度这个属性赋值,然后打印的华氏度属性是自动转换后的结果。
class Celsius:#描述符类
    def __init__(self,value=26.0):
        self.value=float(value)
    def __get__(self,instance,owner):
        return self.value
    def __set__(self,instance,value):
        self.value=float(value)
        
class Fahrenheit:#描述符类
    def __get__(self,instance,owner):
        return instance.cel*1.8+32
    def __set__(self,instance,value):
        instance.cel=(float(value)-32)/1.8

class Temperature:#温度类
    cel=Celsius()#摄氏度属性
    fah=Fahrenheit()#华氏度属性
    
=========================== RESTART: D:/python/温度计.py ==========================
>>> temp=Temperature()
>>> temp.cel
26.0
>>> temp.cel=30
>>> temp.fah
86.0
>>> temp.fah=100
>>> temp.cel
37.77777777777778

6、定制序列

(1)协议

协议(Protocols)与其他编程语言中的接口很相似,它规定你哪些方法必须要定义。然而,在Python中的协议就显得不那么正式。事实上,在Python中,协议更像是一种指南。

(2)容器类型的协议

  • 如果你希望定制的容器是不可变的话,你只需要定义__len__()和__getitem__()方法。比如字符串是不可变的。
  • 如果你希望定制的容器是可变的话,除了__len__()和__getitem__()方法,你还需要定义__setitem__()和__delitem__()两个方法。

7、迭代器

迭代器python提供了两个BIF:

  • iter():一个容器用这个方法就会得到一个迭代器
  • next():返回迭代器下一个值,如果没有值可以返回了,就抛出一个StopIteration异常

迭代器有两个魔法方法:这两个对应的就是上面两个的实现

  • __iter__()
  • __next__()
>>> string='FishC'
>>> it=iter(string)
>>> next(it)
'F'
>>> next(it)
'i'
>>> next(it)
's'
>>> next(it)
'h'
>>> next(it)
'C'
>>> next(it)
Traceback (most recent call last):
  File "<pyshell#134>", line 1, in <module>
    next(it)
StopIteration

8、生成器

所谓的协同程序就是可以运行的独立函数调用,函数可以暂停或者挂起,并在需要的时候从程序离开的地方继续或者重新开始。

>>> def myGen():
	print("生成器被调用!")
	yield 1
	yield 2 #一旦一个函数里出现yield语句,说明这个函数就被定义为生成器

	
>>> myG=myGen()
>>> next(myG)
生成器被调用!
1
>>> next(myG)
2
>>> next(myG)
Traceback (most recent call last):
  File "<pyshell#152>", line 1, in <module>
    next(myG)
StopIteration
>>> for i in myGen():
	print(i)

	
生成器被调用!
1
2
>>> #斐波那锲数列也可用yield来写
>>> def libs():#虽然执行流程仍按函数的流程执的行,但每执行到一个yield语句就会中断,每次中断都会通过yield返回当前迭代值
	a=0
	b=1
	while True:
		a,b=b,a+b
		yield a

		
>>> for each in libs():
	if each>100:
		break
	print(each,end='  ')

	
1  1  2  3  5  8  13  21  34  55  89

#列表推导式

>>> a=[i for i in range(100) if not(i%2) and i%3]
>>> a
[2, 4, 8, 10, 14, 16, 20, 22, 26, 28, 32, 34, 38, 40, 44, 46, 50, 52, 56, 58, 62, 64, 68, 70, 74, 76, 80, 82, 86, 88, 92, 94, 98]

#字典推导式

>>> b={i:i%2==0 for i in range(10)}#因为是字典所以有冒号 #通过字典的方式显示1到9的数字是否为偶数
>>> b
{0: True, 1: False, 2: True, 3: False, 4: True, 5: False, 6: True, 7: False, 8: True, 9: False}

#集合推导式

>>> c={i for i in [1,1,2,3,4,5,5,6,7,8,3,2,1]}
>>> c
{1, 2, 3, 4, 5, 6, 7, 8}#因为是集合所以不会显示重复的数字

#字符串推导式

>>> d="i for i in 'I love FishC.com!'"
>>> d
"i for i in 'I love FishC.com!'"

#元组推导式(生成器推导式)

>>> e=(i for i in range(10))
>>> e
<generator object <genexpr> at 0x043695A0>
>>> #上面generator关键字,e就是生成器推导式
>>> next(e)
0
>>> next(e)
1
>>> next(e)
2
>>> for each in e:
	print(each)

	
3
4
5
6
7
8
9

#生成器还可直接做函数的参数

>>> sum(i for i in range(100) if i%2)#把100之内不能够被2整除的数都加起来
2500

十五、模块

1、模块就是程序

模块就是封装

  • 容器 -> 数据的封装
  • 函数 -> 语句的封装
  • 类 -> 方法和属性的封装
  • 模块 -> 模块就是程序
    导入模块
  • 第一种:import 模块名
  • 第二种:from 模块名 import 函数名(若有多个函数名,之间用逗号隔开)
  • 第三种:import 模块名 as 新名字

2、name=='main’搜索路径和包

if __name__=='__main__'
__name__变量在主程序中得到的是一个__main__,在模块中得到的是模块的名字。

>>> __name__
'__main__'
>>> tc.__name__#在模块中调用
'TemperatureConversion'

例子:
下面的文件名字是TemperatureConversion.py是一个温度转换模块

#温度转换模块
def c2f(cel):
    fah=cel*1.8+32
    return fah
def f2c(fah):
    cel=(fah-32)/1.8
    return cel


#下面是测试语句
def test():
    print("测试,0摄氏度=%.2f华氏度"% c2f(0))
    print("测试,0华氏度=%.2f摄氏度"% f2c(0))
test()

下面写一个程序并导入上面那个模块:

import TemperatureConversion as tc

print("32摄氏度=%.2f华氏度"% tc.c2f(32))
print("99华氏度=%.2f摄氏度"% tc.f2c(99))

程序的结果还会带有测试的部分:

>>> 
========================== RESTART: D:\python\ceshi.py =========================
测试,0摄氏度=32.00华氏度
测试,0华氏度=-17.78摄氏度
32摄氏度=89.60华氏度
99华氏度=37.22摄氏度

所以要修改模块:(下面的if语句表示的是如果在其他程序里(就是__name__≠__main__)不运行test())

#温度转换模块
def c2f(cel):
    fah=cel*1.8+32
    return fah
def f2c(fah):
    cel=(fah-32)/1.8
    return cel


#下面是测试语句
def test():
    print("测试,0摄氏度=%.2f华氏度"% c2f(0))
    print("测试,0华氏度=%.2f摄氏度"% f2c(0))
if __name__=="__main__":
	test()

程序的结果就不会带有测试的部分:

>>> 
========================== RESTART: D:\python\ceshi.py =========================
32摄氏度=89.60华氏度
99华氏度=37.22摄氏度

(2)搜索路径

python模块的导入需要一个路径搜索的过程(导入的模块在哪里找,因为直接导入会出错)

>>> import sys
>>> sys.path
['C:\\Users\\lijin\\AppData\\Local\\Programs\\Python\\Python38-32\\python38.zip', 'C:\\Users\\lijin\\AppData\\Local\\Programs\\Python\\Python38-32\\DLLs', 'C:\\Users\\lijin\\AppData\\Local\\Programs\\Python\\Python38-32\\lib', 'C:\\Users\\lijin\\AppData\\Local\\Programs\\Python\\Python38-32', 'C:\\Users\\lijin\\AppData\\Local\\Programs\\Python\\Python38-32\\lib\\site-packages']#主要看这最后一个路径(最佳存放模块的路径)

>>> sys.path.append("D:\\python")#把这个路径加到搜索路径里
>>> sys.path
['C:\\Users\\lijin\\AppData\\Local\\Programs\\Python\\Python38-32\\python38.zip', 'C:\\Users\\lijin\\AppData\\Local\\Programs\\Python\\Python38-32\\DLLs', 'C:\\Users\\lijin\\AppData\\Local\\Programs\\Python\\Python38-32\\lib', 'C:\\Users\\lijin\\AppData\\Local\\Programs\\Python\\Python38-32', 'C:\\Users\\lijin\\AppData\\Local\\Programs\\Python\\Python38-32\\lib\\site-packages', 
'D:\\python']#最后多加了一个路径
>>> import TemperatureConversion#这样就能导入了
>>> TemperatureConversion.c2f(32)
89.6

(3)包

  • 1、创建一个文件夹,用于存放相关的模块,文件夹的名字即包的名字;
  • 2、在文件夹中创建一个__init__.py的模块文件,内容可以为空;
  • 3、将相关的模块放入文件夹中
  • 4、导入只需将包名加到模块名前就可import baoming.TemperatureConversion as tc

3、像个极客一样去思考

看视频去

十六、爬虫

1、论一只爬虫的自我修养

自带urllib(是一个包)
urllib是一个包,它收集了几个用于处理url的模块:

  • urllib.request 用于打开和阅读url
  • urlurllib.error 包含由urllib.request引发的异常
  • urllib.parse 解析url
  • urllib.robotparser 用于解析robots.txt文件

URL是统一资源定位符,表示资源的地址。

  • URL的一般格式为(带方括号[ ]的为可选项):
    protocol://hostname[:port]/path/[;parameters][?query]#fragment
  • URL由三部分组成:
    第一部分是协议:http,https,ftp,file,ed2k…
    第二部分是存放资源的服务器的域名系统或IP地址(有时候要包含端口号,各种传输协议都有默认的端口号,如http的默认端口为80)。
    第三部分是资源的具体地址,如目录或文件名。
import urllib.request
response=urllib.request.urlopen("http://placekitten.com/500/600")#此方法获得返回一个对象,在服务器上把整个网页获取的过程
html=response.read()#把对象读取出来(以二进制的形式)
print(html)#html也可打印出来
html=html.decode("utf-8")#解码操作,变成utf-8

urllib.request.urlopen这个函数总是返回一个对象,该对象可以作为上下文管理器工作,并具有以下方法:

  • geturl() -得到的是你访问的具体链接地址(返回所检索资源的URL,通常用于确定是否执行了重定向)
  • info()-得到的是HTTPMessage的对象(以电子邮件的形式返回页面的元信息,比如标题。实例(请参阅快速引用HTTP头信息))
  • getcode() -返回响应的HTTP状态码,200表示OK正常执行。

urllib.request.urlopen(url, data=None, [timeout, ]*, cafile=None, capath=None, cadefault=False, context=None)
此方法返回的是一个HTTPResponse的实例对象,它属于http.client模块,调用read()方法才能读出URL的内容。

若给data赋值,就以post的形式提交;
data参数必须用parse模块的函数解析后才能用urllib.parse.urlencode(query,doseq=False,safe='',encoding=None,errors=None)

2、实战

(1) 下载网站上猫的图片:

import urllib.request

response=urllib.request.urlopen("http://placekitten.com/500/600")#爬取的地址(返回一个对象(类文件/文件对象))
cat_img=response.read()
with open("cat_500_600.jpg","wb") as f:#cat_img用一个文件保存(第一个参数是文件名字,第二个参数是把二进制形式打开,并将数据写入JPG图片文件)
    f.write(cat_img)



====================== RESTART: D:\python\download_cat.py ======================
#执行上面那个程序就会下载一张图片
>>> response.geturl()#得到的是你访问的具体链接地址
'http://placekitten.com/500/600'
>>> response.info()#得到的是HTTPMessage的对象
<http.client.HTTPMessage object at 0x03B3CBF8>
>>> print(response.info())#把上面的打印出来,包含了远程服务器返回的信息
Date: Mon, 24 Aug 2020 01:20:50 GMT
Content-Type: image/jpeg
Transfer-Encoding: chunked
Connection: close
Set-Cookie: __cfduid=d8505bc0d76ba830f5a502656aa4d16c41598232050; expires=Wed, 23-Sep-20 01:20:50 GMT; path=/; domain=.placekitten.com; HttpOnly; SameSite=Lax
Cache-Control: public, max-age=86400
Expires: Thu, 31 Dec 2020 20:00:00 GMT
Vary: User-Agent, Accept-Encoding
Access-Control-Allow-Origin: *
CF-Cache-Status: HIT
Age: 41151
cf-request-id: 04bfa6d4da000078ea2a896200000001
Server: cloudflare
CF-RAY: 5c7940ce2aa478ea-LAX


>>> response.getcode()#得到的是HTTP的状态码,200表示OK正常执行
200

(2)利用有道词典翻译文本

在网页的代码测试页面,点Network,如果找不到Method栏的可以右键status打开Method栏。
Network->POST->Headers:

  • 一般通过Request Headers里面的User-Agent来识别是浏览器访问还是代码访问(可自定义以防阻止访问)
  • Form Data表单数据,POST提交的主要内容
import urllib.request
import urllib.parse
import json

content=input("请输入需要翻译的内容:")

url='http://fanyi.youdao.com/translate?smartresult=dict&smartresult=rule'
data={}#data是一个字典
data['i']= content
data['from']='AUTO'
data['to']='AUTO'
data['smartresult']='dict'
data['client']='fanyideskweb'
data['salt']='15982334264829'
data['sign']='ed9b041588fb22218d7ed22d23f562c2'
data['lts']='1598233426482'
data['bv']='ee7775aa36453cc1dee29ed153e6bfab'
data['doctype']='json'
data['version']='2.1'
data['keyfrom']='fanyi.web'
data['action']='FY_BY_CLICKBUTTION'
data=urllib.parse.urlencode(data).encode('utf-8')#把编码后的值赋值给data(把它硬编码成utf8的形式)

response=urllib.request.urlopen(url,data)#发出请求得到响应
html=response.read().decode('utf-8')#windows系统下不用decode()
#上面返回的结果是JSON结构。JSON是一种轻量级的数据交换格式,说白了这里就是用字符串把Pyhon的数据结构封装起来,便于存储和使用

target=json.loads(html)#把字符串载入,载入之后得到的是一个字典
print("翻译结果:%s"%(target['translateResult'][0][0]['tgt']))



==================== RESTART: D:/python/translation.py ====================
请输入需要翻译的内容:小甲鱼是帅哥
翻译结果:The little turtle is a handsome boy

JSON是一种轻量级的数据交换格式,说白了这里就是用字符串把Pyhon的数据结构封装起来,便于存储和使用

3、隐藏(机器访问)

服务器一般检查连接的Request Headers里面的User-Agent来判断是浏览器访问还是代码访问。
可修改headers来模拟浏览器访问:

  • 一、通过Request的headers参数修改
  • 二、通过Request.add_header()方法修改
    class urllib.request.Request(url, data=None, headers={}, origin_req_host=None, unverifiable=False, method=None)
    以有道翻译为例:
  • 方法一:直接添加一个head参数
import urllib.request
import urllib.parse
import json

content=input("请输入需要翻译的内容:")
url='http://fanyi.youdao.com/translate?smartresult=dict&smartresult=rule'

head={}
head['User-Agent']='Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.89 Safari/537.36'

data={}#data是一个字典
data['i']= content
data['from']='AUTO'
data['to']='AUTO'
data['smartresult']='dict'
data['client']='fanyideskweb'
data['salt']='15982334264829'
data['sign']='ed9b041588fb22218d7ed22d23f562c2'
data['lts']='1598233426482'
data['bv']='ee7775aa36453cc1dee29ed153e6bfab'
data['doctype']='json'
data['version']='2.1'
data['keyfrom']='fanyi.web'
data['action']='FY_BY_CLICKBUTTION'
data=urllib.parse.urlencode(data).encode('utf-8')#把编码后的值赋值给data(把它硬编码成utf8的形式)

req=urllib.request.Request(url,data,head)
response=urllib.request.urlopen(url,data)#发出请求得到响应
html=response.read().decode('utf-8')

target=json.loads(html)
print("翻译结果:%s"%(target['translateResult'][0][0]['tgt']))
  • 方法二:在req生成之后,通过add_header()方法:Request.add_header(key,val)
    先生成一个req对象,再在对象里动态追加add_header()
import urllib.request
import urllib.parse
import json

content=input("请输入需要翻译的内容:")
url='http://fanyi.youdao.com/translate?smartresult=dict&smartresult=rule'

data={}#data是一个字典
data['i']= content
data['from']='AUTO'
data['to']='AUTO'
data['smartresult']='dict'
data['client']='fanyideskweb'
data['salt']='15982334264829'
data['sign']='ed9b041588fb22218d7ed22d23f562c2'
data['lts']='1598233426482'
data['bv']='ee7775aa36453cc1dee29ed153e6bfab'
data['doctype']='json'
data['version']='2.1'
data['keyfrom']='fanyi.web'
data['action']='FY_BY_CLICKBUTTION'
data=urllib.parse.urlencode(data).encode('utf-8')#把编码后的值赋值给data(把它硬编码成utf8的形式)

req=urllib.request.Request(url,data)

req.add_header('User-Agent','Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.89 Safari/537.36')

response=urllib.request.urlopen(url,data)#发出请求得到响应
html=response.read().decode('utf-8')

target=json.loads(html)
print("翻译结果:%s"%(target['translateResult'][0][0]['tgt']))

为了防止频繁访问而拒之门外:第一可延迟提交时间,第二使用代理

  • 第一种:延迟提交时,使用time模块
import urllib.request
import urllib.parse
import json
import time

while True:
    content=input("请输入需要翻译的内容(输入'q!'退出程序):")
    if content=='q!':
        break
    
    url='http://fanyi.youdao.com/translate?smartresult=dict&smartresult=rule'

    data={}#data是一个字典
    data['i']= content
    data['from']='AUTO'
    data['to']='AUTO'
    data['smartresult']='dict'
    data['client']='fanyideskweb'
    data['salt']='15982334264829'
    data['sign']='ed9b041588fb22218d7ed22d23f562c2'
    data['lts']='1598233426482'
    data['bv']='ee7775aa36453cc1dee29ed153e6bfab'
    data['doctype']='json'
    data['version']='2.1'
    data['keyfrom']='fanyi.web'
    data['action']='FY_BY_CLICKBUTTION'
    data=urllib.parse.urlencode(data).encode('utf-8')#把编码后的值赋值给data(把它硬编码成utf8的形式)

    req=urllib.request.Request(url,data)
    req.add_header('User-Agent','Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.89 Safari/537.36')

    response=urllib.request.urlopen(url,data)#发出请求得到响应
    html=response.read().decode('utf-8')

    target=json.loads(html)
    print("翻译结果:%s"%(target['translateResult'][0][0]['tgt']))
    time.sleep(5)#休息5秒钟再进行下一次

  • 第二种:使用代理
    – 1.参数是一个字典{‘类型’:‘代理ip:端口号’}
    proxy_support=urllib.request.ProxyHandler({})
    – 2.定制、创建一个opener
    opener=urllib.request.build_opener(proxy_support)
    – 3a.安装opener
    urllib.request.install_opener(opener)
    – 3b.调用opener
    opener.open(url)
import urllib.request

url='http://45.32.164.128/ip.php'#能够测当前ip的网址

proxy_support=urllib.request.ProxyHandler({'http':'101.4.136.34:81'})
opener=urllib.request.build_opener(proxy_support)
#可修改opener的headers的值()
opener.addheaders=[('User-Agent','Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.89 Safari/537.36')]

urllib.request.install_opener(opener)
response=urllib.request.urlopen(url)#访问就可以了
html=response.read().decode('utf-8')

print(html)

13、变量进阶

十?、图形用户界面EasyGui

九、号外号外

1.打印不换行

>>>print(x,end='')

2.命令行中返回上一条记录

Alt+P

3、提示按键:Tab

4、两个值互换

>>> x=3
>>> y=5
>>> x,y=y,x
>>> print(x,y)
5 3

//x, y, z = z, y, x//三个值互换

5、查类有什么属性

>>>dd=CC()
>>>dd.__dict__
{} #没有属性

6、字符串变大写

.upper()方法

7、raise触发报错

if n>2:
	raise StopIteraion

8、r.json()

.json()是把json数据(一对大括号)转换成python字典

requests模块中,r.json()为Requests中内置的JSON解码器
其中只有response返回为json格式时,用r.json()打印出响应的内容,
如果response返回不为json格式,使用r.json()会报错

9、print

print("www","baidu","com",sep=".")
========***========
www.baidu.com

十、其他

1. IDLE 是什么?

IDLE是一个Python Shell,shell的意思就是“外壳”,基本上来说,就是一个通过键入文本与程序交互的途径!像我们Windows那个cmd窗口,像Linux那个黑乎乎的命令窗口,他们都是shell,利用他们,我们就可以给操作系统下达命令。同样的,我们可以利用IDLE这个shell与Python进行互动。

2. 什么是BIF?

BIF 就是 Built-in Functions,内置函数。为了方便程序员快速编写脚本程序(脚本就是要编程速度快快快!!!),Python 提供了非常丰富的内置函数,我们只需要直接调用即可,例如 print() 的功能是“打印到屏幕”,input() 的作用是接收用户输入(注:Python3 用 input() 取代了 Python2 的 raw_input() )。

3.Python3 提供了多少个 BIF?

在 Python 或 IDLE 中,输入 dir(__builtins__) 可以看到 Python 提供的内置方法列表(注意,builtins 前后是两个下划线哦)其中小写的就是 BIF。如果想具体查看某个 BIF 的功能,比如 input(),可以在 shell 中输入 help(input),就会得到这个 BIF 的功能描述。哦,答案应该是 68 个,不信你自己数数看T_T~。

//查看python中所有的内置函数
>>> dir(__builtins__) 

4.Python 中什么是最重要的?你赞同吗?

缩进!缩进是 Python 的灵魂,缩进的严格要求使得 Python 的代码显得非常精简并且有层次。
所以在 Python 里对待缩进代码要十分小心,如果没有正确地缩进,代码所做的事情可能和你的期望相去甚远(就像C语言里边括号打错了位置)。
如果在正确的位置输入冒号“:”,IDLE 会自动将下一行缩进!

if guess == 8:
    print("缩进"))
else:
    print("缩进")

5.“=”和“==”,他们表示不同的含义

C语言的话,如果 if( c == 1 ) 写成 if( c = 1 ),程序就完全不按程序员原本的目的去执行,但在 Python 这里,不好意思,行不通,语法错误!Python 不允许 if 条件中赋值,所以 if c = 1: 会报错!

6.str() 和 print() 都是内置函数,但 Python 貌似不介意我们对内置函数进行赋值操作,所以这点我们以后就要注意啦,否则可能会出现以下的 BUG:

>>> print = 1
>>> print("I love FishC")
Traceback (most recent call last):
  File "<pyshell#37>", line 1, in <module>
    print("I love FishC")
TypeError: 'int' object is not callable

7.while 后边的条件

在 Python 看来,只有以下内容会被看作假(注意冒号括号里边啥都没有,连空格都不要有!):False None 0 "" '' () [] {}
其他一切都被解释为真!

8.Python3 中,一行可以书写多个语句吗?

可以,语句之间用分号隔开即可,不妨试试:

>>> print('I love fishc');print('very much!')

9.Python3 中,一个语句可以分成多行书写吗?

可以,一行过长的语句可以使用反斜杠或者括号分解成几行,不妨试试:

>>> 3 > 4 and \
  1 < 2

或者

>>> ( 3 > 4 and
  1 < 2 )

10.请问Python的 and 操作符 和C语言的 && 操作符 有何不同?

在这里插入图片描述
VS
在这里插入图片描述

11.听说过“短路逻辑(short-circuit logic)”吗?

逻辑操作符有个有趣的特性:在不需要求值的时候不进行操作。这么说可能比较“高深”,举个例子,表达式 x and y,需要 x 和 y 两个变量同时为真(True)的时候,结果才为真。因此,如果当 x 变量得知是假(False)的时候,表达式就会立刻返回 False,而不用去管 y 变量的值。

这种行为被称为短路逻辑(short-circuit logic)或者惰性求值(lazy evaluation),这种行为同样也应用与 or 操作符,这个后边的课程小甲鱼会讲到,不急。

实际上,Python 的做法是如果 x 为假,表达式会返回 x 的值(0),否则它就会返回 y 的值(例子参考楼上那题)。
短路逻辑的核心思想就是:从左往右,只有当第一个操作数的值无法确定逻辑运算的结果时,才对第二个操作数进行求值。

12.不妨写一个小代码,让你的计算机为之崩溃?

由于幂运算是从右往左运算的,所以 print(2 ** 2 ** 32) 就相当于 print(2 ** 4294967296),数字太大了,Python 一时算不出结果。

而 print((2 ** 2) ** 32) 加了括号,相当于 print(4 ** 32),Python 当然可以很快算出是 18446744073709551616。

13.猜猜 (x < y and [x] or [y])[0] 实现什么样的功能?

这其实是 Python 的作者还没有为 Python 加入三元操作符之前,Python 社区的小伙伴们灵活的使用 and 和 or 搭配来实现三元操作符的功能,这里边有涉及到列表和切片的知识,这部分知识很快就会讲解,迫不及待的朋友可以先稍微预习下。

14.创建列表快还是创建元组快?

检测一个函数或者表达式的效率,可以使用 timeit 模块:


>>> import timeit
>>> print(timeit.timeit('x = [1, 1, 2, 3, 5, 8, 13, 21]', number=100000000))
9.118212128999858
>>> print(timeit.timeit('y = (1, 1, 2, 3, 5, 8, 13, 21)', number=100000000))
1.4662796760003403

可见,两者分别执行 1 亿次的时间差距是非常明显的。
创建列表用了 9.12 秒,而创建元组仅需 1.47 秒,比前者速度的 6 倍。
对于大数据计算来说,失之毫厘差之千里。
所以,掌握并理解 Python 各种内置对象的性能重要性不言而喻。

15、列表的拷贝

利用分片完成列表的拷贝 list2 = list1[:],那事实上可不可以直接写成 list2 = list1 更加简洁呢?
千万不可以!
使用分片创建列表的拷贝,例如:

>>> list1 = [1, 3, 2, 9, 7, 8]
>>> list2 = list1[:]
>>> list2
[1, 3, 2, 9, 7, 8]
>>> list3 = list1
>>> list3
[1, 3, 2, 9, 7, 8]

看上去貌似一样的,对吧?但事实上呢?我们利用列表的一个小伙伴做下修改,大家看一下差别:

>>> list1.sort()
>>> list1
[1, 2, 3, 7, 8, 9]

看到吧,我们的list1已经从小到大排了个序,那list2和list3呢?

>>> list2
[1, 3, 2, 9, 7, 8]

可以看到我们使用分片的方式得到的list2很有原则、很有格调,并不会因为list1的改变而改变,这个原理我待会儿跟大家说,我们接着看下list3:

>>> list3
[1, 2, 3, 7, 8, 9]

大家可以看到了,真正的汉奸、墙头草是list3,Ta跟着list1改变了,这是为什么呢?

不知道大家还记不记得我们在讲解变量的时候说过,Python的变量就像一个标签,就一个名字而已,贴哪是哪,指哪打哪,呃,我还是给大家伙画个图好。
在这里插入图片描述
这下大家应该明白了吧,在为一个固定的东西指定另一个名字的做法,只是向同一个东西增加一个新的标签而已。

16、return

请问调用以下这个函数会打印什么内容?

>>> def hello():
        print('Hello World!')
        return
        print('Welcome To FishC.com!')

会打印:

>>> hello()
Hello World!

因为当Python执行到return语句的时候,Python认为函数到此结束,需要返回了(尽管没有任何返回值)。

如果python没有使用return语句指定返回值,Python也不是什么都不返回的,Ta会返回一个None对象,所以我们说python所有的函数都有返回值。
python的return可以返回多个不同类型的值,默认用逗号隔开,是以元组的形式返回,不过也可以用列表包含起来返回:

>>>def myFun():
		return ["皮卡丘",3.14,520,False]
>>>myFun()
["皮卡丘",3.14,520,False]

17、随机数攻击

要实现对伪随机数的攻击,就要拿到它的种子,默认下,random使用当前操作系统时间来作为随机数种子,
getstate()这个函数来获取随机数种子加工之后随机数生成器的内部状态。

>>>x=random.getstate()
>>>random.randint(1,10)
7

调用setstate函数重新设置随机数生成器的内部状态
把刚才这个内部状态给传进去

>>>random.setstate(x) 

然后让刚才随机数重现

>>>random.randint(1,10)

18、x==(x//y)*y+(x%y)

被除数=商乘除数再加余数

19、欧几里德算法

欧几里德算法求最大公约数
def gcd(a, b):
while a != 0:
a, b = b % a, a

return b

20、闭包

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

21、filter、labbda、列表推导式

在这里插入图片描述

22、zip、map、lambda、list

在这里插入图片描述

23、输入判断

zz=input("是否修改用户资料(YES/NO):")
if zz=='YES':
     number=input('请输入用户联系电话:')
     ff[name]=number

可以这样简写:

if input("是否修改用户资料(YES/NO):")=='YES'
	number=input('请输入用户联系电话:')
    ff[name]=number

24、函数和方法的区别

几乎完全一样,但有一点区别是方法默认有一个self参数。

25、self参数的作用

绑定方法,据说有了这个参数,python再也不会傻傻分不清是哪个对象在调用方法了,你可以认为方法中的self其实就是实例化对象的唯一标志。

26、循环遍历元组

  • 在 Python 中,可以使用 for 循环遍历所有非数字型类型的变量:列表、元组、字典 以及 字符串
  • 提示:在实际开发中,除非 能够确认元组中的数据类型,否则针对元组的循环遍历需求并不是很多

27、公共方法~Python 内置函数

Python 包含了以下内置函数:

函数描述备注
len(item)计算容器中元素个数
del(item)删除变量del 有两种方式
max(item)返回容器中元素最大值如果是字典,只针对 key 比较
min(item)返回容器中元素最小值如果是字典,只针对 key 比较
cmp(item1, item2)比较两个值,-1 小于/0 相等/1 大于Python 3.x 取消了 cmp 函数

注意

  • 字符串 比较符合以下规则: “0” < “A” < “a”

28、TODO 注释

1、在 # 后跟上 TODO,用于标记需要去做的工作

# TODO(作者/邮件) 显示系统菜单

在这里插入图片描述

2、pycharm右下角点击TODO:
在这里插入图片描述
3、点击红框,直接定位到1图那个位置:
在这里插入图片描述

29、return下方法的代码不会被执行

如果return后面没有任何内容,表示会返回到调用函数的位置,并且不返回任何的结果

30、 LINUX 上的 Shebang 符号(#!)

  • #!这个符号叫做 Shebang 或者 Sha-bang
  • Shebang 通常在 Unix 系统脚本的中 第一行开头 使用
  • 指明 执行这个脚本文件 的 解释程序

使用 Shebang 的步骤

  • 1.使用 which 查询 python3 解释器所在路径

    $ which python3

  • 2.修改要运行的 主 python 文件,在第一行增加以下内容

    #! /usr/bin/python3

  • 3.修改 主 python 文件 的文件权限,增加执行权限

    $ chmod +x cards_main.py

  • 4.在需要时执行程序即可

    ./cards_main.py

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值