基础

本文深入浅出地讲解了Python的基础语法,包括变量定义、数据类型、运算符、流程控制等核心内容,适合初学者快速掌握Python编程。
  • Python的三种运行方式

    终端、脚本、IDE
    

注释

#这是单行注释

"""
这是多行注释1
"""

'''
这是多行注释2
'''

print()输出

print("唐友吃不着鸡")
print('唐友吃不着鸡')
print("""
	唐友吃不着鸡
	""")
print('''
	唐友吃不着鸡
	''')

print(help(print))
#查看打印的类型

input 函数

a = input("请输入信息>>>")
print(a)
print(type(a))
  • input()函数中可以给提示信息,但本身不会传递给相关变量,只有输入的值才会传递。
  • input()函数的返回值为字符串类型,可以用type()函数测试

数据:

  • 文本
  • 图形
  • 音频
  • 视频
  • 网页数据
  • 等等

不同的数据,我们需要定义不同的数据类型。

python的常见数据类型:

  • 数字(number){

    1. 数字提供了标量存储和直接访问
    2. 是不可更改的数据类型(指变更数字会生成新的对象)

    }

    • 整型(int){

      ​ Python有几种整数类型,布尔类型是只有两个值的整型,常规整型是绝大多数

      ​ Python2区分整型和长整形,Python3不区分

      }

    • 长整型(long)

    • 浮点型(float){又分为双精度浮点型和十进制浮点型

      ​ 十进制浮点型:

      ​ python3中说浮点型

      主要知道科学计算法

      print(2.3124E4)
      print(4000e-3)
      """
      23124.0
      4.0
      大小写e都可以,代表
      """
      

      }

    • 复数(complex){

      x ** 2 = -1 x的平方等于-1 任何一个实数的平方都是一个非负数。

      但是现在一个数的平方我们要让他得到一个负数,怎么办?

      所以,18世纪的数学家们定义了虚数(i,j, 虚数基本单位,i ** 2 = -1 , j * *2 = -1)

      属性:

      ​ num.real 该复数的实部

      ​ num.imag 该复数的虚部

      ​ num.conjugate 返回该复数的共

      ​ }

  • 字符串(String)

  • 布尔型(Bool){True/False(1,0)}

  • 列表(list)

  • 元组(tuple)

  • 集合(set)

  • 字典(dict)

变量

  • 概念:
    • 程序可操作的存储区名称
    • 程序运行存储区中能改变的数据
    • 每个变量都有特定的类型
  • 作用:将数据存储到内存;
  • 变量的定义
