Python 基础初级
print函数输出数组
py3.x使用输出集合
list = ["a","b","c"]
print (list)
-------------------
["a","b","c"]
带引号的是同一行显示多条语句
print('hello'); print('world')
py代码块不能使用大括号 只能用缩进
if True:
print('true')
else:
print('false')
多行语句可以用斜杠( \ )
多行注释可以用 单引号 也可以用双引号
# 多引号
"""
111
1
"""
# 单引号
'''
1
1
1
'''
print输出是否换行 不换行就末尾加逗号 在py3之后就要用end=” “
x = "a"
y = "b"
print(x, end=" ")
print(y)
整型 浮点 字符串
counter = 100
miles = 100.0
name = "Runoob"
print(counter)
print(miles)
print(name)
加号是字符串连接运算符 型号是重复操作
str = "Hello World!"
print(str * 2)
print(str + "TEST")
list = ['sac', 123, 2.32, 'john', 70.2]
print list[2:] # 输出从第三个开始至列表末尾的所有元素
-------------------
Hello World!Hello World!
Hello World!TEST
[2.32, 'john', 70.2]
列表是有序的对象集合,字典是无序的对象集合
两者之间的区别在于:字典当中的元素是通过键来存取的,而不是通过偏移存储
字典用’{ }’标识,字典由索引(key)和它对应的值value组成
Python中的集合(Set)、元组(Tuple)和字典(Dictionary)是三种不同的数据结构,它们各自有不同的特点和用途:
- 集合(Set):
- 无序的集合数据类型,其中每个元素都是唯一的,没有重复的元素。
- 支持集合的数学运算,如并集、交集、差集等。
- 用大括号
{}
或者 set()
函数来创建,但空集合只能用 set()
创建,因为 {}
创建的是空字典。
- 例子:
{1, 2, 3}
- 元组(Tuple):
- 有序的集合数据类型,元素用圆括号
()
括起来。
- 元组中的元素不可修改,即一旦创建,就不能更改其内容。
- 元组可以包含不同类型的元素。
- 例子:
(1, "hello", 3.14)
- 字典(Dictionary):
- 无序的键值对集合,每个键都是唯一的。
- 键和值之间用冒号
:
分隔,多个键值对之间用逗号 ,
分隔,整个字典包括在大括号 {}
中。
- 键必须是不可变的数据类型,如字符串、数字或元组,而值可以是任何数据类型。
- 可以通过键来访问、修改或删除对应的值。
- 例子:
{"name": "Alice", "age": 25}
总结区别:
- 唯一性:集合和字典中的元素(对于集合是元素,对于字典是键)都是唯一的,而元组中的元素可以重复。
- 可变性:集合和字典是可变的,可以添加、删除元素,而元组是不可变的。
- 有序性:元组是有序的,可以索引访问;集合和字典是无序的,不能通过索引访问。
- 用途:集合用于处理集合操作,字典用于存储键值对,元组用于存储不可变的有序元素
tinydict = {'name': 'runoob','code':6734, 'dept':'sales'}
print(tinydict)
print(tinydict.keys())
print(tinydict.values())
------------------------------------
{'name': 'runoob', 'code': 6734, 'dept': 'sales'}
dict_keys(['name', 'code', 'dept'])
dict_values(['runoob', 6734, 'sales'])
算术运算符
‘‘ 两个数相乘
‘%’ 返回除法的余数 — 取模
‘**’ 幂 返回x的y次幂 a * * b为10的20次方
‘ *=’ c * * = a 等效于 c = c * * a
比较运算符
‘<>’ 不等于 类似于 !=
运算符 |
描述 |
实例 |
& |
按位与运算符:参与运算的两个值,如果两个相应位都为1,则该位的结果为1,否则为0 |
(a & b) 输出结果 12 ,二进制解释: 0000 1100 |
| |
按位或运算符:只要对应的二个二进位有一个为1时,结果位就为1。 |
(a | b) 输出结果 61 ,二进制解释: 0011 1101 |
^ |
按位异或运算符:当两对应的二进位相异时,结果为1 |
(a ^ b) 输出结果 49 ,二进制解释: 0011 0001 |
~ |
按位取反运算符:将二进制表示中的每一位取反,0 变为 1,1 变为 0。**~x** 类似于 -x-1 |
(~a ) 输出结果 -61 ,二进制解释: 1100 0011 (以补码形式表示),在一个有符号二进制数的补码形式。 |
<< |
左移动运算符:运算数的各二进位全部左移若干位,由 << 右边的数字指定了移动的位数,高位丢弃,低位补0。 |
a << 2 输出结果 240 ,二进制解释: 1111 0000 |
>> |
右移动运算符:把”>>”左边的运算数的各二进位全部右移若干位,**>>** 右边的数字指定了移动的位数 |
a >> 2 输出结果 15 ,二进制解释: 0000 1111 |
成员运算符
除了以上的一些运算符之外,Python还支持成员运算符,测试实例中包含了一系列的成员,包括字符串,列表或元组。
运算符 |
描述 |
实例 |
in |
如果在指定的序列中找到值返回 True,否则返回 False。 |
x 在 y 序列中 , 如果 x 在 y 序列中返回 True。 |
not in |
如果在指定的序列中没有找到值返回 True,否则返回 False。 |
x 不在 y 序列中 , 如果 x 不在 y 序列中返回 True。 |
a = 10
b = 20
list = [1,2,3,4,5];
if(a in list):
print("a 在列表内")
else:
print("a 不在列表内")
if(b not in list):
print("b 不在列表内")
else:
print("b 在列表内")
--------------------------
a 不在列表内
b 不在列表内
身份运算符
算符 |
描述 |
实例 |
is |
is 是判断两个标识符是不是引用自一个对象 |
x is y, 类似 id(x) == id(y) , 如果引用的是同一个对象则返回 True,否则返回 False |
is not |
is not 是判断两个标识符是不是引用自不同对象 |
x is not y , 类似 **id(a) != id(b)**。如果引用的不是同一个对象则返回结果 True,否则返回 False。 |
a1 = 20
b1 = 20
if(a1 is b1):
print("a1 与 b1 是相同的对象")
else:
print("a1 与 b1 不是相同的对象")
if(a1 is not b1):
print("a1 与 b1 不是相同的对象")
else:
print("a1 与 b1 是相同的对象")
----------------------------------
a1 与 b1 是相同的对象
a1 与 b1 是相同的对象
while循环语句 + continue + break
count = 0
while(count < 9):
print('The count is:', count)
count = count + 1
print("Good bye!")
--------------------------------
The count is: 0
The count is: 1
The count is: 2
The count is: 3
The count is: 4
The count is: 5
The count is: 6
The count is: 7
The count is: 8
Good bye!
count = 0
while(count < 9):
print('The count is:', count)
count = count + 1
print("Good bye!")
---------------------------------
The count is: 0
Good bye!
The count is: 1
Good bye!
The count is: 2
Good bye!
The count is: 3
Good bye!
The count is: 4
Good bye!
The count is: 5
Good bye!
The count is: 6
Good bye!
The count is: 7
Good bye!
The count is: 8
Good bye!
# continue 和 break 用法
i = 1
while i < 10:
i += 1
if i%2 > 0: # 非双数时跳过输出
continue
print i # 输出双数2、4、6、8、10
i = 1
while 1: # 循环条件为1必定成立
print i # 输出1~10
i += 1
if i > 10: # 当i大于10时跳出循环
break
for循环语句
for letter in 'Python':
print('当前字母 : %s' %letter)
fruits = ['banana', 'apple', 'mango']
for fruit in fruits:
print('当前水果 :', fruit)
print('Good bye!')
--------------------------------------
当前字母 : P
当前字母 : y
当前字母 : t
当前字母 : h
当前字母 : o
当前字母 : n
当前水果 : banana
当前水果 : apple
当前水果 : mango
Good bye!
循环嵌套
Python 语言允许在一个循环体里面嵌入另一个循环。
Python for 循环嵌套语法:
for iterating_var in sequence:
for iterating_var in sequence:
statements(s)
statements(s)
Python while 循环嵌套语法:
while expression:
while expression:
statement(s)
statement(s)
Python break 用法
for letter in 'python':
if letter == 'h':
break
print('当前字母 :', letter)
------------------------------
当前字母 : p
当前字母 : y
当前字母 : t
Python pass 用法
在 Python 中有时候会看到一个 def 函数:
def sample(n_samples):
pass
该处的 pass 便是占据一个位置,因为如果定义一个空函数程序会报错
当你没有想好函数的内容是可以用 pass 填充,使程序可以正常运行
-----------------------------------
在 Python3.x 的时候 pass 可以写或不写。
python2.x:
def function():
# 空函数在Python2.x版本中pass是必须的
pass
python3.x
def function():
# 在Python3.x的时候pass可以写或不写
pass
Python Number数字
Python Number 数据类型用于存储数值。
数据类型是不允许改变的,这就意味着如果改变 Number 数据类型的值,将重新分配内存空间。
以下实例在变量赋值时 Number 对象将被创建:
var1 = 1
var2 = 10
您也可以使用del语句删除一些 Number 对象引用。
del语句的语法是:
del var1[,var2[,var3[....,varN]]]]
您可以通过使用del语句删除单个或多个对象,例如:
del var
del var_a, var_b
Python 支持四种不同的数值类型:
整型(Int) - 通常被称为是整型或整数,是正或负整数,不带小数点。
长整型(long integers) - 无限大小的整数,整数最后是一个大写或小写的L。
浮点型(floating point real values) - 浮点型由整数部分与小数部分组成,浮点型也可以使用科学计数法表示(2.5e2 = 2.5 x 102 = 250)
复数(complex numbers) - 复数由实数部分和虚数部分构成,可以用a + bj,或者complex(a,b)表示, 复数的实部a和虚部b都是浮点型。
Python Number 类型转换
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 ) 将一个整数转换为一个八进制字符串
Python math 模块、cmath 模块
Python 中数学运算常用的函数基本都在 math 模块、cmath 模块中。
Python math 模块提供了许多对浮点数的数学运算函数。
Python cmath 模块包含了一些用于复数运算的函数。
cmath
模块的函数跟 math 模块函数基本一致,区别是 cmath 模块运算的是复数
math
模块运算的是数学运算。
要使用 math 或 cmath 函数必须先导入:
查看 math 查看包中的内容:
>>> import math
>>> dir(math)
['__doc__', '__file__', '__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']
>>>
下文会介绍各个函数的具体应用。
查看 cmath 查看包中的内容
>>> import cmath
>>> dir(cmath)
['__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'acos', 'acosh', 'asin', 'asinh', 'atan', 'atanh', 'cos', 'cosh', 'e', 'exp', 'inf', 'infj', 'isclose', 'isfinite', 'isinf', 'isnan', 'log', 'log10', 'nan', 'nanj', 'phase', 'pi', 'polar', 'rect', 'sin', 'sinh', 'sqrt', 'tan', 'tanh', 'tau']
>>>
Python数学函数
函数 |
返回值 ( 描述 ) |
abs(x) |
返回数字的绝对值,如abs(-10) 返回 10 |
ceil(x) |
返回数字的上入整数,如math.ceil(4.1) 返回 5 |
cmp(x, y) |
如果 x < y 返回 -1, 如果 x == y 返回 0, 如果 x > y 返回 1 |
exp(x) |
返回e的x次幂(ex),如math.exp(1) 返回2.718281828459045 |
fabs(x) |
以浮点数形式返回数字的绝对值,如math.fabs(-10) 返回10.0 |
floor(x) |
返回数字的下舍整数,如math.floor(4.9)返回 4 |
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 运算后的值。 |
[round(x ,n]) |
返回浮点数x的四舍五入值,如给出n值,则代表舍入到小数点后的位数。 |
sqrt(x) |
返回数字x的平方根 |
Python随机数函数
随机数可以用于数学,游戏,安全等领域中,还经常被嵌入到算法中,用以提高算法效率,并提高程序的安全性。
Python包含以下常用随机数函数:
Python数学常量
常量 |
描述 |
pi |
数学常量 pi(圆周率,一般以π来表示) |
e |
数学常量 e,e即自然常数(自然常数)。 |
Python 字符串
字符串是 Python 中最常用的数据类型。我们可以使用引号 ( ‘ 或 “ ) 来创建字符串。
创建字符串很简单,只要为变量分配一个值即可。例如:
var1 = 'Hello World!'
var2 = "Python Runoob"
Python 字符串格式化符号
符 号 |
描述 |
%c |
格式化字符及其ASCII码 |
%s |
格式化字符串 |
%d |
格式化整数 |
%u |
格式化无符号整型 |
%o |
格式化无符号八进制数 |
%x |
格式化无符号十六进制数 |
%X |
格式化无符号十六进制数(大写) |
%f |
格式化浮点数字,可指定小数点后的精度 |
%e |
用科学计数法格式化浮点数 |
%E |
作用同%e,用科学计数法格式化浮点数 |
%g |
%f和%e的简写 |
%G |
%F 和 %E 的简写 |
%p |
用十六进制数格式化变量的地址 |
格式化操作符辅助指令:
符号 |
功能 |
* |
定义宽度或者小数点精度 |
- |
用做左对齐 |
+ |
在正数前面显示加号( + ) |
|
在正数前面显示空格 |
# |
在八进制数前面显示零(‘0’),在十六进制前面显示’0x’或者’0X’(取决于用的是’x’还是’X’) |
0 |
显示的数字前面填充’0’而不是默认的空格 |
% |
‘%%’输出一个单一的’%’ |
(var) |
映射变量(字典参数) |
m.n. |
m 是显示的最小总宽度,n 是小数点后的位数(如果可用的话) |
Python 的字符串内建函数
字符串方法是从 Python1.6 到 2.0 慢慢加进来的 —— 它们也被加到了Jython 中。
这些方法实现了 string 模块的大部分方法,如下表所示列出了目前字符串内建支持的方法,所有的方法都包含了对 Unicode 的支持,有一些甚至是专门用于 Unicode 的。
方法 |
描述 |
string.capitalize() |
把字符串的第一个字符大写 |
string.center(width) |
返回一个原字符串居中,并使用空格填充至长度 width 的新字符串 |
string.count(str, beg=0, end=len(string)) |
返回 str 在 string 里面出现的次数,如果 beg 或者 end 指定则返回指定范围内 str 出现的次数 |
string.decode(encoding=’UTF-8’, errors=’strict’) |
以 encoding 指定的编码格式解码 string,如果出错默认报一个 ValueError 的 异 常 , 除非 errors 指 定 的 是 ‘ignore’ 或 者’replace’ |
string.encode(encoding=’UTF-8’, errors=’strict’) |
以 encoding 指定的编码格式编码 string,如果出错默认报一个ValueError 的异常,除非 errors 指定的是’ignore’或者’replace’ |
string.endswith(obj, beg=0, end=len(string)) |
检查字符串是否以 obj 结束,如果beg 或者 end 指定则检查指定的范围内是否以 obj 结束,如果是,返回 True,否则返回 False. |
string.expandtabs(tabsize=8) |
把字符串 string 中的 tab 符号转为空格,tab 符号默认的空格数是 8。 |
string.find(str, beg=0, end=len(string)) |
检测 str 是否包含在 string 中,如果 beg 和 end 指定范围,则检查是否包含在指定范围内,如果是返回开始的索引值,否则返回-1 |
string.format() |
格式化字符串 |
string.index(str, beg=0, end=len(string)) |
跟find()方法一样,只不过如果str不在 string中会报一个异常. |
string.isalnum() |
如果 string 至少有一个字符并且所有字符都是字母或数字则返回 True,否则返回 False |
string.isalpha() |
如果 string 至少有一个字符并且所有字符都是字母则返回 True,否则返回 False |
string.isdecimal() |
如果 string 只包含十进制数字则返回 True 否则返回 False. |
string.isdigit() |
如果 string 只包含数字则返回 True 否则返回 False. |
string.islower() |
如果 string 中包含至少一个区分大小写的字符,并且所有这些(区分大小写的)字符都是小写,则返回 True,否则返回 False |
string.isnumeric() |
如果 string 中只包含数字字符,则返回 True,否则返回 False |
string.isspace() |
如果 string 中只包含空格,则返回 True,否则返回 False. |
string.istitle() |
如果 string 是标题化的(见 title())则返回 True,否则返回 False |
string.isupper() |
如果 string 中包含至少一个区分大小写的字符,并且所有这些(区分大小写的)字符都是大写,则返回 True,否则返回 False |
string.join(seq) |
以 string 作为分隔符,将 seq 中所有的元素(的字符串表示)合并为一个新的字符串 |
string.ljust(width) |
返回一个原字符串左对齐,并使用空格填充至长度 width 的新字符串 |
string.lower() |
转换 string 中所有大写字符为小写. |
string.lstrip() |
截掉 string 左边的空格 |
string.maketrans(intab, outtab) |
maketrans() 方法用于创建字符映射的转换表,对于接受两个参数的最简单的调用方式,第一个参数是字符串,表示需要转换的字符,第二个参数也是字符串表示转换的目标。 |
max(str) |
返回字符串 str 中最大的字母。 |
min(str) |
返回字符串 str 中最小的字母。 |
string.partition(str) |
有点像 find()和 split()的结合体,从 str 出现的第一个位置起,把 字 符 串 string 分 成 一 个 3 元 素 的 元 组 (string_pre_str,str,string_post_str),如果 string 中不包含str 则 string_pre_str == string. |
string.replace(str1, str2, num=string.count(str1)) |
把 string 中的 str1 替换成 str2,如果 num 指定,则替换不超过 num 次. |
string.rfind(str, beg=0,end=len(string) ) |
类似于 find() 函数,返回字符串最后一次出现的位置,如果没有匹配项则返回 -1。 |
string.rindex( str, beg=0,end=len(string)) |
类似于 index(),不过是返回最后一个匹配到的子字符串的索引号。 |
string.rjust(width) |
返回一个原字符串右对齐,并使用空格填充至长度 width 的新字符串 |
string.rpartition(str) |
类似于 partition()函数,不过是从右边开始查找 |
string.rstrip() |
删除 string 字符串末尾的空格. |
string.split(str=””, num=string.count(str)) |
以 str 为分隔符切片 string,如果 num 有指定值,则仅分隔 num+1 个子字符串 |
[string.splitlines(keepends]) |
按照行(‘\r’, ‘\r\n’, ‘\n’)分隔,返回一个包含各行作为元素的列表,如果参数 keepends 为 False,不包含换行符,如果为 True,则保留换行符。 |
string.startswith(obj, beg=0,end=len(string)) |
检查字符串是否是以 obj 开头,是则返回 True,否则返回 False。如果beg 和 end 指定值,则在指定范围内检查. |
[string.strip(obj]) |
在 string 上执行 lstrip()和 rstrip() |
string.swapcase() |
翻转 string 中的大小写 |
string.title() |
返回”标题化”的 string,就是说所有单词都是以大写开始,其余字母均为小写(见 istitle()) |
string.translate(str, del=””) |
根据 str 给出的表(包含 256 个字符)转换 string 的字符,要过滤掉的字符放到 del 参数中 |
string.upper() |
转换 string 中的小写字母为大写 |
string.zfill(width) |
返回长度为 width 的字符串,原字符串 string 右对齐,前面填充0 |
访问列表中的值 && 追加列表【append】&& 删除列表元素【del】
print("----------------")
list1 = ['physics', 'chemistry', 1997, 2000]
print(list1)
print(list1[0])
list1.append('Google')
print(list1)
del list1[4] #删除了Google
print(list1)
-------------------------------
['physics', 'chemistry', 1997, 2000]
physics
['physics', 'chemistry', 1997, 2000, 'Google']
['physics', 'chemistry', 1997, 2000] #删除了Google
Python列表脚本操作符
列表对 + 和 * 的操作符与字符串相似。+ 号用于组合列表,* 号用于重复列表。
Python 表达式 |
结果 |
描述 |
len([1, 2, 3]) |
3 |
长度 |
[1, 2, 3] + [4, 5, 6] |
[1, 2, 3, 4, 5, 6] |
组合 |
[‘Hi!’] * 4 |
[‘Hi!’, ‘Hi!’, ‘Hi!’, ‘Hi!’] |
重复 |
3 in [1, 2, 3] |
True |
元素是否存在于列表中 |
for x in [1, 2, 3]: print x, |
1 2 3 |
迭代 |
记得负号是倒数的噢
>>>L = ['Google', 'Runoob', 'Taobao']
>>> L[2]
'Taobao'
>>> L[-2]
'Runoob'
>>> L[1:]
['Runoob', 'Taobao']
>>>
Python 表达式 |
结果 |
描述 |
L[2] |
‘Taobao’ |
读取列表中第三个元素 |
L[-2] |
‘Runoob’ |
读取列表中倒数第二个元素 |
L[1:] |
[‘Runoob’, ‘Taobao’] |
从第二个元素开始截取列表 |
Python列表函数&方法
Python日期和时间
Python 程序能用很多方式处理日期和时间,转换日期格式是一个常见的功能。
Python 提供了一个 time 和 calendar 模块可以用于格式化日期和时间。
时间间隔是以秒为单位的浮点小数。
每个时间戳都以自从1970年1月1日午夜(历元)经过了多长时间来表示。
Python 的 time 模块下有很多函数可以转换常见日期格式。
如函数time.time()
用于获取当前时间戳, 如下实例:
#!/usr/bin/python
# -*- coding: UTF-8 -*-
import time # 引入time模块
ticks = time.time()
print "当前时间戳为:", ticks
--------------------------
当前时间戳为: 1459994552.51
获取某月日历
time.time( ) 返回当前时间的时间戳(1970纪元后经过的浮点秒数)
time.sleep(secs) 推迟调用线程的运行,secs指秒数。
time.localtime([secs]) 接收时间戳(1970纪元后经过的浮点秒数)并返回当地时间下的时间元组t(t.tm_isdst可取0或1,取决于当地当时是不是夏令时)。
import calendar
cal = calendar.month(2025, 2)
print("以下输出是 2025 年 2 月的日历:")
print(cal)
------------------------------------
以下输出是 2025 年 2 月的日历:
February 2025
Mo Tu We Th Fr Sa Su
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28
Python函数
你可以定义一个由自己想要功能的函数,以下是简单的规则:
- 函数代码块以 def 关键词开头,后接函数标识符名称和圆括号**()**。
- 任何传入参数和自变量必须放在圆括号中间。圆括号之间可以用于定义参数。
- 函数的第一行语句可以选择性地使用文档字符串—用于存放函数说明。
- 函数内容以冒号起始,并且缩进。
- return [表达式] 结束函数,选择性地返回一个值给调用方。不带表达式的return相当于返回 None。
def functionname( parameters ):
"函数_文档字符串"
function_suite
return [expression]
默认情况下,参数值和参数名称是按函数声明中定义的顺序匹配起来的。
def readme(str):
print(str)
return
readme("Hello World!")
readme("Runoob")
----------------
Hello World!
Runoob
不定长参数
你可能需要一个函数能处理比当初声明时更多的参数。这些参数叫做不定长参数,和上述2种参数不同,声明时不会命名。基本语法如下:
def functionname([formal_args,] *var_args_tuple ):
"函数_文档字符串"
function_suite
return [expression]
加了星号(*)的变量名会存放所有未命名的变量参数。不定长参数实例如下:
#!/usr/bin/python
# -*- coding: UTF-8 -*-
# 可写函数说明
def printinfo( arg1, *vartuple ):
"打印任何传入的参数"
print "输出: "
print arg1
for var in vartuple:
print var
return
# 调用printinfo 函数
printinfo( 10 )
printinfo( 70, 60, 50 )
------------------------------
输出:
10
输出:
70
60
50
匿名函数
python 使用 lambda 来创建匿名函数。
- lambda只是一个表达式,函数体比def简单很多。
- lambda的主体是一个表达式,而不是一个代码块。仅仅能在lambda表达式中封装有限的逻辑进去。
- lambda函数拥有自己的命名空间,且不能访问自有参数列表之外或全局命名空间里的参数。
- 虽然lambda函数看起来只能写一行,却不等同于C或C++的内联函数,后者的目的是调用小函数时不占用栈内存从而增加运行效率。
lambda函数的语法只包含一个语句,如下:
lambda [arg1 [,arg2,.....argn]]:expressio
实例如下:
#!/usr/bin/python
# -*- coding: UTF-8 -*-
# 可写函数说明
sum = lambda arg1, arg2: arg1 + arg2
# 调用sum函数
print "相加后的值为 : ", sum( 10, 20 )
print "相加后的值为 : ", sum( 20, 20 )
---------------------------------------
相加后的值为 : 30
相加后的值为 : 40
Python 中的 lambda
表达式是一种匿名函数,即没有名字的函数。lambda
表达式通常用于需要短小精悍函数的场景,比如排序时的键函数,或者作为高阶函数的参数。
lambda
表达式的语法如下:
lambda arguments: expression
这里的关键点如下:
lambda
是一个关键字,用于定义匿名函数。
arguments
是函数的参数,可以有多个,用逗号分隔。
expression
是一个表达式,其结果将作为函数的返回值。
以下是一些 lambda
表达式的使用示例:
示例 1:定义一个简单的加法函数
add = lambda x, y: x + y
print(add(5, 3)) # 输出 8
示例 2:列表排序
使用 lambda
表达式来按照列表中元素的某个属性进行排序:
# 假设有一个包含字典的列表
list_of_dicts = [{'name': 'Alice', 'age': 25}, {'name': 'Bob', 'age': 20}, {'name': 'Charlie', 'age': 30}]
# 按照年龄排序
sorted_list = sorted(list_of_dicts, key=lambda x: x['age'])
print(sorted_list) # 输出 [{'name': 'Bob', 'age': 20}, {'name': 'Alice', 'age': 25}, {'name': 'Charlie', 'age': 30}]
示例 3:高阶函数中的使用
lambda
表达式常用于 map
, filter
, reduce
等高阶函数:
# 使用 map 函数将列表中的每个元素乘以2
numbers = [1, 2, 3, 4, 5]
doubled = map(lambda x: x * 2, numbers)
print(list(doubled)) # 输出 [2, 4, 6, 8, 10]
# 使用 filter 函数过滤出列表中的偶数
even_numbers = filter(lambda x: x % 2 == 0, numbers)
print(list(even_numbers)) # 输出 [2, 4]
需要注意的是,虽然 lambda
表达式非常方便,但它们通常只用于简单的函数。如果函数逻辑较为复杂,最好还是使用常规的 def
语句来定义函数,这样可以提高代码的可读性和可维护性。
return 语句
return语句[表达式]退出函数,选择性地向调用方返回一个表达式。不带参数值的return语句返回None。之前的例子都没有示范如何返回数值,下例便告诉你怎么做:
#!/usr/bin/python
# -*- coding: UTF-8 -*-
# 可写函数说明
def sum( arg1, arg2 ):
# 返回2个参数的和."
total = arg1 + arg2
print "函数内 : ", total
return total
# 调用sum函数
total = sum( 10, 20 )
全局变量和局部变量
定义在函数内部的变量拥有一个局部作用域,定义在函数外的拥有全局作用域。
局部变量只能在其被声明的函数内部访问,而全局变量可以在整个程序范围内访问。调用函数时,所有在函数内声明的变量名称都将被加入到作用域中。如下实例:
#!/usr/bin/python
# -*- coding: UTF-8 -*-
total = 0 # 这是一个全局变量
# 可写函数说明
def sum( arg1, arg2 ):
#返回2个参数的和."
total = arg1 + arg2 # total在这里是局部变量.
print "函数内是局部变量 : ", total
return total
#调用sum函数
sum( 10, 20 )
print "函数外是全局变量 : ", total
------------------------------------------
函数内是局部变量 : 30
函数外是全局变量 : 0
from…import 语句
Python 的 from 语句让你从模块中导入一个指定的部分到当前命名空间中。语法如下:
from modname import name1[, name2[, ... nameN]]
例如,要导入模块 fib 的 fibonacci 函数,使用如下语句:
from fib import fibonacci
这个声明不会把整个 fib 模块导入到当前的命名空间中,它只会将 fib 里的 fibonacci 单个引入到执行这个声明的模块的全局符号表。
from…import* 语句
把一个模块的所有内容全都导入到当前的命名空间也是可行的,只需使用如下声明:
from modname import *
这提供了一个简单的方法来导入一个模块中的所有项目。然而这种声明不该被过多地使用。
例如我们想一次性引入 math 模块中所有的东西,语句如下:
from math import *
globals() 和 locals() 函数
根据调用地方的不同,globals() 和 locals() 函数可被用来返回全局和局部命名空间里的名字。
如果在函数内部调用 locals(),返回的是所有能在该函数里访问的命名。
如果在函数内部调用 globals(),返回的是所有在该函数里能访问的全局名字。
两个函数的返回类型都是字典。所以名字们能用 keys() 函数摘取。
读取键盘输入
Python提供了两个内置函数从标准输入读入一行文本,默认的标准输入是键盘。如下:
input函数
input([prompt])
函数从标准输入读取一个行,并返回一个字符串(去掉结尾的换行符)
请输入:23
你输入的内容是: 23
打开和关闭文件
您已经可以向标准输入和输出进行读写。现在,来看看怎么读写实际的数据文件。
Python 提供了必要的函数和方法进行默认情况下的文件基本操作。你可以用 file 对象做大部分的文件操作
open 函数
你必须先用Python内置的open()函数打开一个文件,创建一个file对象,相关的方法才可以调用它进行读写。
语法:
file object = open(file_name [, access_mode][, buffering])
各个参数的细节如下:
- file_name:file_name变量是一个包含了你要访问的文件名称的字符串值。
- access_mode:access_mode决定了打开文件的模式:只读,写入,追加等。所有可取值见如下的完全列表。这个参数是非强制的,默认文件访问模式为只读(r)。
- buffering:如果buffering的值被设为0,就不会有寄存。如果buffering的值取1,访问文件时会寄存行。如果将buffering的值设为大于1的整数,表明了这就是的寄存区的缓冲大小。如果取负值,寄存区的缓冲大小则为系统默认。
不同模式打开文件的完全列表:
模式 |
描述 |
t |
文本模式 (默认)。 |
x |
写模式,新建一个文件,如果该文件已存在则会报错。 |
b |
二进制模式。 |
+ |
打开一个文件进行更新(可读可写)。 |
U |
通用换行模式(不推荐)。 |
r |
以只读方式打开文件。文件的指针将会放在文件的开头。这是默认模式。 |
rb |
以二进制格式打开一个文件用于只读。文件指针将会放在文件的开头。这是默认模式。一般用于非文本文件如图片等。 |
r+ |
打开一个文件用于读写。文件指针将会放在文件的开头。 |
rb+ |
以二进制格式打开一个文件用于读写。文件指针将会放在文件的开头。一般用于非文本文件如图片等。 |
w |
打开一个文件只用于写入。如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除。如果该文件不存在,创建新文件。 |
wb |
以二进制格式打开一个文件只用于写入。如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除。如果该文件不存在,创建新文件。一般用于非文本文件如图片等。 |
w+ |
打开一个文件用于读写。如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除。如果该文件不存在,创建新文件。 |
wb+ |
以二进制格式打开一个文件用于读写。如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除。如果该文件不存在,创建新文件。一般用于非文本文件如图片等。 |
a |
打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。也就是说,新的内容将会被写入到已有内容之后。如果该文件不存在,创建新文件进行写入。 |
ab |
以二进制格式打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。也就是说,新的内容将会被写入到已有内容之后。如果该文件不存在,创建新文件进行写入。 |
a+ |
打开一个文件用于读写。如果该文件已存在,文件指针将会放在文件的结尾。文件打开时会是追加模式。如果该文件不存在,创建新文件用于读写。 |
ab+ |
以二进制格式打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。如果该文件不存在,创建新文件用于读写 |
模式 |
r |
r+ |
w |
w+ |
a |
a+ |
读 |
+ |
+ |
|
+ |
|
+ |
写 |
|
+ |
+ |
+ |
+ |
+ |
创建 |
|
|
+ |
+ |
+ |
+ |
覆盖 |
|
|
+ |
+ |
|
|
指针在开始 |
+ |
+ |
+ |
+ |
|
|
指针在结尾 |
|
|
|
|
+ |
+ |
File对象的属性
一个文件被打开后,你有一个file对象,你可以得到有关该文件的各种信息。
以下是和file对象相关的所有属性的列表:
属性 |
描述 |
file.closed |
返回true如果文件已被关闭,否则返回false。 |
file.mode |
返回被打开文件的访问模式。 |
file.name |
返回文件的名称。 |
file.softspace |
如果用print输出后,必须跟一个空格符,则返回false。否则返回true。 |
以上实例输出结果:
文件名: foo.txt
是否已关闭 : False
访问模式 : w
末尾是否强制加空格 : 0
close()方法
File 对象的 close()方法刷新缓冲区里任何还没写入的信息,并关闭该文件,这之后便不能再进行写入。
当一个文件对象的引用被重新指定给另一个文件时,Python 会关闭之前的文件。用 close()方法关闭文件是一个很好的习惯。
语法:
fileObject.close()
例子:
#!/usr/bin/python
# -*- coding: UTF-8 -*-
# 打开一个文件
fo = open("foo.txt", "w")
print "文件名: ", fo.name
# 关闭打开的文件
fo.close()
以上实例输出结果:
文件名: foo.txt
write()方法
write()方法可将任何字符串写入一个打开的文件。需要重点注意的是,Python字符串可以是二进制数据,而不是仅仅是文字。
write()方法不会在字符串的结尾添加换行符(‘\n’):
语法:
fileObject.write(string)
在这里,被传递的参数是要写入到已打开文件的内容。
例子:
#!/usr/bin/python
# -*- coding: UTF-8 -*-
# 打开一个文件
fo = open("foo.txt", "w")
fo.write( "www.runoob.com!\nVery good site!\n")
# 关闭打开的文件
fo.close()
read()方法
read()方法从一个打开的文件中读取一个字符串。需要重点注意的是,Python字符串可以是二进制数据,而不是仅仅是文字。
语法:
fileObject.read([count])
在这里,被传递的参数是要从已打开文件中读取的字节计数。该方法从文件的开头开始读入,如果没有传入count,它会尝试尽可能多地读取更多的内容,很可能是直到文件的末尾。
例子:
这里我们用到以上创建的 foo.txt 文件。
实例:
\#!/usr/bin/python
\# -*- coding: UTF-8 -*-
\# 打开一个文件
fo = open("foo.txt", "r+")
str = fo.read(10)
**print** "读取的字符串是 : ", str
\# 关闭打开的文件
fo.close()
---------------------
读取的字符串是 : www.runoob
重命名和删除文件
Python的os模块提供了帮你执行文件处理操作的方法,比如重命名和删除文件。
要使用这个模块,你必须先导入它,然后才可以调用相关的各种功能。
rename() 方法
rename() 方法需要两个参数,当前的文件名和新文件名。
语法:
os.rename(current_file_name, new_file_name)
例子:
下例将重命名一个已经存在的文件test1.txt。
#!/usr/bin/python
# -*- coding: UTF-8 -*-
import os
# 重命名文件test1.txt到test2.txt。
os.rename( "test1.txt", "test2.txt" )
remove()方法
你可以用remove()方法删除文件,需要提供要删除的文件名作为参数。
语法:
os.remove(file_name)
例子:
下例将删除一个已经存在的文件test2.txt。
#!/usr/bin/python
# -*- coding: UTF-8 -*-
import os
# 删除一个已经存在的文件test2.txt
os.remove("test2.txt")
mkdir()方法
可以使用os模块的mkdir()方法在当前目录下创建新的目录们。你需要提供一个包含了要创建的目录名称的参数。
语法:
os.mkdir("newdir")
例子:
下例将在当前目录下创建一个新目录test。
#!/usr/bin/python
# -*- coding: UTF-8 -*-
import os
# 创建目录test
os.mkdir("test")
chdir()方法
可以用chdir()方法来改变当前的目录。chdir()方法需要的一个参数是你想设成当前目录的目录名称。
语法:
os.chdir("newdir")
例子:
下例将进入”/home/newdir”目录。
#!/usr/bin/python
# -*- coding: UTF-8 -*-
import os
# 将当前目录改为"/home/newdir"
os.chdir("/home/newdir")
getcwd() 方法
getcwd()方法显示当前的工作目录。
语法:
os.getcwd()
例子:
下例给出当前目录:
#!/usr/bin/python
# -*- coding: UTF-8 -*-
import os
# 给出当前的目录
print os.getcwd()
rmdir()方法
rmdir()方法删除目录,目录名称以参数传递。
在删除这个目录之前,它的所有内容应该先被清除。
语法:
os.rmdir('dirname')
例子:
以下是删除” /tmp/test”目录的例子。目录的完全合规的名称必须被给出,否则会在当前目录下搜索该目录。
#!/usr/bin/python
# -*- coding: UTF-8 -*-
import os
# 删除”/tmp/test”目录
os.rmdir( "/tmp/test" )
Python File(文件) 方法
open() 方法
Python 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: 设置自定义开启器,开启器的返回值必须是一个打开的文件描述符。
file 对象
file 对象使用 open 函数来创建,下表列出了 file 对象常用的函数:
异常处理
捕捉异常可以使用try/except语句。
try/except语句用来检测try语句块中的错误,从而让except语句捕获异常信息并处理。
如果你不想在异常发生时结束你的程序,只需在try里捕获它。
语法:
以下为简单的try….except…else的语法:
try:
<语句> #运行别的代码
except <名字>:
<语句> #如果在try部份引发了'name'异常
except <名字>,<数据>:
<语句> #如果引发了'name'异常,获得附加的数据
else:
<语句> #如果没有异常发生
try的工作原理是,当开始一个try语句后,python就在当前程序的上下文中作标记,这样当异常出现时就可以回到这里,try子句先执行,接下来会发生什么依赖于执行时是否出现异常。
- 如果当try后的语句执行时发生异常,python就跳回到try并执行第一个匹配该异常的except子句,异常处理完毕,控制流就通过整个try语句(除非在处理异常时又引发新的异常)。
- 如果在try后的语句里发生了异常,却没有匹配的except子句,异常将被递交到上层的try,或者到程序的最上层(这样将结束程序,并打印默认的出错信息)。
- 如果在try子句执行时没有发生异常,python将执行else语句后的语句(如果有else的话),然后控制流通过整个try语句。
#!/usr/bin/python
# -*- coding: UTF-8 -*-
try:
fh = open("testfile", "w")
fh.write("这是一个测试文件,用于测试异常!!")
except IOError:
print "Error: 没有找到文件或读取文件失败"
else:
print "内容写入文件成功"
fh.close()
使用except而不带任何异常类型
try:
# 正常的操作
......................
except:
# 发生异常,执行这块代码
......................
else:
# 如果没有异常执行这块代码
以上方式try-except
语句捕获所有发生的异常。但这不是一个很好的方式,我们不能通过该程序识别出具体的异常信息。因为它捕获所有的异常。
使用except而带多种异常类型
你也可以使用相同的except语句来处理多个异常信息,如下所示:
try:
# 正常的操作
......................
except(Exception1[, Exception2[,...ExceptionN]]):
# 发生以上多个异常中的一个,执行这块代码
......................
else:
# 如果没有异常执行这块代码
try-finally 语句
try-finally 语句无论是否发生异常都将执行最后的代码。
try:
<语句>
finally:
<语句> #退出try时总会执行
raise
---------------------------
try:
fh = open("testfile", "w")
fh.write("这是一个测试文件,用于测试异常!!")
finally:
print "Error: 没有找到文件或读取文件失败"
同样的例子也可以写成如下方式
#!/usr/bin/python
# -*- coding: UTF-8 -*-
try:
fh = open("testfile", "w")
try:
fh.write("这是一个测试文件,用于测试异常!!")
finally:
print "关闭文件"
fh.close()
except IOError:
print "Error: 没有找到文件或读取文件失败"
当在try块中抛出一个异常,立即执行finally块代码。finally块中的所有语句执行后,异常被再次触发,并执行except块代码。参数的内容不同于异常。
触发异常
实例
一个异常可以是一个字符串,类或对象。 Python的内核提供的异常,大多数都是实例化的类,这是一个类的实例的参数。
定义一个异常非常简单,如下所示:
实例
def functionName( level ):
if level < 1:
raise Exception("Invalid level!", level)
\# 触发异常后,后面的代码就不会再执行
为了能够捕获异常,”except”语句必须有用相同的异常来抛出类对象或者字符串。例如我们捕获以上异常,”except”语句如下所示:
# 触发异常后,后面的代码就不会再执行 触发异常后,后面的代码就不会再执行
try:
正常逻辑
except Exception,err:
触发自定义异常
else:
其余代码
----------------------
#!/usr/bin/python
# -*- coding: UTF-8 -*-
# 定义函数
def mye( level ):
if level < 1:
raise Exception,"Invalid level!"
# 触发异常后,后面的代码就不会再执行
try:
mye(0) # 触发异常
except Exception,err:
print 1,err
else:
print 2
----------------------
$ python test.py
1 Invalid level!
用户自定义异常
通过创建一个新的异常类,程序可以命名它们自己的异常。异常应该是典型的继承自Exception类,通过直接或间接的方式。以下为与RuntimeError相关的实例,实例中创建了一个类,基类为RuntimeError,用于在异常触发时输出更多的信息。在try语句块中,用户自定义的异常后执行except块语句,变量 e 是用于创建Networkerror类的实例。
class Networkerror(RuntimeError):
def __init__(self, arg):
self.args = arg
在你定义以上类后,你可以触发该异常,如下所示:
try:
raise Networkerror("Bad hostname")
except Networkerror,e:
print e.args
Python OS 文件/目录方法
序号 |
方法及描述 |
1 |
os.access(path, mode) 检验权限模式 |
2 |
os.chdir(path) 改变当前工作目录 |
3 |
os.chflags(path, flags) 设置路径的标记为数字标记。 |
4 |
os.chmod(path, mode) 更改权限 |
5 |
os.chown(path, uid, gid) 更改文件所有者 |
6 |
os.chroot(path) 改变当前进程的根目录 |
7 |
os.close(fd) 关闭文件描述符 fd |
8 |
os.closerange(fd_low, fd_high) 关闭所有文件描述符,从 fd_low (包含) 到 fd_high (不包含), 错误会忽略 |
9 |
os.dup(fd) 复制文件描述符 fd |
10 |
os.dup2(fd, fd2) 将一个文件描述符 fd 复制到另一个 fd2 |
11 |
os.fchdir(fd) 通过文件描述符改变当前工作目录 |
12 |
os.fchmod(fd, mode) 改变一个文件的访问权限,该文件由参数fd指定,参数mode是Unix下的文件访问权限。 |
13 |
os.fchown(fd, uid, gid) 修改一个文件的所有权,这个函数修改一个文件的用户ID和用户组ID,该文件由文件描述符fd指定。 |
14 |
os.fdatasync(fd) 强制将文件写入磁盘,该文件由文件描述符fd指定,但是不强制更新文件的状态信息。 |
15 |
[os.fdopen(fd, mode[, bufsize]]) 通过文件描述符 fd 创建一个文件对象,并返回这个文件对象 |
16 |
os.fpathconf(fd, name) 返回一个打开的文件的系统配置信息。name为检索的系统配置的值,它也许是一个定义系统值的字符串,这些名字在很多标准中指定(POSIX.1, Unix 95, Unix 98, 和其它)。 |
17 |
os.fstat(fd) 返回文件描述符fd的状态,像stat()。 |
18 |
os.fstatvfs(fd) 返回包含文件描述符fd的文件的文件系统的信息,像 statvfs() |
19 |
os.fsync(fd) 强制将文件描述符为fd的文件写入硬盘。 |
20 |
os.ftruncate(fd, length) 裁剪文件描述符fd对应的文件, 所以它最大不能超过文件大小。 |
21 |
os.getcwd() 返回当前工作目录 |
22 |
os.getcwdu() 返回一个当前工作目录的Unicode对象 |
23 |
os.isatty(fd) 如果文件描述符fd是打开的,同时与tty(-like)设备相连,则返回true, 否则False。 |
24 |
os.lchflags(path, flags) 设置路径的标记为数字标记,类似 chflags(),但是没有软链接 |
25 |
os.lchmod(path, mode) 修改连接文件权限 |
26 |
os.lchown(path, uid, gid) 更改文件所有者,类似 chown,但是不追踪链接。 |
27 |
os.link(src, dst) 创建硬链接,名为参数 dst,指向参数 src |
28 |
os.listdir(path) 返回path指定的文件夹包含的文件或文件夹的名字的列表。 |
29 |
os.lseek(fd, pos, how) 设置文件描述符 fd当前位置为pos, how方式修改: SEEK_SET 或者 0 设置从文件开始的计算的pos; SEEK_CUR或者 1 则从当前位置计算; os.SEEK_END或者2则从文件尾部开始. 在unix,Windows中有效 |
30 |
os.lstat(path) 像stat(),但是没有软链接 |
31 |
os.major(device) 从原始的设备号中提取设备major号码 (使用stat中的st_dev或者st_rdev field)。 |
32 |
os.makedev(major, minor) 以major和minor设备号组成一个原始设备号 |
33 |
[os.makedirs(path, mode]) 递归文件夹创建函数。像mkdir(), 但创建的所有intermediate-level文件夹需要包含子文件夹。 |
34 |
os.minor(device) 从原始的设备号中提取设备minor号码 (使用stat中的st_dev或者st_rdev field )。 |
35 |
[os.mkdir(path, mode]) 以数字mode的mode创建一个名为path的文件夹.默认的 mode 是 0777 (八进制)。 |
36 |
[os.mkfifo(path, mode]) 创建命名管道,mode 为数字,默认为 0666 (八进制) |
37 |
[os.mknod(filename, mode=0600, device]) 创建一个名为filename文件系统节点(文件,设备特别文件或者命名pipe)。 |
38 |
[os.open(file, flags, mode]) 打开一个文件,并且设置需要的打开选项,mode参数是可选的 |
39 |
os.openpty() 打开一个新的伪终端对。返回 pty 和 tty的文件描述符。 |
40 |
os.pathconf(path, name) 返回相关文件的系统配置信息。 |
41 |
os.pipe() 创建一个管道. 返回一对文件描述符(r, w) 分别为读和写 |
42 |
[os.popen(command, mode[, bufsize]]) 从一个 command 打开一个管道 |
43 |
os.read(fd, n) 从文件描述符 fd 中读取最多 n 个字节,返回包含读取字节的字符串,文件描述符 fd对应文件已达到结尾, 返回一个空字符串。 |
44 |
os.readlink(path) 返回软链接所指向的文件 |
45 |
os.remove(path) 删除路径为path的文件。如果path 是一个文件夹,将抛出OSError; 查看下面的rmdir()删除一个 directory。 |
46 |
os.removedirs(path) 递归删除目录。 |
47 |
os.rename(src, dst) 重命名文件或目录,从 src 到 dst |
48 |
os.renames(old, new) 递归地对目录进行更名,也可以对文件进行更名。 |
49 |
os.rmdir(path) 删除path指定的空目录,如果目录非空,则抛出一个OSError异常。 |
50 |
os.stat(path) 获取path指定的路径的信息,功能等同于C API中的stat()系统调用。 |
51 |
[os.stat_float_times(newvalue]) 决定stat_result是否以float对象显示时间戳 |
52 |
os.statvfs(path) 获取指定路径的文件系统统计信息 |
53 |
os.symlink(src, dst) 创建一个软链接 |
54 |
os.tcgetpgrp(fd) 返回与终端fd(一个由os.open()返回的打开的文件描述符)关联的进程组 |
55 |
os.tcsetpgrp(fd, pg) 设置与终端fd(一个由os.open()返回的打开的文件描述符)关联的进程组为pg。 |
56 |
[os.tempnam(dir[, prefix]]) 返回唯一的路径名用于创建临时文件。 |
57 |
os.tmpfile() 返回一个打开的模式为(w+b)的文件对象 .这文件对象没有文件夹入口,没有文件描述符,将会自动删除。 |
58 |
os.tmpnam() 为创建一个临时文件返回一个唯一的路径 |
59 |
os.ttyname(fd) 返回一个字符串,它表示与文件描述符fd 关联的终端设备。如果fd 没有与终端设备关联,则引发一个异常。 |
60 |
os.unlink(path) 删除文件 |
61 |
os.utime(path, times) 返回指定的path文件的访问和修改的时间。 |
62 |
[os.walk(top[, topdown=True[, onerror=None[, followlinks=False]]])](https://www.runoob.com/python/os-walk.html) 输出在文件夹中的文件名通过在树中游走,向上或者向下。 |
63 |
os.write(fd, str) 写入字符串到文件描述符 fd中. 返回实际写入的字符串长度 |
64 |
os.path 模块 获取文件的属性信息。 |
Python 内置函数
Python高级
创建类 [面向对象]
class Employee:
'所有员工的基本类型'
empCount = 0
def __init__(self, name, salary):
self.name = name
self.salary = salary
Employee.empCount += 1
def displayCount(self):
print ("Total Employee %d" % Employee.empCount)
def displayEmployee(self):
print ("Name : ", self.name, ", Salary: ", self.salary)
------------------------------------------
class Employee:
# 定义一个名为 Employee 的新类
'所有员工的基本类型'
# 类的文档字符串,描述类的用途
empCount = 0
# 类变量,用于跟踪类实例的数量
def __init__(self, name, salary):
# 类的构造函数,用于创建类的新实例
self.name = name
# 将参数 name 的值赋给实例变量 name
self.salary = salary
# 将参数 salary 的值赋给实例变量 salary
Employee.empCount += 1
# 每创建一个实例,类变量 empCount 的值就增加 1
def displayCount(self):
# 类的方法,用于显示当前员工数量
print("Total Employee %d" % Employee.empCount) # 打印员工总数
def displayEmployee(self):
# 类的方法,用于显示员工信息
print("Name : ", self.name, ", Salary: ", self.salary)
# 打印员工的姓名和薪水
- empCount 变量是一个类变量,它的值将在这个类的所有实例之间共享。你可以在内部类或外部类使用 Employee.empCount 访问。
- 第一种方法__init__()方法是一种特殊的方法,被称为类的构造函数或初始化方法,当创建了这个类的实例时就会调用该方法
- self 代表类的实例,self 在定义类的方法时是必须有的,虽然在调用时不必传入相应的参数。
创建实例对象
实例化类其他编程语言中一般用关键字 new,但是在 Python 中并没有这个关键字,类的实例化类似函数调用方式。以下使用类的名称 Employee 来实例化,并通过 init 方法接收参数
# 其余的都在上面的代码中
emp1 = Employee("Zara", 2000)
emp2 = Employee("Manni", 5000)
访问属性
您可以使用点号 . 来访问对象的属性。使用如下类的名称访问类变量:
emp1.displayEmployee()
emp2.displayEmployee()
print "Total Employee %d" % Employee.empCount
----------------------------------
Name : Zara , Salary: 2000
Name : Manni , Salary: 5000
Total Employee:2
你可以添加,删除,修改类的属性,如下所示:
emp1.age = 7 # 添加一个 'age' 属性
emp1.age = 8 # 修改 'age' 属性
del emp1.age # 删除 'age' 属性
你也可以使用以下函数的方式来访问属性:
- getattr(obj, name[, default]) : 访问对象的属性。
- hasattr(obj,name) : 检查是否存在一个属性。
- setattr(obj,name,value) : 设置一个属性。如果属性不存在,会创建一个新属性。
- delattr(obj, name) : 删除属性。
hasattr(emp1, ‘age’) # 如果存在 ‘age’ 属性返回 True。
getattr(emp1, ‘age’) # 返回 ‘age’ 属性的值
setattr(emp1, ‘age’, 8) # 添加属性 ‘age’ 值为 8
delattr(emp1, ‘age’) # 删除属性 ‘age’
emp1.displayEmployee()
emp2.displayEmployee()
emp1.age = 7 # 添加一个 'age' 属性
print("姓名:%s" %emp1.name, "年龄:%d" %emp1.age)
print ("总计:%d" %Employee.empCount)
-----------------------------------
Name : Zara , Salary: 2000
Name : Manni , Salary: 5000
姓名:Zara 年龄:7
总计:2
python对象销毁(垃圾回收)
Python 使用了引用计数这一简单技术来跟踪和回收垃圾。在 Python 内部记录着所有使用中的对象各有多少引用。一个内部跟踪变量,称为一个引用计数器。当对象被创建时,就创建了一个引用计数,当这个对象不再需要时, 也就是说, 这个对象的引用计数变为0 时, 它被垃圾回收。但是回收不是”立即”的, 由解释器在适当的时机,将垃圾对象占用的内存空间回收。
a = 40 # 创建对象 <40>
b = a # 增加引用, <40> 的计数
c = [b] # 增加引用. <40> 的计数
del a # 减少引用 <40> 的计数
b = 100 # 减少引用 <40> 的计数
c[0] = -1 # 减少引用 <40> 的计数
垃圾回收机制不仅针对引用计数为0的对象,同样也可以处理循环引用的情况。循环引用指的是,两个对象相互引用,但是没有其他变量引用他们。这种情况下,仅使用引用计数是不够的。Python 的垃圾收集器实际上是一个引用计数器和一个循环垃圾收集器。作为引用计数的补充, 垃圾收集器也会留心被分配的总量很大(即未通过引用计数销毁的那些)的对象。 在这种情况下, 解释器会暂停下来, 试图清理所有未引用的循环。
类的继承
面向对象的编程带来的主要好处之一是代码的重用,实现这种重用的方法之一是通过继承机制。通过继承创建的新类称为子类或派生类,被继承的类称为基类、父类或超类。
继承语法
class 派生类名(基类名)
...
在python中继承中的一些特点:
- 1、如果在子类中需要父类的构造方法就需要显式的调用父类的构造方法,或者不重写父类的构造方法。详细说明可查看: python 子类继承父类构造函数说明。
- 2、在调用基类的方法时,需要加上基类的类名前缀,且需要带上 self 参数变量。区别在于类中调用普通函数时并不需要带上 self 参数
- 3、Python 总是首先查找对应类型的方法,如果它不能在派生类中找到对应的方法,它才开始到基类中逐个查找。(先在本类中查找调用的方法,找不到才去基类中找)。
如果在继承元组中列了一个以上的类,那么它就被称作”多重继承” 。
语法:
派生类的声明,与他们的父类类似,继承的基类列表跟在类名之后
如下所示:
class SubClassName (ParentClass1[, ParentClass2, ...]):
...
方法重写
如果你的父类方法的功能不能满足你的需求,你可以在子类重写你父类的方法:
class Parent:
def myMethod(self):
print ('调用父类方法')
class Child(Parent):
def myMethod(self):
print ('调用子类方法')
c = Child()
c.myMethod()
类属性与方法
类的私有属性
“_ _” → __private_attrs
两个下划线开头,声明属性为私有,不能在外部被使用或直接访问。在类内部的方法中使用时 self.__private_attrs
类的方法
在类的内部,使用def
关键字可以为类定义一个方法,与一般函数定义不同,类方法必须包含参数self,且为第一个参数
类的私有方法
__private_method
:两个下划线开头,声明该方法为私有方法,不能在类的外部调用。
在类的内部调用self.__private_methods
#!/usr/bin/python
# -*- coding: UTF-8 -*-
class JustCounter:
__secretCount = 0 # 私有变量
publicCount = 0 # 公开变量
def count(self):
self.__secretCount += 1
self.publicCount += 1
print self.__secretCount
counter = JustCounter()
counter.count()
counter.count()
print counter.publicCount
print counter.__secretCount # 报错,实例不能访问私有变量
----------------------------------------------------
1
2
2
Traceback (most recent call last):
File "test.py", line 17, in <module>
print counter.__secretCount # 报错,实例不能访问私有变量
AttributeError: JustCounter instance has no attribute '__secretCount'
Python不允许实例化的类访问私有数据,但你可以使用 object._className__attrName( 对象名._类名__私有属性名 )访问属性,参考以下实例:
#!/usr/bin/python
# -*- coding: UTF-8 -*-
class Runoob:
__site = "www.runoob.com"
runoob = Runoob()
print runoob._Runoob__site
执行以上代码,执行结果如下:
www.runoob.com
下划线、双下划线、头尾双下划线说明:
- _ _ foo _ _: 定义的是特殊方法,一般是系统定义名字 ,类似 init() 之类的。
- _ foo: 以单下划线开头的表示的是 protected 类型的变量,即保护类型只能允许其本身与子类进行访问,不能用于 from module import *
- _ _ foo: 双下划线的表示的是私有类型(private)的变量, 只能是允许这个类本身进行访问了。
正则表达
re.match() 与 re.search()的区别
在 Python 的正则表达式模块 re
中,re.match()
和 re.search()
都用于在字符串中查找正则表达式的匹配项,但它们在查找匹配项的方式上有所不同。
re.match() 只在字符串的开始处进行匹配。如果字符串的开头与正则表达式不匹配,re.match()
将返回None
import re
# 使用 re.search()
string = "hello world"
pattern = "hello"
match = re.match(pattern, string)
if match:
print(f"匹配成功: {match.group()}")
else:
print("匹配失败")
----------------------
匹配成功: hello
re.search() 会扫描整个字符串,直到找到第一个匹配正则表达式的子串。它在整个字符串中查找匹配项,而不仅仅是在字符串的开始处。
import re
# 使用 re.search()
string = "world hello"
pattern = "hello"
search = re.search(pattern, string)
if search:
print(f"Match found: {search.group()}")
else:
print("No match found.")
-------------------------------
Match found: hello
检索和替换
Python 的 re 模块提供了re.sub用于替换字符串中的匹配项。
re.sub(pattern, repl, string, count=0, flags=0)
参数:
- pattern : 正则中的模式字符串。
- repl : 替换的字符串,也可为一个函数。
- string : 要被查找替换的原始字符串。
- count : 模式匹配后替换的最大次数,默认 0 表示替换所有的匹配。
代码分析
import re
phone = "2004-959-559 # 这是一个国外电话号码"
# 删除字符串中的 Python注释
num = re.sub(r'#.*$', "", phone)
print("电话号码是: ", num)
# 删除非数字(-)的字符串
num = re.sub(r'\D', "", phone)
print("电话号码是 : ", num)
第一部分:删除字符串中的注释
num = re.sub(r'#.*$', "", phone)
这个正则表达式 r'#.*$'
的意思是:从 #
字符开始,匹配直到字符串末尾的所有字符。因此,该行代码将删除字符串 phone
中从 #
开始到字符串末尾的所有内容。
执行结果:
复制
电话号码是: 2004-959-559
第二部分:删除非数字字符
num = re.sub(r'\D', "", phone)
这个正则表达式 r'\D'
的意思是:匹配字符串中所有的非数字字符。因此,该行代码将删除字符串 phone
中所有非数字字符。
电话号码是 : 2004959559
总结
这段代码展示了如何使用 re.sub()
函数结合正则表达式来清理和格式化字符串。第一个例子中,我们移除了字符串末尾的注释。第二个例子中,我们移除了电话号码中的所有非数字字符,从而得到一个仅包含数字的字符串。这些操作在数据清洗和预处理中非常有用。
import re
string = "hello world"
pattern = "hello"
match = re.match(pattern, string)
if match:
print(f"匹配成功: {match.group()}")
else:
print("匹配失败")
print('-----------------')
import re
phone = "2004-959-559 # 这是一个国外电话号码"
num = re.sub("#.*$","",phone)
print("电话号码是: ", num)
num2 = re.sub(r'\D',"",phone)
print("电话号码是: ", num2)
-----------------------------------------
电话号码是: 2004-959-559
电话号码是: 2004959559
★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★
print(f"匹配成功: {match.group()}")
f-string 是 Python 3.6 及以上版本中引入的一种新的字符串格式化方法,它允许你在字符串字面量中嵌入表达式,并在运行时动态地进行求值和格式化。
f
告诉 Python 这是一个格式化字符串。
{match.group()}
是一个表达式,它将被求值,并且其结果将插入到字符串中相应的位置。
findall
在字符串中找到正则表达式所匹配的所有子串,并返回一个列表,如果有多个匹配模式,则返回元组列表,如果没有找到匹配的,则返回空列表。
注意: match 和 search 是匹配一次,findall 是匹配所有。
语法格式为:
findall(string[, pos[, endpos]])
参数:
- string : 待匹配的字符串。
- pos : 可选参数,指定字符串的起始位置,默认为 0。
- endpos : 可选参数,指定字符串的结束位置,默认为字符串的长度。
查找字符串中的所有数字:
# -*- coding:UTF8 -*-
import re
# 这里您编译了一个正则表达式模式,该模式 r'\d+' 匹配一个或多个数字。
# \d 表示数字 [0-9],+ 表示一个或多个。
pattern = re.compile(r'\d+') # 查找数字
# 这里您在字符串 'runoob 123 google 456' 中查找所有匹配的数字。
# 由于字符串中有两个数字序列 '123' 和 '456',所以返回一个列表 ['123', '456']
result1 = pattern.findall('runoob 123 google 456')
# 在这里,您同样查找数字,但是指定了搜索的起始位置 0 和结束位置 10。
# 这意味着搜索只会在字符串的前10个字符内进行。在这个范围内,有两个数字序列 '88' 和 '12',所以返回列表 ['88', '12']
result2 = pattern.findall('run88oob123google456', 0, 10)
print(result1)
print(result2)
输出结果:
['123', '456']
['88', '12']
re.finditer
和 findall 类似,在字符串中找到正则表达式所匹配的所有子串,并把它们作为一个迭代器返回。
re.finditer(pattern, string, flags=0)
参数 |
描述 |
pattern |
匹配的正则表达式 |
string |
要匹配的字符串。 |
flags |
标志位,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等等。参见:正则表达式修饰符 - 可选标志 |
# -*- coding: UTF-8 -*-
import re
it = re.finditer(r"\d+","12a32bc43jf3")
for match in it:
print(match) # 打印匹配对象的描述
print("==========")
print(match.group()) # 打印匹配到的字符串
下面是具体的区别:
re.split
split
方法按照能够匹配的子串将字符串分割后返回列表
import re
# 定义一个包含单词和数字的字符串
text = "单词1单词2单词3单词4"
# 使用 re.split() 按照数字进行分割,但不保留数字
# (?:\d+) 匹配一个或多个数字,但不会捕获匹配的数字
result = re.split(r'(?:\d+)', text)
print(result)
正则表达式模式
模式字符串使用特殊的语法来表示一个正则表达式:
字母和数字表示他们自身。一个正则表达式模式中的字母和数字匹配同样的字符串。
多数字母和数字前加一个反斜杠时会拥有不同的含义。
标点符号只有被转义时才匹配自身,否则它们表示特殊的含义。
反斜杠本身需要使用反斜杠转义。
由于正则表达式通常都包含反斜杠,所以你最好使用原始字符串来表示它们。模式元素(如 r’\t’,等价于 ‘\t’)匹配相应的特殊字符。
下表列出了正则表达式模式语法中的特殊元素。如果你使用模式的同时提供了可选的标志参数,某些模式元素的含义会改变。
模式 |
描述 |
^ |
匹配字符串的开头 |
$ |
匹配字符串的末尾。 |
. |
匹配任意字符,除了换行符,当re.DOTALL标记被指定时,则可以匹配包括换行符的任意字符。 |
[…] |
用来表示一组字符,单独列出:[amk] 匹配 ‘a’,’m’或’k’ |
[^…] |
不在[]中的字符:[^abc] 匹配除了a,b,c之外的字符。 |
re* |
匹配0个或多个的表达式。 |
re+ |
匹配1个或多个的表达式。 |
re? |
匹配0个或1个由前面的正则表达式定义的片段,非贪婪方式 |
re{ n} |
精确匹配 n 个前面表达式。例如, o{2} 不能匹配 “Bob” 中的 “o”,但是能匹配 “food” 中的两个 o。 |
re{ n,} |
匹配 n 个前面表达式。例如, o{2,} 不能匹配”Bob”中的”o”,但能匹配 “foooood”中的所有 o。”o{1,}” 等价于 “o+”。”o{0,}” 则等价于 “o*”。 |
re{ n, m} |
匹配 n 到 m 次由前面的正则表达式定义的片段,贪婪方式 |
a| b |
匹配a或b |
(re) |
对正则表达式分组并记住匹配的文本 |
(?imx) |
正则表达式包含三种可选标志:i, m, 或 x 。只影响括号中的区域。 |
(?-imx) |
正则表达式关闭 i, m, 或 x 可选标志。只影响括号中的区域。 |
(?: re) |
类似 (…), 但是不表示一个组 |
(?imx: re) |
在括号中使用i, m, 或 x 可选标志 |
(?-imx: re) |
在括号中不使用i, m, 或 x 可选标志 |
(?#…) |
注释. |
(?= re) |
前向肯定界定符。如果所含正则表达式,以 … 表示,在当前位置成功匹配时成功,否则失败。但一旦所含表达式已经尝试,匹配引擎根本没有提高;模式的剩余部分还要尝试界定符的右边。 |
(?! re) |
前向否定界定符。与肯定界定符相反;当所含表达式不能在字符串当前位置匹配时成功 |
(?> re) |
匹配的独立模式,省去回溯。 |
\w |
匹配字母数字及下划线 |
\W |
匹配非字母数字及下划线 |
\s |
匹配任意空白字符,等价于 **[ \t\n\r\f]**。 |
\S |
匹配任意非空字符 |
\d |
匹配任意数字,等价于 [0-9]. |
\D |
匹配任意非数字 |
\A |
匹配字符串开始 |
\Z |
匹配字符串结束,如果是存在换行,只匹配到换行前的结束字符串。 |
\z |
匹配字符串结束 |
\G |
匹配最后匹配完成的位置。 |
\b |
匹配一个单词边界,也就是指单词和空格间的位置。例如, ‘er\b’ 可以匹配”never” 中的 ‘er’,但不能匹配 “verb” 中的 ‘er’。 |
\B |
匹配非单词边界。’er\B’ 能匹配 “verb” 中的 ‘er’,但不能匹配 “never” 中的 ‘er’。 |
\n, \t, 等. |
匹配一个换行符。匹配一个制表符。等 |
\1…\9 |
匹配第n个分组的内容。 |
\10 |
匹配第n个分组的内容,如果它经匹配。否则指的是八进制字符码的表达式 |
正则表达式实例
字符匹配
实例 |
描述 |
python |
匹配 “python”. |
字符类
实例 |
描述 |
[Pp]ython |
匹配 “Python” 或 “python” |
rub[ye] |
匹配 “ruby” 或 “rube” |
[aeiou] |
匹配中括号内的任意一个字母 |
[0-9] |
匹配任何数字。类似于 [0123456789] |
[a-z] |
匹配任何小写字母 |
[A-Z] |
匹配任何大写字母 |
[a-zA-Z0-9] |
匹配任何字母及数字 |
[^aeiou] |
除了aeiou字母以外的所有字符 |
[^0-9] |
匹配除了数字外的字符 |
特殊字符类
实例 |
描述 |
. |
匹配除 “\n” 之外的任何单个字符。要匹配包括 ‘\n’ 在内的任何字符,请使用象 ‘[.\n]’ 的模式。 |
\d |
匹配一个数字字符。等价于 [0-9]。 |
\D |
匹配一个非数字字符。等价于 [^0-9]。 |
\s |
匹配任何空白字符,包括空格、制表符、换页符等等。等价于 [ \f\n\r\t\v]。 |
\S |
匹配任何非空白字符。等价于 [^ \f\n\r\t\v]。 |
\w |
匹配包括下划线的任何单词字符。等价于’[A-Za-z0-9_]’。 |
\W |
匹配任何非单词字符。等价于 ‘[^A-Za-z0-9_]’。 |
request请求的用法
以下是使用 Python 标准库中的 urllib
模块进行 HTTP GET
和 POST
请求的简化用法。
Get请求request.get()
import requests
# 简化的 GET 请求
def simple_get(url):
response = requests.get(url)
return response.text
# 使用 GET 请求
url = 'http://httpbin.org/get'
response_text = simple_get(url)
print(response_text)
Post请求request.post()
import requests
# 简化的 POST 请求
def simple_post(url, data):
response = requests.post(url, data=data)
return response.text
# 使用 POST 请求
url = 'http://httpbin.org/post'
data = {'key1': 'value1', 'key2': 'value2'}
response_text = simple_post(url, data)
print(response_text)
SMTP发送邮件
import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.header import Header
# 设置QQ邮箱的SMTP服务器地址和端口
smtp_server = 'smtp.qq.com'
smtp_port = 465 # QQ邮箱SMTP服务器端口为465或587
# 设置发件人和收件人邮箱
sender_email = '390415032@qq.com' # 发件人邮箱
receiver_email = 'recipient@example.com' # 收件人邮箱
password = 'your_qq_email_auth_code' # QQ邮箱授权码
# 设置邮件主题和内容
subject = 'Test Email from Python'
body = 'This is a test email sent by Python.'
# 创建MIMEText对象,设置邮件内容和编码
msg = MIMEText(body, 'plain', 'utf-8')
msg['From'] = Header(sender_email, 'utf-8')
msg['To'] = Header(receiver_email, 'utf-8')
msg['Subject'] = Header(subject, 'utf-8')
# 发送邮件
try:
# 创建SMTP对象
server = smtplib.SMTP_SSL(smtp_server, smtp_port)
# 登录SMTP服务器
server.login(sender_email, password)
# 发送邮件
server.sendmail(sender_email, [receiver_email], msg.as_string())
print('Email sent successfully!')
except smtplib.SMTPException as e:
print('Error: unable to send email. ', e)
finally:
# 关闭服务器连接
server.quit()
Python 多线程
Python中使用线程有两种方式:函数或者用类来包装线程对象。
函数式:调用thread模块中的start_new_thread()函数来产生新线程。语法如下:
thread.start_new_thread ( function, args[, kwargs] )
参数说明:
- function - 线程函数。
- args - 传递给线程函数的参数,他必须是个tuple类型。
- kwargs - 可选参数。
#!/usr/bin/python
# -*- coding: UTF-8 -*-
import thread
import time
# 为线程定义一个函数
def print_time( threadName, delay):
count = 0
while count < 5:
time.sleep(delay)
count += 1
print "%s: %s" % ( threadName, time.ctime(time.time()) )
# 创建两个线程
try:
thread.start_new_thread( print_time, ("Thread-1", 2, ) )
thread.start_new_thread( print_time, ("Thread-2", 4, ) )
except:
print "Error: unable to start thread"
while 1:
pass
-------------------------------------------------------
Thread-1: Thu Jan 22 15:42:17 2009
Thread-1: Thu Jan 22 15:42:19 2009
Thread-2: Thu Jan 22 15:42:19 2009
Thread-1: Thu Jan 22 15:42:21 2009
Thread-2: Thu Jan 22 15:42:23 2009
Thread-1: Thu Jan 22 15:42:23 2009
Thread-1: Thu Jan 22 15:42:25 2009
Thread-2: Thu Jan 22 15:42:27 2009
Thread-2: Thu Jan 22 15:42:31 2009
Thread-2: Thu Jan 22 15:42:35 2009
线程的结束一般依靠线程函数的自然结束;也可以在线程函数中调用thread.exit(),他抛出SystemExit exception,达到退出线程的目的。
线程模块
Python通过两个标准库thread和threading提供对线程的支持。thread提供了低级别的、原始的线程以及一个简单的锁。
threading 模块提供的其他方法:
threading.currentThread():
返回当前的线程变量。
threading.enumerate():
返回一个包含正在运行的线程的list。正在运行指线程启动后、结束前,不包括启动前和终止后的线程。
threading.activeCount():
返回正在运行的线程数量,与len(threading.enumerate())有相同的结果。
除了使用方法外,线程模块同样提供了Thread类来处理线程,Thread类提供了以下方法:
- run(): 用以表示线程活动的方法。
- start(): 启动线程活动。
- join([time]): 等待至线程中止。这阻塞调用线程直至线程的join() 方法被调用中止-正常退出或者抛出未处理的异常-或者是可选的超时发生。
- isAlive(): 返回线程是否活动的。
- getName(): 返回线程名。
- setName(): 设置线程名。
使用Threading模块创建线程
使用Threading模块创建线程,直接从threading.Thread继承
然后重写__init__方法和run方法:
#!/usr/bin/python
# -*- coding: UTF-8 -*-
import threading
import time
exitFlag = 0
class myThread (threading.Thread): #继承父类threading.Thread
def __init__(self, threadID, name, counter):
threading.Thread.__init__(self)
self.threadID = threadID
self.name = name
self.counter = counter
def run(self): #把要执行的代码写到run函数里面 线程在创建后会直接运行run函数
print "Starting " + self.name
print_time(self.name, self.counter, 5)
print "Exiting " + self.name
def print_time(threadName, delay, counter):
while counter:
if exitFlag:
(threading.Thread).exit()
time.sleep(delay)
print "%s: %s" % (threadName, time.ctime(time.time()))
counter -= 1
# 创建新线程
thread1 = myThread(1, "Thread-1", 1)
thread2 = myThread(2, "Thread-2", 2)
# 开启线程
thread1.start()
thread2.start()
print "Exiting Main Thread"
------------------------------------------
Starting Thread-1
Starting Thread-2
Exiting Main Thread
Thread-1: Thu Mar 21 09:10:03 2013
Thread-1: Thu Mar 21 09:10:04 2013
Thread-2: Thu Mar 21 09:10:04 2013
Thread-1: Thu Mar 21 09:10:05 2013
Thread-1: Thu Mar 21 09:10:06 2013
Thread-2: Thu Mar 21 09:10:06 2013
Thread-1: Thu Mar 21 09:10:07 2013
Exiting Thread-1
Thread-2: Thu Mar 21 09:10:08 2013
Thread-2: Thu Mar 21 09:10:10 2013
Thread-2: Thu Mar 21 09:10:12 2013
Exiting Thread-2
线程同步
如果多个线程共同对某个数据修改,则可能出现不可预料的结果,为了保证数据的正确性,需要对多个线程进行同步。
使用Thread对象的Lock和Rlock可以实现简单的线程同步,这两个对象都有acquire方法
和release方法
,对于那些需要每次只允许一个线程操作的数据,可以将其操作放到acquire和release方法之间。如下:
多线程的优势在于可以同时运行多个任务(至少感觉起来是这样)。但是当线程需要共享数据时,可能存在数据不同步的问题。
考虑这样一种情况:一个列表里所有元素都是0,线程”set”从后向前把所有元素改成1,而线程”print”负责从前往后读取列表并打印。
那么,可能线程”set”开始改的时候,线程”print”便来打印列表了,输出就成了一半0一半1,这就是数据的不同步。为了避免这种情况,引入了锁的概念。
锁有两种状态——锁定和未锁定。每当一个线程比如”set”要访问共享数据时,必须先获得锁定;如果已经有别的线程比如”print”获得锁定了,那么就让线程”set”暂停,也就是同步阻塞;等到线程”print”访问完毕,释放锁以后,再让线程”set”继续。
经过这样的处理,打印列表时要么全部输出0,要么全部输出1,不会再出现一半0一半1的尴尬场面。
#!/usr/bin/python
# -*- coding: UTF-8 -*-
import threading
import time
class myThread (threading.Thread):
def __init__(self, threadID, name, counter):
threading.Thread.__init__(self)
self.threadID = threadID
self.name = name
self.counter = counter
def run(self):
print "Starting " + self.name
# 获得锁,成功获得锁定后返回True
# 可选的timeout参数不填时将一直阻塞直到获得锁定
# 否则超时后将返回False
threadLock.acquire()
print_time(self.name, self.counter, 3)
# 释放锁
threadLock.release()
def print_time(threadName, delay, counter):
while counter:
time.sleep(delay)
print "%s: %s" % (threadName, time.ctime(time.time()))
counter -= 1
threadLock = threading.Lock()
threads = []
# 创建新线程
thread1 = myThread(1, "Thread-1", 1)
thread2 = myThread(2, "Thread-2", 2)
# 开启新线程
thread1.start()
thread2.start()
# 添加线程到线程列表
threads.append(thread1)
threads.append(thread2)
# 等待所有线程完成
for t in threads:
t.join()
print "Exiting Main Thread"
线程优先级队列( Queue)
Python的Queue模块中提供了同步的、线程安全的队列类,包括FIFO(先入先出)队列Queue,LIFO(后入先出)队列LifoQueue,和优先级队列PriorityQueue。这些队列都实现了锁原语,能够在多线程中直接使用。可以使用队列来实现线程间的同步。
Queue模块中的常用方法:
- Queue.qsize() 返回队列的大小
- Queue.empty() 如果队列为空,返回True,反之False
- Queue.full() 如果队列满了,返回True,反之False
- Queue.full 与 maxsize 大小对应
- Queue.get([block[, timeout]])获取队列,timeout等待时间
- Queue.get_nowait() 相当Queue.get(False)
- Queue.put(item, block=True, timeout=None) 写入队列,timeout等待时间
- Queue.put_nowait(item) 相当 Queue.put(item, False)
- Queue.task_done() 在完成一项工作之后,Queue.task_done()函数向任务已经完成的队列发送一个信号
- Queue.join() 实际上意味着等到队列为空,再执行别的操作
#!/usr/bin/python
# -*- coding: UTF-8 -*-
import Queue
import threading
import time
exitFlag = 0
class myThread (threading.Thread):
def __init__(self, threadID, name, q):
threading.Thread.__init__(self)
self.threadID = threadID
self.name = name
self.q = q
def run(self):
print "Starting " + self.name
process_data(self.name, self.q)
print "Exiting " + self.name
def process_data(threadName, q):
while not exitFlag:
queueLock.acquire()
if not workQueue.empty():
data = q.get()
queueLock.release()
print "%s processing %s" % (threadName, data)
else:
queueLock.release()
time.sleep(1)
threadList = ["Thread-1", "Thread-2", "Thread-3"]
nameList = ["One", "Two", "Three", "Four", "Five"]
queueLock = threading.Lock()
workQueue = Queue.Queue(10)
threads = []
threadID = 1
# 创建新线程
for tName in threadList:
thread = myThread(threadID, tName, workQueue)
thread.start()
threads.append(thread)
threadID += 1
# 填充队列
queueLock.acquire()
for word in nameList:
workQueue.put(word)
queueLock.release()
# 等待队列清空
while not workQueue.empty():
pass
# 通知线程是时候退出
exitFlag = 1
# 等待所有线程完成
for t in threads:
t.join()
print "Exiting Main Thread"
---------------------------------------------------
Starting Thread-1
Starting Thread-2
Starting Thread-3
Thread-1 processing One
Thread-2 processing Two
Thread-3 processing Three
Thread-1 processing Four
Thread-2 processing Five
Exiting Thread-3
Exiting Thread-1
Exiting Thread-2
Exiting Main Thread
Python XML解析
XML 指可扩展标记语言(eXtensible Markup Language);XML 被设计用来传输和存储数据。XML 是一套定义语义标记的规则,这些标记将文档分成许多部件并对这些部件加以标识。它也是元标记语言,即定义了用于定义其他与特定领域有关的、语义的、结构化的标记语言的句法语言。常见的 XML 编程接口有 DOM 和 SAX,这两种接口处理 XML 文件的方式不同,当然使用场合也不同。
Python 有三种方法解析 XML,SAX,DOM,以及 ElementTree:
1.SAX (simple API for XML )
Python 标准库包含 SAX 解析器,SAX 用事件驱动模型,通过在解析XML的过程中触发一个个的事件并调用用户定义的回调函数来处理XML文件。
2.DOM(Document Object Model)
将 XML 数据在内存中解析成一个树,通过对树的操作来操作XML。
3.ElementTree(元素树)
ElementTree就像一个轻量级的DOM,具有方便友好的API。代码可用性好,速度快,消耗内存少。
注:因DOM需要将XML数据映射到内存中的树,一是比较慢,二是比较耗内存,而SAX流式读取XML文件,比较快,占用内存少,但需要用户实现回调函数(handler)。
XML解析一下
import xml.sax
from lxml import etree
# 确保文件路径正确
xml_file_path = 'movies.xml'
# 使用 lxml 创建一个 XML 解析器
parser = etree.XMLParser()
# 解析 XML 文件
try:
tree = etree.parse(xml_file_path, parser)
# 遍历所有元素并打印
for element in tree.iter():
print(f"Element tag: {element.tag}, text: {element.text.strip() if element.text else ''}")
except etree.XMLSyntaxError as e:
print(f"XML 解析错误: {e}")
movies.xml
<collection shelf="New Arrivals">
<movie title="Enemy Behind">
<type>War, Thriller</type>
<format>DVD</format>
<year>2003</year>
<rating>PG</rating>
<stars>10</stars>
<description>Talk about a US-Japan war</description>
</movie>
<movie title="Transformers">
<type>Anime, Science Fiction</type>
<format>DVD</format>
<year>1989</year>
<rating>R</rating>
<stars>8</stars>
<description>A schientific fiction</description>
</movie>
<movie title="Trigun">
<type>Anime, Action</type>
<format>DVD</format>
<episodes>4</episodes>
<rating>PG</rating>
<stars>10</stars>
<description>Vash the Stampede!</description>
</movie>
<movie title="Ishtar">
<type>Comedy</type>
<format>VHS</format>
<rating>PG</rating>
<stars>2</stars>
<description>Viewable boredom</description>
</movie>
</collection>