变量名 = 初始值(初始值的实际类型决定变量的数据类型)
  • 变量的命名
    • 必须由字母、数字、下划线组成;
    • 不能以数字开头(但是由于Python中单下划线("_")和双下划线("__")名称的变量有特殊用途,因此不推荐自定义单下划线和双下划线开头的变量
    • 不能是Python中的关键字

变量命名尽可能见名知意:

大驼峰、小驼峰

首先,看一下关键字:

import keyword
print(keyword.kwlist)

'''
['False', 'None', 'True', 'and', 'as', 'assert', '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']
'''
  • 变量类型查看
type(变量名)

  • 变量内存地址
id(变量名)

dir():对应之前所有变量
dir(a): 参数里所有的变量和属性

举例

a = 1
print(a,type(a),id(a))
b = "Hunan"
print(b,type(b),id(b))
a = 1
print(a)
del a
print(a)

ApplePrice/Apple_Price

  • 变量的调用
a = 1
b = 6
c = a + b
print(c)

调用变量的时候,变量实现必须与定义,否则报错

常量

常量即不变的量,比如,π 3.1415926,或者程序运行过程中不可以更改的量。

一般常量的定义全部都用大写

π = 3.14

# 交换变量
x = 2
y = 3
x,y = y,x
print(x,y)

# 同时赋值
a = b = c = 3
print(a,b,c)
# a,b,c= 3  #报错
a,b,c= 1,2,3  #同步赋值,---对应
print(a,b,c)
b = 1,2  #返回一个元组
print(b)

运算符描述实例
+加 : 两个对象相加a + b
-减 :得到负数或是一个数减去另一个数a - b
*乘 : 两个数相乘或是返回一个被重复若干次的字符串a * b
/除 : x 除以 yb / a
%取模 : 返回除法的余数b % a
**幂 : 返回x的y次幂a**b
//取整除 : 向下取接近除数的整数a//b
a = 27
b = 4
print(a/b)
print(a//b)
print(a%b)
"""
6.75
6
3
"""

Python的比较运算符

以下假设变量a为10,变量b为20:
运算符描述实例
==等于 - 比较对象是否相等(a == b) 返回 False。
!=不等于 - 比较两个对象是否不相等(a != b) 返回 True。
>大于 - 返回x是否大于y(a > b) 返回 False。
<小于 - 返回x是否小于y。所有比较运算符返回1表示真,返回0表示假。这分别与特殊的变量True和False等价。注意,这些变量名的大写。(a < b) 返回 True。
>=大于等于 - 返回x是否大于等于y。(a >= b) 返回 False。
<=小于等于 - 返回x是否小于等于y。(a <= b) 返回 True。

Python赋值运算符

以下假设变量a为10,变量b为20:

运算符描述实例
=简单的赋值运算符c = a + b 将 a + b 的运算结果赋值为 c
+=加法赋值运算符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

python中没有++,–这种写法

Python位运算符

按位运算符是把数字看作二进制来进行计算的。Python中的按位运算法则如下:

运算符描述
&按位与运算符:参与运算的两个值,如果两个相应位都为1,则该位的结果为1,否则为0
|按位或运算符:只要对应的二个二进位有一个为1时,结果位就为1。
^按位异或运算符:当两对应的二进位相异时,结果为1
~按位取反运算符:对数据的每个二进制位取反,即把1变为0,把0变为1。~x 类似于 -x-1
<<左移动运算符:运算数的各二进位全部左移若干位,由"<<"右边的数指定移动的位数,高位丢弃,低位补0。
>>右移动运算符:把">>“左边的运算数的各二进位全部右移若干位,”>>"右边的数指定移动的位数

关于取反:

下表中变量 a 为31,b为 15二进制格式如下:
a = 31
b = 15
print(bin(a))
print(bin(a<<2))
print(bin(b))
print(bin(b>>2))
print(a&b)
print(a|b)
print(a^b)
print(~b)

"""
0b11111
0b1111100
0b1111
0b11
15
31
16
-16
"""

Python逻辑运算符

Python语言支持逻辑运算符,

运算符逻辑表达式描述
andx and y布尔"与" - 如果 x 为 False,x and y 返回 False,否则它返回 y 的计算值。
orx or y布尔"或" - 如果 x 是 True,它返回 x 的值,否则它返回 y 的计算值。
notnot x布尔"非" - 如果 x 为 True,返回 False 。如果 x 为 False,它返回 True。

同样仍以变量 a 为 31,b 为 15为例:

a = 31
b = 15
print(a<3 and b>12)
print(a<30 or b>12)
print(not a)

"""
False
True
False
"""

  1. 在没有()的情况下not优先级高于 and,and优先级高于or,即优先级关系为()>not>and>or,同一优先级从左往右计算

判断逻辑语句的正与负:

3>4 or 4<3 and 1==1 #
1 < 2 and 3 < 4 or 1>2 #
2 > 1 and 3 < 4 or 4 > 5 and 2 < 1 #
1 > 2 and 3 < 4 or 4 > 5 and 2 > 1 or 9 < 8 #
1 > 2 and 3 < 4 or 4 > 5 and 2 > 1 or 9 > 8 #
1 > 1 and 3 < 4 or 4 > 5 and 2 > 1 and 9 > 8 or 7 < 6 #
not 2 > 1 and 3 < 4 or 4 > 5 and 2 > 1 and 9 > 8 or 7 < 6#
"""
False
True
True
False
True
False
False
"""

and(逻辑与)01
000
101
or(逻辑或)01
001
111

Python成员运算符

除了以上的一些运算符之外,python还支持成员运算符,测试示例中包含一系列的成员,包括字符串,列表或元组

运算符描述实例
in如果在指定的序列中找到值返回True,否则返回Falsex在y序列中,如果x在y序列中返回True
not in如果在指定的序列中没有找到值返回True,否则返回Falsex不在y的序列中,如果x不在y序列或者能够返回True

Python身份运算符

身份运算符用于比较两个对象的存储单元

运算符描述实例
isis 是判断两个标识符是不是引用自一个对象x is y, 类似 id(x) == id(y) , 如果引用的是同一个对象则返回 True,否则返回 False
is notis not 是判断两个标识符是不是引用自不同对象x is not y , 类似 id(a) != id(b)。如果引用的不是同一个对象则返回结果 True,否则返回 False。

注:id()函数用于获取对象内存地址

Python运算符的优先级

以下表格列出了从最高到最低优先级的所有运算符:

运算符描述
**指数 (最高优先级)
~ + -按位翻转, 一元加号和减号 (最后两个的方法名为 +@ 和 -@)
* / % //乘,除,取模和取整除
+ -加法减法
>> <<右移,左移运算符
&位 ‘AND’
^\
<= < > >=比较运算符
<> == !=等于运算符
= %= /= //= -= += *= **=赋值运算符
is is not身份运算符
in not in成员运算符
not and or逻辑运算符

数据类型的强制转换

强转类型描述
int(x)将x转换成一个整数
float(x)将x转换成浮点数
int(x [,base ])将x转换为一个整数
long(x [,base ])将x转换为一个长整数
float(x )将x转换到一个浮点数
complex(real [,imag ])创建一个复数
str(x )将对象 x 转换为字符串
repr(x )将对象 x 转换为表达式字符串
eval(str )用来计算在字符串中的有效Python表达式,并返回一个对象
tuple(s )将序列 s 转换为一个元组
list(s )将序列 s 转换为一个列表
chr(x )将一个整数转换为一个字符
unichr(x )将一个整数转换为Unicode字符
ord(x )将一个字符转换为它的整数值
hex(x )将一个整数转换为一个十六进制字符串
oct(x )将一个整数转换为一个八进制字符串
bin(x)将一个整数转换为一个二进制字符串

关于进制

十进制二进制八进制十六进制
00000 00000000 00000
10000 00010000 00011
20000 00100000 00022
30000 00110000 00033
40000 01000000 00044
50000 01010000 00055
60000 01100000 00066
70000 01110000 00077
80000 10000000 00108
90000 10010000 00119
100000 10100000 0012A
110000 10110000 0013B
120000 11000000 0014C
130000 11010000 0015D
140000 11100000 0016E
150000 11110000 0017F
160001 00000000 00200010

常见的数学函数

函数名描述
abs(x)返回数字的绝对值,如abs(-10) 返回 10
fabs(x)返回数字的绝对值,如math.fabs(-10) 返回10.0
ceil(x)返回数字的上入整数,如math.ceil(4.1) 返回 5
floor(x)返回数字的下舍整数,如math.floor(4.9)返回 4
round(x [,n])返回浮点数x的四舍五入值,如给出n值,则代表舍入到小数点后的位数。
exp(x)返回e的x次幂(ex),如math.exp(1) 返回2.718281828459045
log(x)如math.log(math.e)返回1.0,math.log(100,10)返回2.0
log10(x)返回以10为基数的x的对数,如math.log10(100)返回 2.0
max(x1, x2,…)返回给定参数的最大值,参数可以为序列。
min(x1, x2,…)返回给定参数的最小值,参数可以为序列。
modf(x)返回x的整数部分与小数部分,两部分的数值符号与x相同,整数部分以浮点型表示。
pow(x, y)x**y 运算后的值。
sqrt(x)返回数字x的平方根
cmp(x, y)存在于py2,如果 x < y 返回 -1, 如果 x == y 返回 0, 如果 x > y 返回 1
  • abs与fabs运行区别:
    • fabs()的使用需要导入数学模块(math),而abs()不需要
    • 返回数据类型不同
>>> a = abs(-9)
>>> b = fabs(-9)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'fabs' is not defined
>>> import math
>>> a = abs(-9)
>>> b = math.fabs(-9)
>>> a,type(a)
(9, <class 'int'>)
>>> b,type(b)
(9.0, <class 'float'>)

>>> import math
>>> dir(math)
['__doc__', '__loader__', '__name__', '__package__', '__spec__', 'acos', 'acosh', 'asin', 'asinh', 'atan', 'atan2', 'atanh', 'ceil', 'copysign', 'cos', 'cosh', 'degrees', 'e', 'erf', 'erfc', 'exp', 'expm1', 'fabs', 'factorial', 'floor', 'fmod', 'frexp', 'fsum', 'gamma', 'gcd', 'hypot', 'inf', 'isclose', 'isfinite', 'isinf', 'isnan', 'ldexp', 'lgamma', 'log', 'log10', 'log1p', 'log2', 'modf', 'nan', 'pi', 'pow', 'radians', 'sin', 'sinh', 'sqrt', 'tan', 'tanh', 'tau', 'trunc']
>>> dir()
['__annotations__', '__builtins__', '__doc__', '__loader__', '__name__', '__package__', '__spec__', 'math']
>>> from math import *
>>> dir()
['__annotations__', '__builtins__', '__doc__', '__loader__', '__name__', '__package__', '__spec__', 'acos', 'acosh', 'asin', 'asinh', 'atan', 'atan2', 'atanh', 'ceil', 'copysign', 'cos', 'cosh', 'degrees', 'e', 'erf', 'erfc', 'exp', 'expm1', 'fabs', 'factorial', 'floor', 'fmod', 'frexp', 'fsum', 'gamma', 'gcd', 'hypot', 'inf', 'isclose', 'isfinite', 'isinf', 'isnan', 'ldexp', 'lgamma', 'log', 'log10', 'log1p', 'log2', 'math', 'modf', 'nan', 'pi', 'pow', 'radians', 'sin', 'sinh', 'sqrt', 'tan', 'tanh', 'tau', 'trunc']

指数

1、正整数指数幂:实数a自乘n次得到的实数b,b=a×a×a ×a……×a, (n∈N,且 n >1),称为实数a的n次幂,n为自然数,数a的n次幂用an表示,记作{\rm{b}} = {a^n},数a称为幂的底,数n称为幂指数。注意:{\rm{b}} = {a^1}

  • cmp()函数

    python2使用,python3已取消

    python3中对应的使用:

>>> import operator
>>> operator.eq("q","q") # eq:equal,判断是否相等
True
lt(a,b)相当于a<b  从第一个数字或字母(ASCII)比大小
>>> operator.lt("a","b") # lt:less than
True
>>> operator.le("a","a")
True
>>> operator.lt("a","a") # lt:less than
False

随机函数(random)

  • 模块导入
#方法一
>>>import random
#方法二
>>>from random import * #不推荐使用

  • 查看对应的方法和属性
>>>dir(random)
['BPF', 'LOG4', 'NV_MAGICCONST', 'RECIP_BPF', 'Random', 'SG_MAGICCONST', 'SystemRandom', 'TWOPI', '_BuiltinMethodType', '_MethodType', '_Sequence', '_Set', '__all__', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', '_acos', '_bisect', '_ceil', '_cos', '_e', '_exp', '_inst', '_itertools', '_log', '_pi', '_random', '_sha512', '_sin', '_sqrt', '_test', '_test_generator', '_urandom', '_warn', 'betavariate', 'choice', 'choices', 'expovariate', 'gammavariate', 'gauss', 'getrandbits', 'getstate', 'lognormvariate', 'normalvariate', 'paretovariate', 'randint', 'random', 'randrange', 'sample', 'seed', 'setstate', 'shuffle', 'triangular', 'uniform', 'vonmisesvariate', 'weibullvariate']
>>>

  • random模块常用的功能
    • random.random():用于随机生成一个0到1的浮点数n(0<=n<=1)
>>> import random
>>> nun = random.random()
>>> print(nun)
0.09095966637327513
>>> print(nun)  #在随机生成之后无论怎么打印这个数还是不会变
0.09095966637327513
>>> nun = random.random()
>>> print(nun)	#只能重新生成一个随机数才会改变
0.9659144361674479
>>>

  • random.uniform(a,b):用于生成指定范围内的随机浮点数,两个参数,其中之一是上限,另一个是下限
    • 如果a>b,生成的随机数n:a<=n<=b;
    • 如果a<b,生成的随机数n:b<=n<=a;
>>> import random
>>> random.uniform(1,10)
4.238137852842515
>>> random.uniform(10,1)
1.5240380497388877

  • random.randint(a,b):随机生成a到b范围内的整数n(a<= n <=b)
>>> random.randint(10,1)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "D:\Python36\lib\random.py", line 221, in randint
    return self.randrange(a, b+1)
  File "D:\Python36\lib\random.py", line 199, in randrange
    raise ValueError("empty range for randrange() (%d,%d, %d)" % (istart, istop, width))
ValueError: empty range for randrange() (10,2, -8)
#括号内的数字只能从小到大,从大到小会报错
>>> random.randint(1,10)
3

  • random.randrange([start],[stop],[step]):从指定范围内,按指定基数递增的集合中获取一个随机数。
    • 集合为(start,start+stop+2*step,···,start+n*step)
>>> random.randrange(10,30,2)
20 
>>> random.randrange(100,30,-2)
52

  • random.choice(sequence):从序列中随机获取一个元素
>>> lst = ['python','C','C++','javascript']
>>> str1 = ('I love python')
>>> random.choice(lst)
'javascript'
>>> random.choice(lst)
'C'
>>> random.choice(str1)
'y'
>>> random.choice(str1)
'n'


  • random.shuffle(x[ , random]):用于将一个列表中的元素打乱,即将列表内的元素随机排列
>>> p = ['A','B','C','D','E']
>>> random.shuffle(p)
>>> p
['C', 'E', 'A', 'D', 'B']


  • random.sample(sequemce,k):从指定序列中获取指定长度的片段并随机排列。注意:sample函数不会修改原有序列。
>>> li = [1,2,3,4,5,6]
>>> random.sample(li,4)
[1, 6, 4, 5]
>>> random.sample(li,3)
[4, 1, 5]
>>> random.sample(li,2)
[2, 5]
>>> random.sample(li,5)
[6, 3, 1, 5, 4]


Python程序流程控制

  • if…else

  • while

  • for

    C或者java,Switch…case,default,Python中则不存在

常见流程控制语句:

  1. 顺序执行

  2. 选择分支

  3. 循环执行

    需要去注意的是,C或者java,通常用花括号{}来控制流程控制语句的语法,而Python 则使用缩进来控制相应的语法

>>> a = 2
>>> if a < 3:
...     print("a < 3")
...
a < 3


IF条件分之语句

Python条件语句是通过一条或多条语句执行结果(True或者False)来决定执行的代码块

  • if单分支语句
if 逻辑语句:
    语句()


demo:

print(111)
if True:
	print(222)
print(333)	


结果:

111
222
333


修改条件:

print(111)
if False:
	print(222)
print(333)


结果:

111
333


将True或者False换成逻辑语句。

练习:随机生成一个数字,输入一个数字,比大小

import random
a = random.randint(1,10)
for i in range(10):
    b = int(input("输入数字"))
    if a < b:
        print("猜对了")
print("猜错了")


  • if双分支语句
if 逻辑语句:
	语句()1
elif:
	语句()2


demo:

learning = "java"
if learning == "python"
	print("啊哈,真巧,我也在学习Python")
else:
	print("小明和你一样,他也在学习java")
print("很高兴认识你")	


练习:写一个登录判断

import getpass
username = input("请输入用户名:")
password = getpass.getpass("请输入密码:")
if username == "admin" and password == "123456":
    print("登陆成功")
else:
    print("请重试")


输入密码隐藏:getpass(在IDE中无法运行,只能在脚本中运行)

  • if多分支语句

    Python中用elif代替了 else if,所以if语句的关键字为:if - elif - else。

    注意:
    1. 每个条件后面要使用冒号:,表示接下来是要满足条件后要执行的语句块
    2. 使用缩进来划分语句块,相同缩进数的语句在一起组成一个语句块。
    3. 在Python中没有switch - case语句。
if 逻辑语句:
    语句()1
elif 逻辑语句2:
    语句()2
elif 逻辑语句3:
    语句()3
    ......
elif 逻辑语句n-1:
    语句()n-1
else:
    语句()n


练习:

输入0~100看能到多少分

num = int(input("输入你要的数字:"))
if num == 100 :
    print("A+")
elif num > 100:
    print("比最高分还高是自己改的吧")
elif num >= 90:
    print("A")
elif num >= 80:
    print("B")
elif num >= 70:
    print("C")
elif num >= 60:
    print("D")
else :
    print("不及格")


while循环语句

  • 概念:循环用来执行部分代码…即在一定的条件下执行重复的代码。
  • 格式:
while 逻辑语句:
	语句(块)


demo:

  1. 1-100
num = 0
while num < 100:
   num += 1
   print(num)


2.1-100的和:

num = 0
max = 0
while num < 100:
   num += 1
   max += num
print(max)


braek与continue

如果在循环的过程中,因为某些原因,你不想就像循环了,怎么把它终止掉呢?这就用到break或continue语句

  • break用于完全结束一个循环,跳出循环体执行循环后面的语句
  • continue和break有点类似,区别在于continue只是终止本次循环,接着还执行后面的循环,break则完全终止循环

例子 break

count = 0
while count <= 100:
	print("loop",count)
	if count == 5
		break
	count += 1


for循环

Python for循环可以遍历任何序列的项目,如一个列表或者一个字符串。

for循环格式:

for i in 序列:
	语句()


demo:

  1. 遍历字符串
demo_str = "python"
for i in demo_str:
    print(i)


运行结果:

p
y
t
h
o
n


2.range()

range(end)
#[0,end)
range(start,end)
#[start,end)
range(start,end,step)
#{start,start+step,......,start + n*step}
(start + n*step)[start,end)范围内的


for循环打印四行四列星号
for i in range(4):
    for j in range(4):
        print("*" , end = "")
    print()
    
#运行结果
"""
****
****
****
****
"""


字符串

什么是字符串

​ 字符串是Python中最常用的数据类型,我们可以在使用引号('或")来创建字符串,事实上,在Python中,加了引号的字符都被认为是字符串

​ Python中单个字符和多个字符用引号包裹后,统称为字符串,没有Java或者C中字符的说法

>>> name = "Tang you"
>>> age = "18"
>>> age_1 = 18
>>> msg = '''I'm Tang you''' #单引号会就近重合,使用三个单引号会避免 三单引号三双引号可以换行使用
>>> msg = """I'm Tang you"""
>>> print(type(name),type(age),type(age_1),type(msg))
<class 'str'> <class 'str'> <class 'int'> <class 'str'>


(3)字符串索引([]以及切片[::])

1553130703111

a = "Life is short, I use python"
print(len(a))
print(a[26])
print(a[8:10])
print(a[-19:-17])
print(a[::-1])

"""
27
n
sh
sh
nohtyp esu I ,trohs si efiL
"""


(4)大小写转换
  • str.lower():转小写
  • str.upper();转大写
  • str.swapcase():大小写对换
  • str.capitalize():字符串首为大写,其余小写
  • str.title():已分隔为标记,首字符为大写,其余为小写
a = "Life is short, I use python"
print(a.lower()) # 将所有大写字符转换为小写
print(a.upper()) # 将所有小写字符转换为大写字符
print(a.swapcase()) # 将所有小写字符变成大写,将大写字符变成小写
print(a.capitalize()) # 将字符串的第一个字符大写
print(a.title()) # 返回标题化的字符

"""
life is short, i use python
LIFE IS SHORT, I USE PYTHON
lIFE IS SHORT, i USE PYTHON
Life is short, i use python
Life Is Short, I Use Python
"""


(5)字符串格式输出对齐
  • str.center()
  • str.ljust()
  • str.rjust()
  • str.zfill()
a = "Life is short, I use python"
print(a.center(30, '^')) # 居中对齐,并使用空格填充至长度
print(a.ljust(30, '^')) # 左对齐,并使用空格填充至长度
print(a.rjust(30, '^')) # 右对齐,并使用空格填充至长度
print(a.zfill(30,))

"""
^Life is short, I use python^^
Life is short, I use python^^^
^^^Life is short, I use python
000Life is short, I use python
"""


(6)删除指定字符
  • str.lstrip()
  • str.rstrip()
  • str.strip()
a = "*****Life is short, I use python*****"
print(a.lstrip("*"))
print(a.rstrip("*"))
print(a.strip("*"))

"""
Life is short, I use python*****
*****Life is short, I use python
Life is short, I use python
"""


(7)计数

excel表中:

=COUNTIF(B2:B31,">=30")COUNT(B2:B31)


python中:

a = "Life is short, I use python"
print(a.count('i')) # 返回 str 在 string 里面出现的次数
print(a.count('i' , 4 , 8)) # 在索引值为[4,8)的范围内str出现的次数

"""
2
1
"""


(8)字符搜索定位与替换
  • str.find()
a = "Life is short, I use python"
print(a.find('e')) # 查找元素并返回第一次出现的索引值
print(a.find('e' , 18 , 24)) # 查找元素在指定索引范围内的索引
print(a.rfind('e')) # 从右往左开始查找
print(a.find('w')) # 找不到值返回-1
"""
3
19
19
-1
"""


  • str.index()
    • 和find()方法一样,只不过如果str不在string中会报一个异常。
a = "Life is short, I use python"
print(a.index('i'))
print(a.index('e' , 18))
print(a.index('c')) # 没有这个元素,会报异常
"""
1
19

Traceback (most recent call last):
  File "E:/Python/3.13.py", line 135, in <module>
    print(a.index('c'))
ValueError: substring not found
"""


  • str.replace()
    • 替换
a = "Life is short, I use python"
print(a.replace('I use', 'You need'))
print(a.replace('t' , 'T'))
print(a.replace('t' , 'T' , 1))
"""
Life is short, You need python
Life is shorT, I use pyThon
Life is shorT, I use python
"""


字符串运算及操作

数字可以进行加减乘除的运算,字符串只可以进行"相加"和"相乘"运算

(1)拼接

a = "唐友"
b = "在想屁吃"
print(a + b)
"""
唐友在想屁吃
"""


注意,字符串拼接只能是双方都是字符串,不能跟数字或其他类型拼接

b = "666"
c = 100
print(b + c)
"""
Traceback (most recent call last):
  File "E:/Python/3.13.py", line 145, in <module>
    print(b + c)
TypeError: must be str, not int
"""


(2)重复

a = "唐友"
b = "在想屁吃"
print(a + b * 3)


(3)字符串索引([]以及切片[::])

a = "**********Life is short, I use python"
print(len(a))
print(a[0])
print(a[15])
print(a[-1])
print(a[-6])
#切片
print(a[15::2])
print(a[::-1])
"""
37
*
i
n
p
i hr,Iuepto
nohtyp esu I ,trohs si efiL**********
"""


(9)字符串条件判断

  • isalnum(),字符串由字母或数字组成,
  • isalpha(),字符串只由字母组成,
  • isdigit(),字符串只由数字组成
In [1]: a = "abc123"

In [2]: b = "ABC"

In [3]: c = 123

In [4]: a.isalnum()
Out[4]: True

In [5]: a.isalpha()
Out[5]: False

In [6]: a.isdigit()
Out[6]: False

In [7]: b.isalnum()
Out[7]: True

In [8]: b.isalpha()
Out[8]: True

In [9]: b.isdigit()
Out[9]: False>>> str = '01234'
 
>>> str.isalnum()   # 是否全是字母和数字,并至少有一个字符
True
>>> str.isdigit()    # 是否全是数字,并至少有一个字符
True      
 
 
>>> str = 'string'
 
>>> str.isalnum()  # 是否全是字母和数字,并至少有一个字符
True
>>> str.isalpha()  # 是否全是字母,并至少有一个字符 
True
>>> str.islower() # 是否全是小写,当全是小写和数字一起时候,也判断为True
True
 
>>> str = "01234abcd"
 
>>> str.islower() # 是否全是小写,当全是小写和数字一起时候,也判断为True
True
 
>>> str.isalnum()  # 是否全是字母和数字,并至少有一个字符
True
 
>>> str = ' '
>>> str.isspace()  # 是否全是空白字符,并至少有一个字符
True
 
>>> str = 'ABC'
 
>>> str.isupper()   # 是否全是大写,当全是大写和数字一起时候,也判断为True
True
 
>>> str = 'Aaa Bbb'
 
>>> str.istitle()  # 所有单词字首都是大写,标题 
True
 
 
>>> str = 'string learn'
 
>>> str.startswith('str') # 判断字符串以'str'开头
True
 
>>> str.endswith('arn')  # 判读字符串以'arn'结尾
True


(10)制表符转化
str.expandtabs()

>>> a = "L\tife is short, I use python"
>>> a.expandtabs() # 默认将制表符转化为8个空格
'L       ife is short, I use python'
>>> a.expandtabs(4) # 加上参数,将制表符转化为对应个数的空格
'L   ife is short, I use python'
>>>


(11)字符串分割变换

  • join()将指定字符插入到元素之间
  • split()以指定字符分隔序列且去除该字符
  • partition()以指定字符分隔序列且包含该字符
>>> str = "learn string"
>>> '-'.join(str)
'l-e-a-r-n- -s-t-r-i-n-g'
>>> '+'.join(str)
'l+e+a+r+n+ +s+t+r+i+n+g'
>>> li = ["learn","string"]
>>> '-'.join(li)
'learn-string'
>>> str.split('n')
['lear', ' stri', 'g']
>>> str.split('n',1)
['lear', ' string']
>>> str.rsplit('n',1)
['learn stri', 'g']
>>> str.rsplit('n')
['lear', ' stri', 'g']
>>> str.splitlines()
['learn string']
>>> str.partition('n')
('lear', 'n', ' string')
>>> str.rpartition('n')
('learn stri', 'n', 'g')
>>>



补充:

string模块

查看:

>>> import string
>>> dir(string)
['Formatter', 'Template', '_ChainMap', '_TemplateMetaclass', '__all__', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__',
 '__spec__', '_re', '_string', 'ascii_letters', 'ascii_lowercase', 'ascii_uppercase', 'capwords', 'digits', 'hexdigits', 'octdigits', 'printable', 'punctuation', 'whitespace']
>>> string.ascii_letters
'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
>>> string.ascii_lowercase
'abcdefghijklmnopqrstuvwxyz'
>>> string.ascii_uppercase
'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
>>> string.capwords('hUNAN yingxiao  college')
'Hunan Yingxiao College'
>>>



  • string模块中的capwords()函数功能:
    • 1.将每个单词首字母至为大写
    • 2.将每个单词除首字母外的字母均置为小写
    • 3.将词与词之间的多个空格用一个空格代替
    • 4.其拥有两个参数,第二个参数用以判断单词之间的分割符,默认为空格
>>> import string
>>> string.digits
'0123456789'
>>> string.hexdigits
'0123456789abcdefABCDEF'
>>> string.octdigits
'01234567'
>>> string.printable
'0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~ \t\n\r\x0b\x0c'
>>> string.punctuation
'!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~'
>>>



Python字符串格式化

尽管已经掌握了所介绍的字符串方法和序列操作,Python还提供了一种更高级的方法来组合字符串处理任务——字符串格式化允许在一个单个的步骤中对一个字符串执行多个特定类型的替换。它不是严格必须的,但它很方便使用,特别是当格式化文本以显示给程序的用户的时候。由于Python世界中充满了很多新思想,如今的Python中的字符串格式化可以以两种形式实现:

  • 字符串格式化表达式
    这是从Python诞生的时候就有的最初的技术;这是基于C语言的“printf”模型,并且在大多数现有的代码中使用。
  • 字符串格式化方法调用
    这是Python2.6和Python3.0新增加的技术,这是Python独有的方法,并且和字符串格式化表达式的功能有很大重叠。

由于方法调用是很新,其中的某些或另外一些可能会随着时间的推移而废弃。表达式更有可能在以后的Python版本中废弃,尽管这应该取决于真正的Python程序员未来的实际使用情况。然而,由于它们很大程度上只是同一个方案的变体,现在这两种技术都是有效的。既然字符串格式化表达式是最初的方法,让我们从它开始。

Python在对字符串操作的时候定义了%二进制操作符(你可能还记得它在对数字应用时,是除法取余数的操作符)。当应用在字符串上的时候,%提供了简单的方法对字符串的值进行格式化,这一操作取决于格式化定义的字符串。简而言之,%操作符为编写多字符串替换提供了一种简洁的方法,而不是构建并组合单个的部分。

格式化字符串

  • 1.在%操作符的左侧放置一个需要进行格式化的字符串,这个字符串带有一个或多个嵌入的转换目标,都以%开头(例如,%d)。
  • 2.在%操作符右侧放置一个(或多个,嵌入到元组中)对象,这些对象将会插入到左侧想让Python进行格式化字符串的一个(或多个)转换目标的位置上去。

例如,在下列一个格式化示例中,整数1替换在格式化字符串左边的%d,字符串‘bird’替换%s。结果就得到了一个新的字符串,这个字符串就是这两个替换的结果:

>>> print("No. %d:\tI'm a little little %s." % (1, "bird"))
No. 1:  I'm a little little bird.
>>>


从技术上来讲,字符串的格式化表达式往往是可选的一—通常你可以使用多次的多字符串的合并和转换达到类似的目的。然而格式化允许我们将多个步骤合并为一个简单的操作,这一功能相当强大,我们多举几个例子来看一看:

>>> say = "Hello"
>>> "Hello - %s" % say
'Hello - Hello'
>>> "%d %s %d %s" % (2, "hand", 2, "eye")
'2 hand 2 eye'
>>> "%s -- %s -- %s" % (3.14, 'pi', '山巅一寺一壶酒')
'3.14 -- pi -- 山巅一寺一壶酒'
>>>


在第一个例子中,在左侧目标位置插入字符串"Hello",代替标记%s。在第二个例子中,在目标字符串中插入三个值。需要注意的是当不止一个值待插入的时候,应该在右侧用括号把它们括起来(也就是说,把它们放到元组中去)。%格式化表达式操作符在其右边期待一个单独的项或者一个或多个项的元组。
  第三个例子同样是插入三个值:一个整数、一个浮点数对象和一个列表对象。但是注意到所有目标左侧都是%s,这就表示要把它们转换为字符串。由于对象的每个类型都可以转换为字符串(打印时所使用的),每一个与%s一同参与操作的对象类型都可以转换代码。正因如此,除非你要做特殊的格式化,一般你只需要记得用%s这个代码来格式化表达式。
  另外,请记住格式化总是会返回新的字符串作为结果而不是对左侧的字符串进行修改;

由于字符串是不可变的,所以只能这样操作。如前所述,如果需要的话,你可以分配一个变量名来保存结果。

表:字符串格式化代码


代码意义
s字符串(或任何对象)
rs,但使用repr,而不是str
c字符
d十进制(整数)i整数
u无号(整数)八进位整数
o八进制整数
x十六进制整数
Xx,但打印大写
e浮点指数
Ee,但打印大写
f浮点十进制
F浮点十进制
g浮点e或f
G浮点E或f
%常量%

demo:名片打印

要求:输入姓名、年龄、工作和爱好,按下列格式输出:

---info of Linus---
Name : Linus
Age : 18
job : IT
Hobbie : Read
---------end---------


Format格式化(匹配花括号({}))

位置映射

>>> str = "{} 唱歌好听, \n {}唱歌更好听".format("唐友","周亮")
>>> str
'唐友 唱歌好听, \n 周亮唱歌更好听'

>>> "{}---{}---{}".format("木友","井友","河友")
'木友---井友---河友'


关键字映射

>>> "{0}---{name}---{1}".format("木友","水友",name = "河友")
'木友---河友---水友'
>>> "{0}---{name}---{1}".format(("木友","水友"),name = "河友")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
IndexError: tuple index out of range
>>> "{0[0]}---{name}---{0[1]}".format(("木友","水友"),name = "河友")
'木友---河友---水友'
>>> "{0[0]}---{name}---{0[1]}".format(["木友","水友"],name = "河友")
'木友---河友---水友'
>>> "{name}:{age}".format(name = "唐友", age = "19")
'唐友:19'
>>> "{0[0]}---{0[1]}---{1[0]}---{1[1]}".format((1,2),(3,4))
'1---2---3---4'



列表

列表是python中的基础数据类型之一,其他语言中也有类似于列表的数据类型,比如js中叫数组,他是以[]括起来,每个元素以逗号隔开,而且他里面可以存放各种数据类型比如:

li = [‘ex’,123,Ture,(1,2,3,’sir’),[1,2,3,’小明’,],{‘name’:’ex’}]

列表相比于字符串,不仅可以储存不同的数据类型,而且可以储存大量数据,32位python的限制是 536870912 个元素,64位python的限制是 1152921504606846975 个元素。而且列表是有序的,有索引值,可切片,方便取值。

特点:是一个有序的,可以重复的序列,可变类型

1.创建一个空列表

list1 = []
print(type(list1))


2.创建一个有多个值的列表,每个值用逗号隔开。

list = [18,25,16,22,28]


列表页可以存放不同的类型元素。

lst2 = [18,"str",[1,2,3],(66,67),{'name':'Tom','age':18}]


列表索引和切片

>>> lst2 = [18,"str",[1,2,3],(66,67),{'name':'Tom','age':18}]
>>> len(lst2)
5
>>> lst2[0]
18
>>> lst2[3]
(66, 67)
>>> lst2[-1]
{'name': 'Tom', 'age': 18}
>>> lst2[3:]
[(66, 67), {'name': 'Tom', 'age': 18}]
>>> lst2[0::2]
[18, [1, 2, 3], {'name': 'Tom', 'age': 18}]
>>>



列表的常见操作

列表:

names = ['a','b','c','d']


1.增加

append(),extend(),insert()

  • 1.append(),增加到最后
>>> names = ['a','b','c','d']
>>> names.append('e')
>>> names
['a', 'b', 'c', 'd', 'e']
>>> names = ['a','b','c','d']
>>> names.append([1,2,3])
>>> names
['a', 'b', 'c', 'd', [1, 2, 3]]
>>>



  • 2.extend(),迭代的去增
>>> names = ['a','b','c','d']
>>> place = ['beijing','shangdong','usa']
>>> names.extend(place)
>>> names
['a', 'b', 'c', 'd',  'beijing', 'shangdong', 'usa']
>>>



  • 3.insert(),按照索引去增加
>>> names = ['a','b','c','d']
>>> names.insert(2,'devilf')
>>> names
['a', 'b', 'devilf', 'c', 'd']
>>>



  • 4.其他的插入方法
>>> names[3] = 'lebron'
>>> names
['a', 'b', 'devilf', 'lebron', 'd']
>>>



2.删除

pop、remove、del、clear

  • 1.pop()
>>> names.pop() # 没有指定索引时,默认删除最后一个元素
'usa'
>>> names
['a', 'b', 'devilf', 'lebron', 'd', [1, 2, 3], 'beijing', 'shangdong']
>>> names.pop(2) # 指定索引时,就会删除索引所对应的元素
'devilf'
>>> names
['a', 'b', 'lebron', 'd', [1, 2, 3], 'beijing', 'shangdong']
>>>



  • 2.remove(),按照元素删除
>>> names.remove('b')
>>> names
['a', 'lebron', 'd', [1, 2, 3], 'beijing', 'shangdong']
>>>


  • 3.del
>>> del names[4]
>>> names
['a', 'lebron', 'd', [1, 2, 3], 'shangdong']
>>>


  • 4.clear()
>>> names.clear()
>>> names
[]
>>>



3.改

>>> li = ['a','b','c','d']
>>> li[1] = 'cc'
>>> li
['a', 'cc', 'c', 'd']
>>> li[0:2] = ['aa','bb']
>>> li
['aa', 'bb', 'c', 'd']



4.查

切片去查,或者,循环去查

  • 索引,切片,遍历

1.查找元素所在位置:index()

>>> names = ['a','b','c','d']
>>> names.index('c')
2
>>>



  • 遍历

两种:

(1)

>>> li = ['python','Java','C++']
>>> for i in li:
...     print(i,end = " ")
...
python Java C++ >>>



(2)

>>> li = ['python','Java','C++']
>>> for i in range(len(li)):
...     print(li[i],end = " ")
...
python Java C++ >>>



5.其他操作

1.统计元素的次数:count()

>>> names = ['a', 'b', 'c', 'd']
>>> names.append('d')
>>> names.count('d')
2
>>>



2.反转:reverse()

>>> names = ['a', 'b', 'c', 'd']
>>> names.reverse()
>>> names
['d', 'd', 'c', 'b', 'a']



3.排序:sort()按照ascii码来进行排序

>>> names = ['d', 'd', 'b', 'a']
>>> names.insert(3,'&&')
>>> names
['d', 'd', 'c', '&&', 'b', 'a']
>>> names.sort()
>>> names
['&&', 'a', 'b', 'c', 'd', 'd']
>>> names.sort(reverse=True)
>>> names
['d', 'd', 'c', 'b', 'a', '&&']
>>> names[::-1]
['&&', 'a', 'b', 'c', 'd', 'd']
>>>



索引与元素同时遍历

>>> li = ['python','Java','C++']
>>> for i, li[i] in enumerate(li):
...     print(i,li[i])
...
0 python
1 Java
2 C++
>>>



元组

元组:

是一个有序的,可重复的,不可更改的对象;


特点:
	1.与list类似;
	2.不可变类型数据;
	3.元组使用的是()


元组的基本使用格式:
(元素1,元素2,......,元素n)


基本描述:

​ 元组使用()包裹起来的多个元素的数据类型,每个元素之间用","隔开

​ ,隔开返回的是两个元祖

1.元祖的创建

  • 创建一个空元祖
>>> t1 = ()
>>> type(t1)
<class 'tuple'>
>>> st1 = tuple()
>>> t1,st1
((), ())
>>> type(t1),type(st1)
(<class 'tuple'>, <class 'tuple'>)


  • 创建只含有一个元素的元组

需要注意的地方是,如果我们创建只含有一个元素的元组,我们必须在这仅有的一个元素后加上一个","

>>> t1 = (6)
>>> t1,type(t1)
(6, <class 'int'>)


>>> t1 = (6,) # 只有一个元素的元组,必须加上","
>>> t1,type(t1)
((6,), <class 'tuple'>)


  • 创建含有多个元素的元组
>>> t1 = ("水友","井友","溪友","河友","海友")


和列表一样,元祖的元素也可以是不同的数据类型的元素。

>>> t1 = (1,"hunan",['h','u','n','a','n'],('I','love','python'),{"name":"tom","age":18})


2.元组的基本操作

  • 通过索引值查找对应的元素
>>> t1 = (1,"hunan",['h','u','n','a','n'],('I','love','python'),{"name":"tom","age":18})
>>> t1[4]
{'name': 'tom', 'age': 18}
>>> t1[-1]
{'name': 'tom', 'age': 18}
>>> t1[::-2]
({'name': 'tom', 'age': 18}, ['h', 'u', 'n', 'a', 'n'], 1)


  • 查找元素的索引值
>>> t1 = (1,"hunan",['h','u','n','a','n'],('I','love','python'),{"name":"tom","age":18})
>>> t1.index("hunan")
1


注意:元组是不可变的数据类型,不能够增,删,改

>>> t1 = (1,"hunan",['h','u','n','a','n'],('I','love','python'),{"name":"tom","age":18})
>>> t1[0] = 0
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'tuple' object does not support item assignment


注意到t1里面有个列表,那么这个列表中的元素是否可以更改?

>>> t1 = (1,"hunan",['h','u','n','a','n'],('I','love','python'),{"name":"tom","age":18})
>>> t1[2]
['h', 'u', 'n', 'a', 'n']
>>> t1[2][2]
'n'
>>> t1[2][2] = 'N'
>>> t1
(1, 'hunan', ['h', 'u', 'N', 'a', 'n'], ('I', 'love', 'python'), {'name': 'tom', 'age': 18})


拼接

>>> t1 = ('a','b','c')
>>> t2 = ('d','e','f')
>>> t1 + t2
('a', 'b', 'c', 'd', 'e', 'f')


重复

>>> t1 * 3
('a', 'b', 'c', 'a', 'b', 'c', 'a', 'b', 'c')


判断元素是否存在

>>> t1 = ('a','b','c')
>>> 'a' in t1
True
>>> 'a' not in t1
False



内置函数(最大值最小值)

>>> t1 = ('a','b','c')
>>> max(t1)
'c'
>>> min(t1)
'a'


元组的遍历

1.值遍历

tp = ('Python','Java','C++')
for i in tp:
	print(i,end = " ")
# Python Java C++


2.索引遍历

>>> t1 = ('a','b','c')
>>> for i in range(len(t1)):
...     print(t1[i])
...
a
b
c


3.索引值,遍历

枚举(enumerate),对于一个可迭代的(iterable)/可遍历的对象(如列表、字符串)enumerate将其组成一个索引序列,利用它可以同时获得索引和值

>>> tp = ('Python','Java','C++')
>>> for index, value in enumerate(tp):
...     print(index, ':', value)
...
0 : Python
1 : Java
2 : C++

>>> for index, value in enumerate(tp,6):
...     print(index, ':', value)
...
6 : Python
7 : Java
8 : C++


字典

思考:

场景1

如果有列表

li = ['Pyhton', 'Java', 'C++'];

需要对"pyhton"这个名字写错了,通过代码修改:

li[0] = "Python"

如果列表的顺序发生了变化,如下

li = ['Java', 'C++', 'Pyhton'];

此时就需要修改下标,才能完成名字的修改

li[2] = "Python"

有没有方法,既能存储多个数据,还能在访问元素的很方便就能够定位到需要的那个元素呢?

答:

​ 字典

场景2:

学生信息列表,每个学生信息包括学号、姓名、年龄等,如何从中找到某个学生的信息?


> > >  studens = [[201801, "张三", 18], [201802, "李四", 19], [201803, "王二",17], ...]
> > >  ```

循环遍历? 这样很麻烦。

实际生活中,我们还经常使用汉语字典,英汉词典等等。

程序中的字典:

info = {"username":"Lilei","age":18,"Class":"one"}


​ 字典(dictionary)是除列表以外python之中最灵活的内置数据结构类型。字典是一种可变的数据类型。且可存储任意类型对象。列表是有序的对象结合,字典是无序的对象结合。两者之间的区别在于:字典当中的元素是通过键来存取的,而不是通过偏移存取。

格式:
	{key1:value1,key2:value2,......}


描述:

​ 1.键-值对中间用冒号(":")连接;

​ 2.key:value组成字典里的元素;

​ 3.键-值对(元素)之间用逗号(",")隔开;

​ 4.整个字典用花括号"{}"包裹起来。

字典的创建

创建一个空字典
>>> dic = {}
>>> type(dic)
<class 'dict'>


创建一个有多个值的字典

1.直接赋值法:d = {key1:value1,key2:value2},如

1.
>>> info = {"username":"Lilei","age":18,"Class":"one"}
>>> info
{'username': 'Lilei', 'age': 18, 'Class': 'one'}


拓展:

>>> key1 = "name"
>>> key2 = "age"
>>> value1 = "Tom"
>>> value2 = 18
>>> d = {key1:value1,key2:value2}
>>> d
{'name': 'Tom', 'age': 18}


2.通过函数创建字典(强制转换):

# 法1
>>> info = dict(usrname = "Lilei", age = 18, Class = "one")
>>> info
{'usrname': 'Lilei', 'age': 18, 'Class': 'one'}
# 法2
>>> info = dict([['name', 'LiLei'], ['age', 18]])
>>> info
{'name': 'LiLei', 'age': 18}
# 法3
>>> info = dict((('name', 'LiLei'), ('age', 18)))
>>> info
{'name': 'LiLei', 'age': 18}
# 法4
>>> info = dict([('name', 'LiLei'), ('age', 18)])
>>> info
{'name': 'LiLei', 'age': 18}
# 法5
>>> info = dict((['name', 'LiLei'], ['age', 18]))
>>> info
{'name': 'LiLei', 'age': 18}


3.通过字典的fromkeys方法创建字典

>>> info = dict.fromkeys("Hello") # 如果没有指定默认值,默认为 None
>>> info
{'H': None, 'e': None, 'l': None, 'o': None}
>>> info = dict.fromkeys(["Lilei","Lee","Jack"],"123456") # 给每个元素设置默认值为"123456";
>>> info
{'Lilei': '123456', 'Lee': '123456', 'Jack': '123456'}


字典的常见操作

字典值的访问(查的一种)

字典是无序的,不是通过索引值来获取值。

>>> info = info[2]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
KeyError: 2


  • 通过键(key)访问值(value)
    • key值不存在的时候,会报错
>>> info = {"username":"Lilei","age":18,"Class":"one"}
>>> info["username"] # 通过关键字访问对应的值
'Lilei'
>>> info["age"]
18
>>> info["ysername"] 
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
KeyError: 'ysername'


  • 使用get访问值(value)

    不确定字典中是否存在某个键而又想获取值时,可以使用get方法,还可以设置默认值

    • 当key不存在的,不会抛出异常,返回None
>>> info = {"name":"Lilei","age":18}
>>> info.get("name")
'Lilei'
# 当key不存在的,不会抛出异常,返回None
>>> info.get("job")
>>> type(info.get("job"))
<class 'NoneType'>


  • 直接添加新键-值对

    在使用变量名[‘键’] = 数据时,这个"键"在字典中,不存在,那么就会新增这个元素:

>>> info["job"] = "IT"
>>> info
{'name': 'Lilei', 'age': 18, 'job': 'IT'}


  • dict.update()

    把字典info1的键/值对更新到info里

    • 当两个字典中的键不同时,把info1的键值插入到info中
    • 当两个字典中存在相同键时,info1覆盖info的键值
# 当两个字典完全不相同时
>>> info = {"name":"Lilei","age":18}
>>> info1 = {"job":"IT","salary":10000}
>>> info.update(info1)
>>> info
{'name': 'Lilei', 'age': 18, 'job': 'IT', 'salary': 10000}
>>> info1
{'job': 'IT', 'salary': 10000}
>>>
# 当两个字典存在相同键时,会覆盖前面的键值
>>> info = {"name":"Lilei","age":18}
>>> info1 = {"name":"Tom","salary":10000}
>>> info.update(info1)
>>> info
{'name': 'Tom', 'age': 18, 'salary': 10000}
>>> info1
{'name': 'Tom', 'salary': 10000}


  • del dict[keys]
    • 删除指定的元素键/值对
    • 没有返回值
>>> info = {"name":"Lilei","age":18}
>>> del info["name"]
>>> info
{'age': 18}


  • del dict
    • 删除整个字典
>>> info = {"name":"Lilei","age":18}
>>> del info


  • dict.clear()
    • 清空整个字典
>>> info = {"name":"Lilei","age":18}
>>> info.clear()
>>> info
{}


  • dict.pop(keys)
    • 删除指定键/值对
>>> info = {'name': 'Tom', 'age': 18, 'salary': 10000}
>>> info.pop("age")
18
>>> info
{'name': 'Tom', 'salary': 10000}


  • dict.popitem()
    • 随即删除字典中的一组键值对
    • 有返回值,以元组的方式返回
    • 应用不广泛
>>> info = {'name': 'Tom', 'age': 18, 'salary': 10000}
>>> info.popitem()
('salary', 10000)
>>> info
{'name': 'Tom', 'age': 18}


字典的每个元素中的数据是可以修改的,只要通过key找到,即可修改

  • 直接修改
>>> info = {'name': 'Tom', 'age': 18, 'salary': 10000}
>>> info["name"] = "Lilei"
>>> info
{'name': 'Lilei', 'age': 18, 'salary': 10000}


  • dict.setdefault()
    • 键存在,不改动,返回字典中相应的值
    • 键不存在,在字典中添加相应的键值对,并返回相应的值
# 键存在,不改动,返回字典中相应的值
>>> info = {'name': 'Tom', 'age': 18, 'salary': 10000}
>>> info.setdefault("age",20) # 有返回值
18
>>> info
{'name': 'Tom', 'age': 18, 'salary': 10000}

# 键不存在,在字典中添加相应的键值对,并返回相应的值
>>> info = {'name': 'Tom', 'age': 18, 'salary': 10000}
>>> info.setdefault("job","IT")
'IT'
>>> info
{'name': 'Tom', 'age': 18, 'salary': 10000, 'job': 'IT'}


  • dict.keys()
    • 返回字典中的所有键(key)
  • dict.values()
    • 返回字典中的所有键(value)
  • dict.items()
    • 返回字典中的所有键-值对(keys-values)
  • 某元素是否存在:
    • key in dict
      • 存在,True
      • 不存在,False
>>> info = {'name': 'Tom', 'age': 18, 'salary': 10000}
>>> info.keys()
dict_keys(['name', 'age', 'salary'])

>>> info.values()
dict_values(['Tom', 18, 10000])

>>> info.items()
dict_items([('name', 'Tom'), ('age', 18), ('salary', 10000)])

>>> "age" in info
True

>>> "job" in info
False



字典的遍历

(1)遍历字典的键(key)

>>> info = {"username":"Lilei","age":18,"Class":"one"}
>>> for key in info.keys():
...     print(key,end = " ")
username age Class 


(2)遍历字典的值(value)

>>> info = {"username":"Lilei","age":18,"Class":"one"}
>>> for value in info.values():
...     print(value,end = " ")
Lilei 18 one 


(3)遍历字典所有的项(items)

>>> info = {"username":"Lilei","age":18,"Class":"one"}
>>> for item in info.items():
...     print(item,end = " ")
('username', 'Lilei') ('age', 18) ('Class', 'one') 


(4)遍历字典的键值对

>>> info = {"username":"Lilei","age":18,"Class":"one"}
>>> for key,value in info.items():
...     print(key,":",value,end = " ")
username : Lilei age : 18 Class : one 


集合

集合是无序的,不重复的且不可以更高的数据集合,它里面的元素是可哈希的(不可变类型),但是集合本身是不可哈希(所以集合做不了字典的键)的。以下是集合最重要的两点:

  • 去重,把一个列表变成集合,就自动去重了。
  • 关系测试,测试两组数据之前的交集、差集、并集等关系。

集合的创建

创建一个空的集合

这里需要注意,我们不可以直接用花括号"{}"

>>> st = set()
>>> st
set()
>>> st1 = {}
>>> type(st),type(st1)
(<class 'set'>, <class 'dict'>)


多元素的集合创建

>>> st = {"a","b","c","d","e"}
>>> st,type(st)
({'a', 'b', 'c', 'e', 'd'}, <class 'set'>)
>>> st = {1,2,3,[1,2]} # 列表是可变类型,所以会报错
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'list'
>>> st = {1,2,3,{"age":18}} # 列表可变
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'dict'
>>> st = {1,2,3,(1,2)} # 元组是不可变类型,所以不会报错
>>> st
{(1, 2), 1, 2, 3}



集合的强转

>>> li = [1,"a","n","University"]
>>> st_li = set(li)
>>> st_li,type(st_li)
({'n', 1, 'University', 'a'}, <class 'set'>)

>>> str = "Universitysity"
>>> st_str = set(str)
>>> st_str,type(st_str)
({'n', 'r', 's', 'v', 'U', 't', 'y', 'i', 'e'}, <class 'set'>)

>>> dic = {"a":1,"b":2,"c":3,"d":4}
>>> st_dic = set(dic)
>>> st_dic,type(st_dic)
({'c', 'b', 'a', 'd'}, <class 'set'>)


集合的基本操作

  • 无序,不可查找
>>> st = {1,2,"Hunan","Yingxiao","College"}
>>> st[2]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'set' object does not support indexing


  • set.add()
  • set.update()
>>> st = {1,2,"Hunan","Yingxiao","College"}
>>> st.add("Computer Science")
>>> st
{1, 2, 'Computer Science', 'College', 'Yingxiao', 'Hunan'}
>>> st.update("湖南","长沙")
>>> st
{1, 2, '湖', '长', 'Computer Science', '南', 'College', 'Yingxiao', 'Hunan', '沙'}


  • set.pop()
  • set.discard()
  • set.remove()
>>> st = {1,2,"Hunan","Yingxiao","College"}
>>> st.pop() # 删除排序最小的一个元素
1
>>> st
{2, 'College', 'Yingxiao', 'Hunan'}

>>> st = {1,2,"Hunan","Yingxiao","College"}
>>> st.discard(2) # 移除元素
>>> st
{1, 'College', 'Yingxiao', 'Hunan'}
>>> st.discard("HUNAN") # 如果元素不存在,不会报错,不做任何操作
>>> st
{1, 'College', 'Yingxiao', 'Hunan'}

>>> st = {1,2,"Hunan","Yingxiao","College"}
>>> st.remove(2) # 删除指定元素,如果元素不存在就会报错
>>> st
{1, 'College', 'Yingxiao', 'Hunan'}
>>> st.("HUNAN")
  File "<stdin>", line 1
    st.("HUNAN")
       ^
SyntaxError: invalid syntax


  • set.clear()
  • del set名
>>> st = {1,2,3}
>>> st.clear()
>>> st
set()
>>> st = {1,2,3}
>>> del st
>>> st
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'st' is not defined


改,不可更改

>>> st = {1,2,3}
>>> st[0] = "Hunan"
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'set' object does not support item assignment


遍历

>>> st = {1,2,"Hunan","Yingxiao","College"}
>>> for i in st:
...     print(i,end = " ")
...
1 2 College Yingxiao Hunan

>>> st = {1,2,"Hunan","Yingxiao","College"}
>>> for index,value in enumerate(st):
...     print(index,value)
...
0 1
1 2
2 College
3 Yingxiao
4 Hunan



比较

集合的基本运算

子集

>>> a = set("abcd")
>>> b = set("cdef")
>>> c = set("ab")
>>> a,b,c
({'c', 'b', 'a', 'd'}, {'c', 'f', 'e', 'd'}, {'b', 'a'})
>>> c.issubset(a)
True
>>> c < a
True
>>> c < b
False


交集

>>> a = set("abcd")
>>> b = set("cdef")
>>> a.intersection(b)
{'c', 'd'}
>>> a & b
{'c', 'd'}


并集

>>> a = set("abcd")
>>> b = set("cdef")
>>>a.union(b)
{'b', 'f', 'a', 'd', 'c', 'e'}
>>>a|b
{'b', 'f', 'a', 'd', 'c', 'e'}


差集

>>> a = set("abcd")
>>> b = set("cdef")
>>>a.difference(b)
{'a', 'b'}
>>>a-b
{'a', 'b'}


函数

  • 数学意义上的函数
    • y=2x+1,y|_{x=3}=2×3+1=7
  • 编程意义上的函数

python中函数的定义:函数是逻辑结构化和过程化的一种编辑方式

函数是可以重复使用的程序段,在开发程序中,需要某代码块多次,但是为了提高编写的效率以及代码的重用,所以把具有独立功能的代码块组织为一个小模块,这就是函数。

他们允许你给一块语句一个名称,然后你可以在你的程序的任何地方使用这个名称任意多次的运行这个语句块,这被称为 调用函数 ,我们已经使用了许多内建的函数,比如len()和range()。

函数的定义和调用

函数定义

  • 空函数

如果定义一个事也不做的空函数,可以使用 pass 语句:

def func():
    pass


pass 语句什么都不做,那有什么用?实际上 pass 可以用来作为占位符,比如现在还没想好怎么写函数的代码,就可以先放一个 pass ,让代码能运行起来。

  • 非空函数

函数通过def关键字定义,def关键字后跟一个函数的 标识符 名称 ,然后跟一对圆括号,圆括号之中可以包括一些变量名,该行以圆括号结尾。接下来是一块语句,它们是函数体。

声明函数的一般形式如下:

def 函数名(参数列表):
    '''说明'''
    函数语句
    return 返回值


说明如下:

​ 1.函数代码块以 def 关键字开头,后接函数标识符名称和小括号()。

​ 2.任何传入参数和自变量必须放在圆括号中间,圆括号之间可以用于定义参数

​ 3.函数的第一行语句可以选择性地使用文档字符串-----用于存放函数说明。

​ 4.函数内容以冒号起始,并且缩进。

​ 5.return[表达式]结束函数,选择性的返回一个值给调用方,不带表达式的return相当于返回None。其中参数列表和返回值不是必须的,return后也可以不跟返回值,甚至连 return 也没有。对于 return 后没有返回值的和没有return语句的函数都会返回None值,有些函数可能既不需要传递参数,也没有返回值。没有参数时,包含参数的圆括号也必须写上,圆括号后也必须有":"。

def info():
	"""打印信息"""
	print("name":"Tom","age":18)
info()


函数调用

函数定义后,我们就具备了实现某种功能的代码。执行这些代码, 只需要调用函数。

函数的调用形式

函数名()


比如上面我们已经定义好了info()函数,现在我们调用:

info()


现在整体写出代码:

# 定义函数
def info():
    """打印信息"""
    print({"name":"Tom","age":18})
# 调用函数
info()


运行,结果为:

{"name":"Tom","age":18}


函数文档说明

在上面代码的基础上,添加

help(info)


运行后,结果为

Help on function info in module _main_:
    
info()
	打印信息


可以看到,help()返回info()函数的相关说明。

直接查看文档说明

print(info._doc_)
# 打印信息


函数参数

假如我们定义一个函数计算两个数的积,有人设计如下函数:

def mul():
	x = 3
    y = 3
    print(x * y)
mul() # 9


这样可以吗?

这个函数只能实现3*3的效果,并不具备通用性。

为了让这个函数更具通用性,我们可以添加参数:

def mul(x,y):
    print(x * y)
mul(3, 6) # 调用


  • 参数调用的顺序

我们可以先看一下以下例子:

>>> def test(x, y):
...     print(x)
...     print(y)
...
>>> test(x = 1, y = 2)
1
2
>>> test(y = 2, x = 1)
1
2
>>> test(1, y = 2)
1
2
>>> test(x = 1, 2)
  File "<stdin>", line 1
SyntaxError: positional argument follows keyword argument


函数返回值

这里形象的解释一下函数:函数就是把一堆代码,打包放在那里, 比如说一个发邮件的功能,然后这个 功能被调用,说到这里大家应该会想知道,我们调了,但是调的一个结果是啥?有没有成功?如果成功,干A的事,如果不成功做B的事情。

返回值的定义:函数外部的代码要想获得函数的执行结果,就可以 在函数里调用return语句把结果返回。

函数参数种类

首先,了解两个概念:形参合实参

  • 1.形参:
    • 只有在被调用时才分配内存单元, 在调用结束时,即可释放所分配的内存单元,因此,形参只在函数内部有效,函数调用结束返回主调用函数后则不能再使用该形参变量;
  • 2.实参:
    • 实参可以是常量,变量,表达式,函数等,无论实参是何种类型的量, 在进行函数调用时,他们都必须有确定的值,一边把这些值传给形参,因此应预先用赋值, 输入等办法是参数获得确定值;
>>> def test(x, y):
...     print(x)
...     print(y)
...
>>> test(1, 2) # 1, 2 ---> 实参
1
2


  • 形参就是一把椅子,放在这里,占个位置而已,直到有人调用,赋值的时候才会分配内存单元,在调用时结束,即可释放;
  • 实参,就是实实在在,什么类型都接受;

1.位置参数

def user_manger(name, age, job, hobby):
    print("用户管理系统".center(16, '-'))
    print("\tName",name)
    print("\tAge",age)
    print("\tJob",job)
    print("\tHobby",hobby)
    print("用户管理系统".center(16, '-'))
user_manger('Tom', 22 , 'IT' , 'Read')
user_manger('Lilei', 23 , 'IT' , 'Sing')
user_manger('Jim' , 21 , 'IT' , 'Dance')


位置参数须以正确的顺序传入函数。调用时的数量必须和声明时的一样

2.默认值参数

假如我们设置hobby值为默认,即hobby = “Coding”。

def user_manger(name, age, job, hobby = "Coding"):
    print("用户管理系统".center(16, '-'))
    print("\tName",name)
    print("\tAge",age)
    print("\tJob",job)
    print("\tHobby",hobby)
    print("用户管理系统".center(16, '-'))
user_manger('Lucy', 21, "It") # 不传入参数,即为默认值。
user_manger('Tom', 22 , 'IT' , 'Read') # 传入参数,则改变值
user_manger('Lilei', 23 , 'IT' , 'Sing') # 传入参数,则改变值


通过观察,可知:

如果定义默认参数,在调用的时候,不给实参, 就会调用默认参数

如果函数定义修改为:

def user_manger(name, age, hobby = "Coding", job):


运行将报错:

def user_manger(name, age, hobby = "Coding", job):
                   ^
SyntaxError: non-default argument follows default argument


因此,默认参数必须要放到位置参数后边;

3.关键字参数

正常情况下,给函数传参数要按顺序,不想按顺序就可以用关键参致,只需指定参数名即可(指定了参数名的参数就叫关键参数)。

def user_manger(name, age, job = "IT", hobby = "Coding"):
    print("用户管理系统".center(16, '-'))
    print("\tName",name)
    print("\tAge",age)
    print("\tJob",job)
    print("\tHobby",hobby)
    print("用户管理系统".center(16, '-'))
user_manger('Tom', age = 22 , hobby = "Read" , job = "IT") # 传参时,关键字参数可以位置改变
user_manger('Lilei', 23 , 'IT' , 'Sing') # 不传关键字时,必须一一对应


思考下列两种方式是否可以?

user_manger('Lucy', age = 21 , 'IT' , 'Read')
user_manger('Lucy', 22 , 'IT' , age = 21)


user_manger('Lucy', age = 21 , 'IT' , 'Read')
# 报错将如下:
	user_manger('Lucy', age = 21 , 'IT' , 'Read')
                                  ^
SyntaxError: positional argument follows keyword argument
    
user_manger('Lucy', 22 , 'IT' , age = 21)
# 报错将如下:
	user_manger('Lucy', 22 , 'IT' , age = 21)
TypeError: user_manger() got multiple values for argument 'age'


关键参数必须放在位置参数(以位置顺序确定对应关系的参致)之后。

4.不定参数

Python的不定参数,主要指 *args 和 **kwargs 这两个魔法变量。那么它们到底是什么?

起始并不是必须写成 *args 和 **kwargs。只有变量前面的 * 才是必须的。也可以写成 **var **vars。而写成 *args 和 **kwargs 只是一个通俗的命名约定。

*args 和 **kwargs 主要用于函数定义。我们可以将不定义的参数传递给一个函数。

这里的不定的意思是:预先并不知道,函数使用者会传递多少个参数给你,所以在这个场景下使用这两个关键字。

  • *args的用法

*args 是用来发送一个非键值对的任意数量的可变数量的参数列表给一个函数。

下面我们举例来帮大家理解:

def uncertain_para(para, *args):
    print("普通参数:", para)
    print("不定参数:", args)
    print(type(args))
    for arg in args:
        print('注意输出不定参数:', arg)
uncertain_para(1, 2, 3, 4, 5)    


运行后输出:

普通参数:1
不定参数:(2345)
<class 'tuple'>
逐一输出不定参数:2
逐一输出不定参数:3
逐一输出不定参数:4
逐一输出不定参数:5


我们可以看出,在这个例子中,para接受了传递的第一个参数,而args则是由所有其他位置参数组成的元组。

**kwargs

**kwargs 允许我们讲不定长度的键值对,作为参数传递给一个函数。

当我们想要在一个函数里处理一个带名字的参数时,就可以使用 **kwargs

比如:

def uncertain_para_key(**kwargs):
    print(type(kwargs))
    print(kwargs)

uncertain_para_key(a = 3, b = 4, c = 5)


运行后输出:

<class 'dict'>
{'a': 3, 'b': 4, c: 5}


*args 和 **kwargs 的使用
def test_args_kwargs(para1, para2, para3):
    print("para1:", para1)
    print("para2:", para2)
    print("para3:", para3)
    
args = ("abc", 6, 9)
print(test_args_kwargs(*args))
kwargs = {"para1":3, "para2":"xyz", "para3": [1, 2, 3]}
print(test_args_kwargs(**kwargs))


运行后输出:

para1: abc
para2: 6
para3: 9
None
para1: 3
para2: xyz
para3: [1, 2, 3]
None


注意这里传递键值参数时,需满足参数数量一致,否则会报错。

标准参数与 *args、 **kwargs在使用时的顺序

那么如果你想在函数里同时使用所有的这三种参数,顺序是这样的:

func(fargs, *args, **kwargs)

举例如下:

def test_args_kwargs(para1, *para2, **para3):
    print("para1:", para1)
    print("para2:", para2)
    print("para3:", para3)
    
print(test_args_kwargs(1, 2, 3, 4, a = 5, b = 6, c = 7))


输出结果为:

para1: 1
para2: (2, 3, 4)
para3: {'a': 5, 'b': 6, 'c': 7}
None


声明与定义比较

​ 在某些编程语言里, 函数声明和函数定义区分开的。一个函数声明包括提供对函数名,参数的名字(传统上还有参数的类型), 但不必给出函数的任何代码, 具体的代码通常属于函数定义的范畴。

​ 在声明和定义有区别的语言中, 往往是因为函数的定义可能和其声明放在不同的文件中。 python将这两者视为一体,函数的子句由声明的标题行以及随后的定义体组成的。

前向引用

和其他高级语言类似,Python 也不允许在函数未声明之前,对其进行引用或者调用.

我们下面给出几个例子来看一下:

def foo():
    print("in foo()")
    bar()

def bar():
    print("in bar()")

foo()

运行结果

in foo()
in bar()

这段代码是正确的因为即使(在 foo()中)对 bar()进行的调用出现在 bar()的定义之前,但 foo()本身不是在 bar()声明之前被调用的。换句话说,我们声明 foo(),然后再声明bar(),接着调用 foo(),但是到那时,bar()已经存在了,所以调用成功。

注意 ,foo()在没有错误的情况下成功输出了’in foo()’。名字错误是当访问没有初始化的标识符时才产生的异常 。

函数属性

​ 你可以获得每个python模块、类、和函数中任意的名字空间,你可以在模块foo和bar里都有名为x的一个变量,但是再将这两个模块导入你的程序后,任然可以使用这两个变量。所以,即使在两个模块中使用了相同的变量名字,这也是安全的,因为句点属性标识对于两个模块意味了不同的命名空间,比如说,在这段代码中没有名字冲突:

import foo, bar
print(foo.x + bar.x)

​ 函数属性是python另外一个使用了句点属性标识并拥有名字空间的领域

def foo():
    'foo() --- properly created doc string'
    
def bar():
    pass
bar._doc_ = 'Oop, forgot the doc str above'
bar.version = 0.1

​ 上面的foo()中,我们以常规的方式创建了我们的文档字符串,比如,在函数声明后第一个没有复制的字串。当声明bar()时,我们什么都没做,仅用了句点属性标识来增加文档字符串以及其他属性,我们可以接着任意地访问属性,下面是一个使用了交互解释器的例子、(你可能已经发现没用内建函数help()显示会比用_doc_属性更漂亮,但是你可以选择你喜欢的方式)

>>> help(foo)
Help on function foo in module __main__:

foo()
    foo() --- properly created doc string
>>> bar.version
0.1
>>> foo._doc_
'foo() --- properly created doc string'
>>> bar._doc_
'Oop, forgot the doc str above'

注意我们是如何在函数声明外定义一个文档字串。然而我们仍然可以就像平常一样,在运行时刻访问它。然而你不能在函数的声明中访问属性。换句话说,在函数声明中没有’self‘这样的东西让你可以进行诸如__dict__[‘version’] = 0.1 的赋值。这是因为函数体还没有被创建,但之后你有了函数对象,就可以按我们在上面描述的那样方法来访问它的字典。另外一个自由的名字空间!

内部/内嵌函数

在函数体内创建另外一个函数(对象)是完全合法的,这种函数叫做内部/内嵌函数

最明显的创造内部函数的方法是在外部函数的定义体内定义函数(用def关键字),如在:

def foo():
    def bar():
        print("bar() called.")
    print('foo() called')
    bar()

foo()
bar()

foo() called
bar() called.
Traceback (most recent call last):
  File "E:/Python/3.13.py", line 288, in <module>
    bar()
NameError: name 'bar' is not defined

内部函数一个有趣的方面在于整个函数体都在外部函数的作用域(即是你可以访问一个对象的区域;稍后会有更多关于作用域的介绍)之内。如果没有任何对 bar()的外部引用,那么除了在函数体内,任何地方都不能对其进行调用,这就是在上述代码执行到最后你看到异常的原因

另外一个函数体内创建函数对象的方式是使用lambda 语句。 稍后讲述。如果内部函数的定义包含了在外部函数里定义的对象的引用(这个对象甚至可以是在外部函数之外),内部函数会变成被称为闭包(closure)的特别之物。

函数应用:打印图形和数学计算

函数的嵌套使用:

程序设计的思路,复杂的问题分解为简单问题。

  • 思考1:编程实现:
    • 写一个函数打印一条横线
    • 打印自定义行数的横线

参考代码

def line():
    print("-"*15)
line()

打印多条横线:

def line():
    print("-"*15)
def lines(n):
    for i in range(n):
        line()
lines(3)

  • 思考二:编程实现
    • 写一个函数求三个数的和
    • 写一个函数求三个数的平均值

参考代码

# 求三个数的和
def operation(a, b, c):
    return a + b + c
print(operation(3, 4, 9))

# 完成对3个数求平均值
def operations(a, b, c):
    sumResult = operation(a, b, c)
    aveResult = sumResult/3.0
    return aveResult
result = operations(13, 25, 34)
print("average is %d"%result)

变量作用域

标识符的作用域是定义为其声明在程序里的可应用范围, 或者即是我们所说的变量可见性。换句话说,就好像在问你自己,你可以在程序里的哪些部分去访问一个制定的标识符。变量可以是局部域或者全局域。

全局变量与局部变量

定义在函数内的变量有局部作用域,在一个模块中最高级别的变量有全局作用域。

“声明适用的程序的范围被称为了声明的作用域。 在一个过程中, 如果名字在过程的声明之内,它的出现即为过程的局部变量;否则的话,出现即为非局部的“ 。

全局变量的一个特征是除非被删除掉,否则它们的存活到脚本运行结束,且对于所有的函数,他们的值都是可以被访问的,然而局部变量,就像它们存放的栈,暂时地存在,仅仅只依赖于定义它们的函数现阶段是否处于活动。当一个函数调用出现时,其局部变量就进入声明它们的作用域。在那一刻,一个新的局部变量名为那个对象创建了,一旦函数完成,框架被释放,变量将会离开作用域 。

关 于 所 有 变 量 名, 包 括 作 用 域 的 定 义 在 内, 都 是 在 Python 赋 值 的 时 候 生 成 的。 正 如 我 们 所 知, Python 中 的 变 量 名 在 第 一 次 赋 值 时 已 经 创 建, 并 且 必 须 经 过 赋 值 后 才 能 够 使 用。 由 于 变 量 名 最 初 没 有 声 明, Python 将 一 个 变 量 名 被 赋 值 的 地 点 关 联 为( 绑 定 给) 一 个 特 定 的 命 名 空 间。 换 句 话 说, 在 代 码 中 给 一 个 变 量 赋 值 的 地 方 决 定 了 这 个 变 量 将 存 在 于 哪 个 命 名 空 间, 也 就 是 它 可 见 的 范 围。

局部变量

先看一个例子:

def foo():
    a = 666
    print('foo(),修改前a:\t', a)
    a = 800
    print('foo(),修改后a:\t', a)

def bar():
    a = 6688
    print("bar(),a:\t", a)
foo()
bar()

运行结果

foo(),修改前a:	 666
foo(),修改后a:	 800
bar(),a:	 6688

可以看出:

  • 局部变量,就是在函数内部定义的变量
  • 不同的函数,可以定义相同的名字的局部变量,但是各用个的不会产生影响
  • 局部变量的作用,为了临时保存数据需要在函数中定义变量来进行存储,这就是它的作用

全局变量

同样,先看一下例子:

a = 6688
def foo():
    print('foo(),a:\t', a)

def bar():
    print('bar() a:\t', a)

print(foo())
print(bar())

运行结果:

foo(),a:	 6688
None
bar() a:	 6688
None

讨论1:

​ 如果全局变量和局部变量名字相同?

a = 6688
def foo():
    a = 666
    print('foo(),修改前a:\t', a)
    a = 800
    print('foo(),修改前a:\t', a)

def bar():
    print("bar(),a:\t", a)
foo()
bar()

运行结果:

foo(),修改前a:	 666
foo(),修改前a:	 800
bar(),a:	 6688

讨论2:

​ 全局变量,是能够在所有的函数中进行使用的变量,那么局部变量可否进行修改编程全局变量呢?

global语句

如果将全局变量名字生命在一个函数体内的时候,全局变量的名字能被局部变量给覆盖掉。

a = 6688
def foo():
    global a
    print('foo(),修改前a:\t', a)
    a = 666
    print('foo(),修改前a:\t', a)

def bar():
    print("bar(),a:\t", a)
foo()
bar()

运行结果:

foo(),修改前a:	 6688
foo(),修改前a:	 666
bar(),a:	 666

通过以上例子,我们可以观察出:

  • 在函数外边定义的叫做 全局变量
  • 全局变量能够在所有函数中进行访问
  • 如果在函数中修改全局变量,那么就需要使用global进行声明,否则出错
  • 如果全局变量的名字和局部变量名字相同,那么使用的是局部变量的

可变类型的全局变量

先举两个例子:

例1:

a = 1
def foo():
    a += 1
    print(a)
a
foo()

运行结果:

Traceback (most recent call last):
  File "E:/Python/3.13.py", line 359, in <module>
    foo()
  File "E:/Python/3.13.py", line 356, in foo
    a += 1
UnboundLocalError: local variable 'a' referenced before assignment

添加global即可

例2:

li = ['a', 'b']
def foo():
    li.append('c')
    print(li)
print(foo())
print(li)

运行结果:

['a', 'b', 'c']
None
['a', 'b', 'c']

  • 在函数中不使用global声明全局变量时不能修改全局变量的本质是不能修改全局变量的指向,既不能将全局变量指向新的数据。
  • 对于不可变类型的全局变量来说,因其指向的数据不能修改,所以不使用global是无法修改全局变量。
  • 对于可变类型的全局变量来说,因其指向的数据可以修改,所以不使用global时也可以修改全局变量

python 函数高级话题

递归函数

递归是颇为高级的话题,它在Python中相对少见。然而,它是一项应该了解的有用的技术,因为它允许程序遍历拥有任意的、不可预知的形状的结构。递归甚至是简单循环和迭代的替换,尽管它不一定是最简单的或最高效的一种。

![img](file:///C:\Users\ADMINI1\AppData\Local\Temp[5UQ[BL(6BS2JV6W}N6[%S.png)https://zhidao.baidu.com/question/550718079.html

用递归求和

让我们来看一些例子。

要对一个数字列表(或者其他序列)求和,我们可以使用内置的sum函数,或者自己编写一个更加定制化的版本。这里是用递归编写的一个定制求和函数的示例:

def mysum(L):
    # print(L)
    if not L:
        return 0
    else:
        return L[0] + mysum(L[1:]) # 调用自身
print(mysum([1, 2, 3, 4, 5, 6]))

第一次:L=[1,2,3,4,5,6]

L[0]=1,|1=L[1:]=[2,3,4,5,6]

第二次 :L=|1=[2,3,4,5,6]

L[0]=2 L[1:]=[3,4,5,6]

以此类推

在每一层,这个函数都递归地调用自己来计算列表剩余的值的和,这个和随后加到前面的一项中。当列表变为空的时候,递归循环结束并返回0。当像这样使用递归的时候,对函数调用的每一个打开的层级,在运行时调用堆栈上都有自己的一个函数本地作用域的副本,也就是说,这意味着L在每个层级都是不同的。如上注释部分的print(L),可以运行查看结果。

正如你所看到的,在每个递归层级上,要加和的列表变得越来越小,直到它变为空——递归循环结束。加和随着递归调用的展开而计算出来。
斐波那契

def fibonacci(n):
    if n==1:
        return 1
    if n==2:
        return 1
    else:
        return fibonacci(n-1) + fibonacci(n-2)
print(fibonacci(10)/fibonacci(9))

匿名函数:lambda

lambda表达式

lambda的一般形式是关键字lambda,之后是一个或多个参数(与一个def头部内用括号括起来的参数列表极其相似),紧跟的是一个冒号,之后是一个表达式,即:

lambda para1, para2, ..., paraN : expression using paras

由lambda表达式所返回的函数对象与由def创建并赋值后的函数对象工作起来是完全一样的,但是lambda有一些不同之处让其在扮演特定角色时很有用。

  • lambda是一个表达式,而不是一个语句。因为这一点,lambda能够出现在Python语法不允许def出现的地方——例如,在一个列表常量中或者函数调用的参数中。此外,作为一个表达式,lambda返回了一个值(一个新的函数),可以选择性地赋值给一个变量名。相反,def语句总是得在头部将一个新的函数赋值给一个变量名,而不是将这个函数作为结果返回。
  • lambda的主体是一个单个的表达式,而不是一个代码块。这个lambda的主体简单得就好像放在def主体的return语句中的代码一样。简单地将结果写成一个顺畅的表达式,而不是明确的返回。因为它仅限于表达式,lambda通常要比def功能要小:你仅能够在lambda主体中封装有限的逻辑进去,连if这样的语句都不能够使用。这是有意设计的——它限制了程序的嵌套:lambda是一个为编写简单的函数而设计的,而def用来处理更大的任务。

除了这些差别,def和lambda都能够做同样种类的工作。例如:

def sumOf3nums(x, y, z):
    return x + y + z
print(sumOf3nums(1, 2, 3))

使用lambda表达式达到相同的效果,通过明确地将结果赋值给一个变量名,之后就能够通过这个变量名调用这个函数。

sumOf3nums = lambda x, y, z:x + y + z
print(sumOf3nums(1, 2, 3))

这里的sumOf3nums被赋值给一个lambda表达式创建的函数对象。这也就是def所完成的任务,只不过def的赋值是自动进行的。

所以参数也能够在lambda参数中使用,就像在def中使用一样。

f = (lambda a="Tom ", b="loves", c="python": a + b + c)
print(f())
print(f('LiLei '))
print(f('Lucy ', 'Likes', 'to travel.'))

高阶函数

高阶函数:把一个函数名,以实参的形式,传给这个函数的形参,这个函数就称为高阶函数。

比如下面的形参c,对应的实参是一个函数名abs。

# 函数abs()的功能是取绝对值
def add(a, b, c):
    return c(a) + c(b)
add_value = add(-0,1,abs)
print(add_value)

最正确的高阶函数解释

满足下面两个条件之一,就可称之为高阶函数:

  • 1.把一个函数名当做一个实参,传给另外一个函数
  • 2.返回值中包含函数名(不修改函数的调用方式)

示例1:

import time
def bar():
    time.sleep(1)
    print('函数bar')

def test1(func): # 高阶函数(满足了条件1)
    start_time = time.time()
    func()
    stop_time = time.time()
    print("这个函数的运行时间是 %s" % (stop_time-start_time))
test1(bar)

示例2:

def bar(): # 高阶函数(满足了条件2)
    time.sleep(1)
    print("in the bar")
def test2(func):
    print(func)
    return func
bar=test2(bar)
bar()

Python中常见的高阶函数

(1)filter
  • 功能
    • filter的功能是过滤掉序列中不符合函数条件的元素,当序列中要删减的元素可以用某些函数描述时,就应该想起filter函数。
  • 调用
    • filter(function , sequence)
      • function可以是匿名函数或者自定义函数,它会对后面的sequence序列的每个元素判定是否符合函数条件,返回TRUE或者FALSE,从而只留下TRUE的元素;sequence可以是列表。元组或者字符串

例子:

x = [1, 2, 3, 4, 5]
y = filter(lambda x: x%2==0,x) # 找出偶数。
print(y)
print(list(y))

普通函数使用lambda

x = [1, 2, 3, 4, 5]
def is_add(n):
    return n % 2 == 1
print(list(filter(is_add, x)))

(2)map

  • 功能
    • 求一个序列或者多个序列进行函数映射后,就该想到map这个函数,它是python自带的函数,py3返回的是迭代器,同filter,需要进行列表转换
  • 调用
    • map(function,iterable1,iterble2)
      • function中的参数值不一定是一个x,也可以是x和y,甚至多个;后面的iterable表示需要参与function运算中的参数值,有几个参数值就传入几个iterble

例子:

x = [1, 2, 3, 4, 5]
y = [2, 3, 4, 5, 6]
z = map(lambda x, y: x * y + 2, x, y)
print(z)
print(list(z))

普通函数:

def func(x,y):
	return x*y+2
x=[1,2,3,4,5]
y=[2,3,4,5,6]  
print(list(map(func,x,y)))

注:map中如果传入的几个序列的长度不一,那么会依据最短的序列进行计算。

(3)reduce

  • 功能
    • 对一个序列进行压缩运算,得到一个值。但是reduce在python2的时候是内置函数,到了python3移到了function模块,所以使用之前需要fromfunctools import reduce
  • 调用
    • reduce(function, iterable[, inital])
      • 其中function必须传入两个参数,iterable可以是列表或者元组

例子:

>>> from functools import reduce
>>> y = [2, 3, 4, 5, 6]
>>> z = reduce(lambda x, y: x+y, y, 100)
>>> z
120

其计算原理:

先计算头两个元素:f[2, 3],结果为5;

再把计算结果和第三个元素计算:f[5, 4]

再把计算结果和第四个元素计算:f[9, 5]

再把计算结果和第五个元素计算:f[14, 6]

由于没有更多元素了,所以返回20

(4)apply

  • 功能
    • 是pandas中的函数,应用对象为pandas中的DataFrame或者Series,大致有两个方面的功能:一是直接对DataFrame或者Series应用函数,二是对pandas中的groupby之后的聚合对象apply函数
  • 函数
    • apply(function.axis),function表明所使用的函数,axis表明对行或者列做运算

例子:

>>> import numpy as np
>>> import pandas as pd
>>> a = np.random.randint(low=0, high=4, size=(2, 4))
>>> a
array([[3, 3, 0, 1],
       [1, 1, 0, 3]])
>>> data = pd.DataFrame(a)
>>> data
   0  1  2  3
0  3  3  0  1
1  1  1  0  3
>>> data.apply(lambda x: x*10)
    0   1  2   3
0  30  30  0  10
1  10  10  0  30

(5)zip

  • 功能

    • zip()函数用于将可迭代对象作为参数,将对象中对应的元素打包成一个个元组,然后返回由这些元组组成的对象。

      如果个个可迭代对象的元素个数不一致,则返回对象长度与最短的可迭代对象相同。

      利用*号操作符,与zip相反,进行解压

  • 调用

    • zip(iterable1, iterable2, …)

      • iterable – 一个或多个可迭代对象(字符串、列表、元组、字典)

        Python2中直接返回一个由元组组成的列表,Python3中返回的是一个对象,如果想要得到列表,可以用list()函数进行转换

例子:

>>> a = [1, 2, 3] # 此处可迭代对象为列表
>>> b = [4, 5, 6]
>>> c = [4, 5, 6, 7, 8]
>>> zipTast = zip(a, b)
>>> zipTast
<zip object at 0x000001EDED28F648> # 返回的是一个对象
>>> list(zipTast)
[(1, 4), (2, 5), (3, 6)]
>>> zipT = zip(a, b)
>>> list(zip(*zipT)) # 解压也使用list进行转换
[(1, 2, 3), (4, 5, 6)]

>>> # v1, v2, v3可是任何可迭代对象,如:子字符串、列表、元组、字典
>>> v1 = {1:11,2:22} # 此处可迭代对象为字典
>>> v2 = {3:33,4:44}
>>> v3 = {5:55,6:66}
>>> v = zip(v1, v2, v3) # 压缩
>>> list(v)
[(1, 3, 5), (2, 4, 6)]
>>> w = zip(*zip(v1, v2, v3)) # 解压
>>> list(w)
[(1, 2), (3, 4), (5, 6)]

总结

1.filter和map都是python内置的函数,可以直接调用,reduce在functools模块,apply在pandas模块

2.要过滤删减序列用filter;要对多个序列做函数运算用map;在pandas里面直接调用apply,reduce用得少。

练习题

1.利用map()函数,把使用户输入的不规范英文名字,变为首字母大写,其余小写的规范名字。输入:[hunan,YINGXIAO,COllege],输出:[Hunan,Yingxiao,College]

2.回文数是指从左向右读和从右向左读都是一样的数,例如12321,909。使用filter()挑选出1-1000里的回文数:

# 1
def formattion(seq):
    return seq[0].upper() + seq[1:].lower()

sr = ['hunna' , 'YINGXIAO' , 'COllege']
print(list(map(formattion, sr)))

# 2
def palindrome(n):
    rev_n = int(str(n)[::-1])
    if rev_n == n:
        return rev_n
print(list(filter(palindrome, range(1, 1000))))

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值