二. python函数与模块

第四章.内置函数与装饰器详解

1.内置函数补充1

注:红色圆圈:必会;  紫红色方框:熟练;   绿色:了解

callable()   判断函数是否可以被调用执行
def f1():
    pass
f1()

f2 = 123
print(callable(f1))
print(callable(f2))
###########################################################################################
# chr(), ord()  对ascii码表中的字符与十进制数互相转换
r = chr(65)   # 把ascii表中十进制数转为字母,只能单个转换。
print(r)
输出结果:A
n = ord("B")   # 把ascii表中字母转为字母十进制数,只能单个转换。
print(n)
输出结果:66
###########################################################################################
#随机验证码基础知识
import random
i = random.randrange(65,91)
c = chr(i)
print(c)
输出结果:随机输出一个大写字母
---------------------------------------------------------------------------------
import random
li = []
for i in range(6):
    temp = random.randrange(65,91)  # ASCII码表大写字母A-Z对应的十进制数范围
    c = chr(temp)         # 输出大写字母
    li.append(c)
result = ".".join(li)
print(result)
输出结果:随机输出6个大写字母
###########################################################################################
#随机验证码完整代码
import random
li = []
for i in range(6):
    r = random.randrange(0,5)  #  0<=r<5
    if r==2 or r==4:
        num = random.randrange(0,10)
        li.append(str(num))
    else:
        temp = random.randrange(65,91)
        c = chr(temp)
        li.append(c)
result = " ".join(li)
print(result)
输出结果:随机生成6个大写字母和数字的组合
###########################################################################################
# compile()  编译单行模式
# eval()     编译表达式模式
# exec()     编译整个python代码

s = "print(123)"   # 定义字符串
r = compile(s,"<string>","exec")  # 编译字符串s转换为python代码
exec(r)         # 执行编译好的代码
输出结果:123
-----------------------------------------------------------------------
s = 8*8
ret = eval("s")  # 接收字符串,并将字符串作为python表达式进行计算的功能,返回表达式运算结果
print(ret)
输出结果:64
-----------------------------------------------------------------------
a = exec("7+8+9")   # 执行python代码,接收代码或字符串
b = eval("6+7+8")   # 执行表达式,并且获取计算结果
print(a,b)
输出结果:None 21
###########################################################################################
# dir()   快速查看对象提供哪些功能
print(dir(dict))
print(dir(list))
help(dict)
help(list)
输出结果:
['__class__', '__contains__', '__delattr__', '__delitem__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__setitem__', '__sizeof__', '__str__', '__subclasshook__', 'clear', 'copy', 'fromkeys', 'get', 'items', 'keys', 'pop', 'popitem', 'setdefault', 'update', 'values']
['__add__', '__class__', '__contains__', '__delattr__', '__delitem__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__iadd__', '__imul__', '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__rmul__', '__setattr__', '__setitem__', '__sizeof__', '__str__', '__subclasshook__', 'append', 'clear', 'copy', 'count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort']
Help on class dict in module builtins:

class dict(object)
 |  dict() -> new empty dictionary
 |  dict(mapping) -> new dictionary initialized from a mapping object's
 |      (key, value) pairs
 |  dict(iterable) -> new dictionary initialized as if via:
 |      d = {}
 |      for k, v in iterable:
 |          d[k] = v
 |  dict(**kwargs) -> new dictionary initialized with the name=value pairs
 |      in the keyword argument list.  For example:  dict(one=1, two=2)
 |  
 |  Methods defined here:
 |  
 |  __contains__(self, key, /)
 |      True if D has a key k, else False.
 |  
 |  __delitem__(self, key, /)
 |      Delete self[key].
 |  
 |  __eq__(self, value, /)
 |      Return self==value.
 |  
 |  __ge__(self, value, /)
 |      Return self>=value.
 |  
 |  __getattribute__(self, name, /)
 |      Return getattr(self, name).
 |  
 |  __getitem__(...)
 |      x.__getitem__(y) <==> x[y]
 |  
 |  __gt__(self, value, /)
 |      Return self>value.
 |  
 |  __init__(self, /, *args, **kwargs)
 |      Initialize self.  See help(type(self)) for accurate signature.
 |  
 |  __iter__(self, /)
 |      Implement iter(self).
 |  
 |  __le__(self, value, /)
 |      Return self<=value.
 |  
 |  __len__(self, /)
 |      Return len(self).
 |  
 |  __lt__(self, value, /)
 |      Return self<value.
 |  
 |  __ne__(self, value, /)
 |      Return self!=value.
 |  
 |  __new__(*args, **kwargs) from builtins.type
 |      Create and return a new object.  See help(type) for accurate signature.
 |  
 |  __repr__(self, /)
 |      Return repr(self).
 |  
 |  __setitem__(self, key, value, /)
 |      Set self[key] to value.
 |  
 |  __sizeof__(...)
 |      D.__sizeof__() -> size of D in memory, in bytes
 |  
 |  clear(...)
 |      D.clear() -> None.  Remove all items from D.
 |  
 |  copy(...)
 |      D.copy() -> a shallow copy of D
 |  
 |  fromkeys(iterable, value=None, /) from builtins.type
 |      Returns a new dict with keys from iterable and values equal to value.
 |  
 |  get(...)
 |      D.get(k[,d]) -> D[k] if k in D, else d.  d defaults to None.
 |  
 |  items(...)
 |      D.items() -> a set-like object providing a view on D's items
 |  
 |  keys(...)
 |      D.keys() -> a set-like object providing a view on D's keys
 |  
 |  pop(...)
 |      D.pop(k[,d]) -> v, remove specified key and return the corresponding value.
 |      If key is not found, d is returned if given, otherwise KeyError is raised
 |  
 |  popitem(...)
 |      D.popitem() -> (k, v), remove and return some (key, value) pair as a
 |      2-tuple; but raise KeyError if D is empty.
 |  
 |  setdefault(...)
 |      D.setdefault(k[,d]) -> D.get(k,d), also set D[k]=d if k not in D
 |  
 |  update(...)
 |      D.update([E, ]**F) -> None.  Update D from dict/iterable E and F.
 |      If E is present and has a .keys() method, then does:  for k in E: D[k] = E[k]
 |      If E is present and lacks a .keys() method, then does:  for k, v in E: D[k] = v
 |      In either case, this is followed by: for k in F:  D[k] = F[k]
 |  
 |  values(...)
 |      D.values() -> an object providing a view on D's values
 |  
 |  ----------------------------------------------------------------------
 |  Data and other attributes defined here:
 |  
 |  __hash__ = None

Help on class list in module builtins:

class list(object)
 |  list() -> new empty list
 |  list(iterable) -> new list initialized from iterable's items
 |  
 |  Methods defined here:
 |  
 |  __add__(self, value, /)
 |      Return self+value.
 |  
 |  __contains__(self, key, /)
 |      Return key in self.
 |  
 |  __delitem__(self, key, /)
 |      Delete self[key].
 |  
 |  __eq__(self, value, /)
 |      Return self==value.
 |  
 |  __ge__(self, value, /)
 |      Return self>=value.
 |  
 |  __getattribute__(self, name, /)
 |      Return getattr(self, name).
 |  
 |  __getitem__(...)
 |      x.__getitem__(y) <==> x[y]
 |  
 |  __gt__(self, value, /)
 |      Return self>value.
 |  
 |  __iadd__(self, value, /)
 |      Implement self+=value.
 |  
 |  __imul__(self, value, /)
 |      Implement self*=value.
 |  
 |  __init__(self, /, *args, **kwargs)
 |      Initialize self.  See help(type(self)) for accurate signature.
 |  
 |  __iter__(self, /)
 |      Implement iter(self).
 |  
 |  __le__(self, value, /)
 |      Return self<=value.
 |  
 |  __len__(self, /)
 |      Return len(self).
 |  
 |  __lt__(self, value, /)
 |      Return self<value.
 |  
 |  __mul__(self, value, /)
 |      Return self*value.n
 |  
 |  __ne__(self, value, /)
 |      Return self!=value.
 |  
 |  __new__(*args, **kwargs) from builtins.type
 |      Create and return a new object.  See help(type) for accurate signature.
 |  
 |  __repr__(self, /)
 |      Return repr(self).
 |  
 |  __reversed__(...)
 |      L.__reversed__() -- return a reverse iterator over the list
 |  
 |  __rmul__(self, value, /)
 |      Return self*value.
 |  
 |  __setitem__(self, key, value, /)
 |      Set self[key] to value.
 |  
 |  __sizeof__(...)
 |      L.__sizeof__() -- size of L in memory, in bytes
 |  
 |  append(...)
 |      L.append(object) -> None -- append object to end
 |  
 |  clear(...)
 |      L.clear() -> None -- remove all items from L
 |  
 |  copy(...)
 |      L.copy() -> list -- a shallow copy of L
 |  
 |  count(...)
 |      L.count(value) -> integer -- return number of occurrences of value
 |  
 |  extend(...)
 |      L.extend(iterable) -> None -- extend list by appending elements from the iterable
 |  
 |  index(...)
 |      L.index(value, [start, [stop]]) -> integer -- return first index of value.
 |      Raises ValueError if the value is not present.
 |  
 |  insert(...)
 |      L.insert(index, object) -- insert object before index
 |  
 |  pop(...)
 |      L.pop([index]) -> item -- remove and return item at index (default last).
 |      Raises IndexError if list is empty or index is out of range.
 |  
 |  remove(...)
 |      L.remove(value) -> None -- remove first occurrence of value.
 |      Raises ValueError if the value is not present.
 |  
 |  reverse(...)
 |      L.reverse() -- reverse *IN PLACE*
 |  
 |  sort(...)
 |      L.sort(key=None, reverse=False) -> None -- stable sort *IN PLACE*
 |  
 |  ----------------------------------------------------------------------
 |  Data and other attributes defined here:
 |  
 |  __hash__ = None
View Code

2.内置函数补充2

# divmod()
# 应用场景:共有97条数,每页显示10条,需多少页?
r = divmod(97,10)     # 97/10 运算后所得的商和余数
n1,n2 = divmod(98,10) # 把商和余数分别赋值给n1,n2
print(r)        # 返回一个元组
print(n1,n2)
输出结果:
(9, 7)
9 8
###########################################################################################
# isinstance()  判断一个对象是否是某个类的实例(对象的功能都封装在类里,对象是类的实例)
s = "raymond"            # s是字符串
r1 = isinstance(s,str)   # s是str类的实例
r2 = isinstance(s,dict)  # s不是dict类的实例
print(r1,r2)

输出结果: True False
###########################################################################################
# filter() 是可迭代的对象
# 普通方法:过滤一个列表(保留大于22的元素)
def f1(args):
    result = []
    for item in args:
        if item > 22:
            result.append(item)
    return result
li = [11,22,33,44,55]
ret = f1(li)
print(ret)

输出结果:
[33, 44, 55]
# -----------------------------------------------------------------
# 用filter()方法过滤大于22的元素
def f2(a):
    if a > 22:
        return True
li = [11,22,33,44,55]
ret = filter(f2,li)
 '''
# 1. filter()内部循环第二个参数,让每个循环元素作为参数传递给第一个函数参数,然后执行函数。
# 2. 如果函数返回True,则将元素赋值给ret并保存在列表输出;函数返回False,则丢弃元素。
 '''
print(list(ret))
#
输出结果:
[33, 44, 55]
###########################################################################################
# lambda 内部返回bool值
f1 = lambda a: a > 30
a = f1(10)
b = f1(90)
print(a,b)
输出结果:False True
# -----------------------------------------------------------------
# filter() + lambda 组合使用场景
li = [11,22,33,44,55]
result = filter(lambda a:a>30,li)
print(list(result))
#
输出结果:
[33, 44, 55]
###########################################################################################
# 一般方法:
li = [11,22,33,44,55]
def f1(args):
    result = []
    for item in args:
        result.append(item+100)
    return result
ret = f1(li)
print(list(ret))

输出结果:
[111, 122, 133, 144, 155]
# ---------------------------------------------------------------------------
# map()函数,可迭代的对象(可以for循环的东西)
# 使用map()函数实现以上代码功能:
li = [11,22,33,44,55]
def f2(a):
    return  a+100
result = map(f2,li)
print(list(result))

输出结果:
[111, 122, 133, 144, 155]
# ---------------------------------------------------------------------------
# 使用map() + lambda 组合应用场景:对列表中每个元素进行同样功能的批量处理
# map() + lambda 实现以上代码:
li = [11, 22, 33, 44, 55]
result = map(lambda a:a+100,li)
print(list(result))

输出结果:[111, 122, 133, 144, 155]
---------------------------------------------------------------------------
# 总结:1. filter() 返回True,将列表元素添加到结果中
#       2. map()  将函数返回值添加到结果中
###########################################################################################
#  globals()  代表所有全局变量
#  locals()  代表所有局部变量
NAME = "raymond"
def show():
    a = 123
    b = 456
    print(locals())    # 输出变量名与值对应的字典
    print(globals())   # 除了输出全局变量,还有一些python内部的全局变量
show()

输出结果:
{'b': 456, 'a': 123}
{'__name__': '__main__', '__doc__': '\n1. filter()内部循环第二个参数,让每个循环元素作为参数传递给第一个函数参数,然后执行函数。\n2. 如果函数返回True,则将元素赋值给ret并保存在列表输出;函数返回False,则丢弃元素。\n', '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x000002165F7DCB00>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'E:/PythonProject/python13-day1/text.py', '__cached__': None, 'NAME': 'raymond', 'show': <function show at 0x000002165F382E18>}
###########################################################################################
# hash()
s1 = 'raymond'
s2 = 'jshfjsfhsjdfhsfsfkskdjf'
print("s1:",hash(s1))
print("s2:",hash(s2))
print(len(str(hash(s1))))   # 输出hash值的长度
输出结果:随机输出两串19位的数字
s1: 4413186832486012387
s2: -6135389105302975698
###########################################################################################
# max(), min(), sum()
li = [11,22,33,44,55]
r = max(li)
s = min(li)
t = sum (li)
print(r,s,t)
输出结果:55 11 165
###########################################################################################
pow()
r = pow(2,10)   # 表示2的10次方
print(r)
###########################################################################################
# reverse() 翻转
li = [11,22,1,1]
li = reversed(li)    # 内部执行了li.reverse()方法,两个效果一样
print(li)
###########################################################################################
r = round(1.8)     # 四舍五入
print(r)
输出结果:2
###########################################################################################
# sorted()
li = [55,11,22,44,33]
li.sort()     # 按列表元素从小到大的顺序输出
sorted(li)    # 按列表元素原本顺序输出
print(li)
###########################################################################################
# zip()
r = ["raymond",11,22,33]
s = ["is",22,33,44]
t = ["boy",33,44,55]

a = zip(r,s)
print(list(a))
# -------------------------------------------------------------------------------------------
b = zip(r,s,t)   # 会把每个以不同列表的元素按相同下标的元素组合成一个元组,每个元组构成的元素形成新列表。元素少的列表不与别的列表元素匹配。
temp = list(b)[0]      #需调试
ret = ' '.join(temp)
print(ret)

输出结果:
[('raymond', 'is'), (11, 22), (22, 33), (33, 44)]
raymond is boy
# ###########################################################################################
# 其他内置函数
id()          # 查看内存地址
issubclass()  # 查看一个类是否是另一个类的派生类
len()         # 查看长度,2.x按字节计算;3.x按字符计算
memoryview()  # 查看内存地址的一个数
object()      # 表示所有类的父类
range()       # 表示范围
vars()        # 当前模块变量哪些可使用
repr(object)  # 将对象转化为供解释器读取的形式。
slice()       # 3.x新加的切片功能
View Code

3.上节作业剖析

4.装饰器概要

# 在a.py文件中创建装饰器代码
# 应用场景:可以对多个业务功能f1(),f2()在不修改的前提下进行添加新的业务功能。
# 可以根据流水线业务的先后顺序在原来功能的前面和后面都可添加新业务功能
def outer(func):
    def inner():
        print('log')
        func()
        print('after')
    return inner

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

@outer
def f2():
    print("f2")
# ###########################################################################################
# # 以下代码在b.py中创建,导入a.py
import a

a.f1()
a.f2()
View Code

5.装饰器流程剖析储备知识

def f1():
    print(123)
def f1():
    print(456)
f1()       # 两个函数f1()类似一个变量名先后赋两个值,输出第二个函数的值

输出结果:456
###########################################################################################
def f1():    # 创建f1()函数,并将整个函数体放入内存中
    print(123)    
def f2(x):   # 此处接收f1函数体,相当于x=f1
    x()      # 此处相当于x()=f1(),是执行f1()函数
f2(f1)       # f1不加括号,代表x形参接收f1全部函数体

输出结果:123
View Code

6.装饰器流程剖析之原理步骤、返回值和参数传递

  代码详解:

# 以下代码段在a.py中创建
# 定义好函数未调用时,函数内部不执行
# 函数名(不加括号)代替整个函数;加括号后,执行函数
def outer(func):    # 括号里func=f1
    def inner():
        print('before')
        func()      # 此处func()=f1(),执行下面原有f1()
        print('after')
    return inner    # 返回值inner表示整个inner函数体,此处会将inner整个函数赋值给f1函数,下面f1()=inner()

@outer
# @outer 功能解释如下:
# 1. 程序运行到此处,自动执行outer函数,并且将其下面装饰的函数名f1当作参数传递到上面func形参中
# 2. 将outer函数的返回值,重新赋值给f1
# 3. 如果一个函数f1()被装饰器函数outer()装饰后,这个函数f1会被重新赋值成装饰器的内层函数,调用f1()会执行outer函数的内层函数inner()
# 4. 应用场景:假如f1()是一个功能的底层函数,那么装饰器函数outer()会在不修改底层函数的前提下,对其进行增加业务功能
def f1():
    print('F1')
# ###########################################################################################
# 以下代码在b.py中创建,导入a.py
import a

a.f1()

输出结果:
before
F1
after
View Code

    运行步骤:

#单行运行步骤:
def outer(func):     # 第一步
    def inner():     # 第三步
        print('before')  # 第五步
        func()           # 第六步   此处调用下面f1()原本功能
        print('after')   # 第八步
    return inner     # 第四步    此处如果inner+(),则代表执行inner(),返回值为None;重新赋值给f1,f1()返回None,改变原有f1()功能。

@outer              # @outer+f1()整体: 第二步
def f1():
    print('F1')     # 第七步 (调用本来函数功能)
View Code

  返回值和参数:

# 完整装饰器函数调用,可接收任意参数
def outer(*args,**kwargs):      # 可接收任意个参数
    def inner(*args,**kwargs):
        print('before')
        r = func()
        print('after')
        return r     
    return inner

@outer
def f1(arg):        # 调用f1()传一个参数
    print('F1')
    return  123     # 原函数f1()带有返回值的情况

@outer
def f2(arg1,arg2):  # def f1(arg):        # 调用f2()传两个参数,也可以有更多参数
    print('F2')
    return  456
#------------------------------------------------------------------------------------
# 以下代码在b.py中创建,导入a.py
import a

a.f1(3)
a.f2(2,3)
View Code

7.实例:用户管理程序

8.今日作业

第五章.双层装饰器、字符串格式化、生成器、迭代器以及重要模块介绍

1.双层装饰器实现用户登录和权限验证1

2.双层装饰器实现用户登录和权限验证2

3.多层装饰器原理

4.python字符串格式化

  Python的字符串格式化有两种方式: 百分号方式、format方式

  百分号的方式相对来说比较老,而format方式则是比较先进的方式,企图替换古老的方式,目前两者并存。

百分号方式:

%[(name)][flags][width].[precision]typecode
  • (name)      可选,用于选择指定的key
  • flags          可选,可供选择的值有:
    • +       右对齐;正数前加正好,负数前加负号;
    • -        左对齐;正数前无符号,负数前加负号;
    • 空格    右对齐;正数前加空格,负数前加负号;
    • 0        右对齐;正数前无符号,负数前加负号;用0填充空白处
  • width         可选,占有宽度
  • .precision   可选,小数点后保留的位数
  • typecode    必选
    • s,获取传入对象的__str__方法的返回值,并将其格式化到指定位置
    • r,获取传入对象的__repr__方法的返回值,并将其格式化到指定位置
    • c,整数:将数字转换成其unicode对应的值,10进制范围为 0 <= i <= 1114111(py27则只支持0-255);字符:将字符添加到指定位置
    • o,将整数转换成 八  进制表示,并将其格式化到指定位置
    • x,将整数转换成十六进制表示,并将其格式化到指定位置
    • d,将整数、浮点数转换成 十 进制表示,并将其格式化到指定位置
    • e,将整数、浮点数转换成科学计数法,并将其格式化到指定位置(小写e)
    • E,将整数、浮点数转换成科学计数法,并将其格式化到指定位置(大写E)
    • f, 将整数、浮点数转换成浮点数表示,并将其格式化到指定位置(默认保留小数点后6位)
    • F,同上
    • g,自动调整将整数、浮点数转换成 浮点型或科学计数法表示(超过6位数用科学计数法),并将其格式化到指定位置(如果是科学计数则是e;)
    • G,自动调整将整数、浮点数转换成 浮点型或科学计数法表示(超过6位数用科学计数法),并将其格式化到指定位置(如果是科学计数则是E;)
    • %,当字符串中存在格式化标志时,需要用 %%表示一个百分号

注:Python中百分号格式化是不存在自动将整数转换成二进制表示的方式

常用格式化:

tpl = "i am %s" % "alex"
 
tpl = "i am %s age %d" % ("alex", 18)
 
tpl = "i am %(name)s age %(age)d" % {"name": "alex", "age": 18}
 
tpl = "percent %.2f" % 99.97623
 
tpl = "i am %(pp).2f" % {"pp": 123.425556, }
 
tpl = "i am %.2f %%" % {"pp": 123.425556, }

Format方式:

[[fill]align][sign][#][0][width][,][.precision][type]
  •  fill           【可选】空白处填充的字符
  • align        【可选】对齐方式(需配合width使用)
  • <,内容左对齐
  • >,内容右对齐(默认)
  • =,内容右对齐,将符号放置在填充字符的左侧,且只对数字类型有效。 即使:符号+填充物+数字
  • ^,内容居中
  • sign         【可选】有无符号数字
    • +,正号加正,负号加负;
    •  -,正号不变,负号加负;
    • 空格 ,正号空格,负号加负;
  • #            【可选】对于二进制、八进制、十六进制,如果加上#,会显示 0b/0o/0x,否则不显示
  • ,            【可选】为数字添加分隔符,如:1,000,000
  • width       【可选】格式化位所占宽度
  • .precision 【可选】小数位保留精度
  • type         【可选】格式化类型
    • 传入” 字符串类型 “的参数
      • s,格式化字符串类型数据
      • 空白,未指定类型,则默认是None,同s
    • 传入“ 整数类型 ”的参数
      • b,将10进制整数自动转换成2进制表示然后格式化
      • c,将10进制整数自动转换为其对应的unicode字符
      • d,十进制整数
      • o,将10进制整数自动转换成8进制表示然后格式化;
      • x,将10进制整数自动转换成16进制表示然后格式化(小写x)
      • X,将10进制整数自动转换成16进制表示然后格式化(大写X)
    • 传入“ 浮点型或小数类型 ”的参数
      • e, 转换为科学计数法(小写e)表示,然后格式化;
      • E, 转换为科学计数法(大写E)表示,然后格式化;
      • f , 转换为浮点型(默认小数点后保留6位)表示,然后格式化;
      • F, 转换为浮点型(默认小数点后保留6位)表示,然后格式化;
      • g, 自动在e和f中切换
      • G, 自动在E和F中切换
      • %,显示百分比(默认显示小数点后6位)

 常用格式化:

tpl = "i am {}, age {}, {}".format("seven", 18, 'alex')
  
tpl = "i am {}, age {}, {}".format(*["seven", 18, 'alex'])
  
tpl = "i am {0}, age {1}, really {0}".format("seven", 18)
  
tpl = "i am {0}, age {1}, really {0}".format(*["seven", 18])
  
tpl = "i am {name}, age {age}, really {name}".format(name="seven", age=18)
  
tpl = "i am {name}, age {age}, really {name}".format(**{"name": "seven", "age": 18})
  
tpl = "i am {0[0]}, age {0[1]}, really {0[2]}".format([1, 2, 3], [11, 22, 33])
  
tpl = "i am {:s}, age {:d}, money {:f}".format("seven", 18, 88888.1)
  
tpl = "i am {:s}, age {:d}".format(*["seven", 18])
  
tpl = "i am {name:s}, age {age:d}".format(name="seven", age=18)
  
tpl = "i am {name:s}, age {age:d}".format(**{"name": "seven", "age": 18})
 
tpl = "numbers: {:b},{:o},{:d},{:x},{:X}, {:%}".format(15, 15, 15, 15, 15, 15.87623, 2)
 
tpl = "numbers: {:b},{:o},{:d},{:x},{:X}, {:%}".format(15, 15, 15, 15, 15, 15.87623, 2)
 
tpl = "numbers: {0:b},{0:o},{0:d},{0:x},{0:X}, {0:%}".format(15)
 
tpl = "numbers: {num:b},{num:o},{num:d},{num:x},{num:X}, {num:%}".format(num=15)

6.python生成器

一个函数调用时返回一个迭代器,那这个函数就叫做生成器(generator);如果函数中包含yield语法,那这个函数就会变成生成器;

def func():
    yield 1
    yield 2
    yield 3
    yield 4

上述代码中:func是函数称为生成器,当执行此函数func()时会得到一个迭代器。

>>> temp = func()
>>> temp.__next__()
1
>>> temp.__next__()
2
>>> temp.__next__()
3
>>> temp.__next__()
4
>>> temp.__next__()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration

 示例: 

# 生成器(具有生成数据的功能叫生成器)
def func():     # 如果函数里有yield,则该函数变为生成器
    print('start')
    yield 1
    yield 2
    yield 3
ret = func()    # 函数执行到此处,并不执行函数
print(ret)      # 返回一个生成器对象(generator object),循环这个对象才可以取值
输出结果:
<generator object func at 0x0000028098630FC0>
----------------------------------------------------------------------------------------
r = ret.__next__()      # 调用此函数找到yield,每次只能取一个yield后面的值
print(r)
输出结果:
<generator object func at 0x0000024DA6F90FC0>
start
1

r = ret.__next__()      # 合并上次取到的值,再取第二个yield后面的值。
print(r)
输出结果:
<generator object func at 0x0000024DA6F90FC0>
start
1
2
###########################################################################################
# 用for循环取生成器中的值,结果输出全部生成器的返回值
def func():
    print('start')
    yield 1
    yield 2
    yield 3
ret = func()

for item in ret:        # 每循环一次,去func()中依次取函数输出值以及yield后面的返回值。
    print(item)         # 分别取到:start,1,2,3

输出结果:
start
1
2
3
View Code

7.基于生成器实现range功能以及python迭代器

# 基于生成器实现range功能
def myrange(arg):
    start = 0
    while True:
        if start > arg:
            return
        else:
            yield start  # 具有生成数据功能的叫生成器。
            start += 1
ret = myrange(5)    # 可迭代的对对象,叫迭代器。可通过__next__()去取值,一直到取完值后,报错!
r = ret.__next__()
print(r)            # 输出结果:0
r = ret.__next__()
print(r)            # 输出结果:0,1
View Code

8.python函数递归

# 如果函数无返回值,默认返回None
def fun(n):     # 递归函数
    n = n + 1
    if n >= 4:
        return  'end'
    return fun(n)
r = fun(1)
print(r)
输出结果:end
View Code

9.利用递归实现阶乘实例

# 递归函数(函数反复调用自己)
def func(num):
    if num ==1:
        return 1
    return num*func(num - 1)
x = func(7)
print(x)

输出结果:5040

10.python模块介绍

  在python安装目录中:D:\Program Files\Python\Python36\Lib

  此目录中包含所有python模块,如:xxx.py

  模块分为:

  • 内置模块
  • 自定义模块
  • 第三方模块

  模块先导入,后使用。示例如下:

import sys
print(sys.path)

输出结果:
['E:\\PythonProject\\python13-day1', 'E:\\PythonProject\\python13-day1', 'E:\\PythonProject\\zgf', 'E:\\PythonProject\\python13-day1\\venv\\Scripts\\python36.zip', 'E:\\PythonProject\\python13-day1\\venv\\DLLs', 'E:\\PythonProject\\python13-day1\\venv\\lib', 'E:\\PythonProject\\python13-day1\\venv\\Scripts', 'D:\\Program Files\\Python\\Python36\\Lib', 'D:\\Program Files\\Python\\Python36\\DLLs', 'E:\\PythonProject\\python13-day1\\venv', 'E:\\PythonProject\\python13-day1\\venv\\lib\\site-packages', 'D:\\Program Files\\JetBrains\\PyCharm professional 2017.3.2\\helpers\\pycharm_matplotlib_backend']

  单模块用法:

  • import  模块名
  • from 模块名 import 函数名

  嵌套在文件夹里的模块:

  • from 文件夹名 import  文件名
  • from 文件夹名 import  文件名 as 别名

注:自定义模块名不要与内置模块名重名

11.安装第三方模块

  pip3 install requests  (python 3.x 自带pip3安装工具,2.x不带,需自己安装)

  源码安装:解压requests包-->进入目录-->python3 setup.py install

12.python序列化之json和pickle模块

# python序列化和反序列化:dumps(),loads()
import json

li = ['k1','v1']
ret = json.dumps(li)  # 将python基本数据类型转化为字符串格式
print(ret,type(ret))

输出结果:
["k1", "v1"] <class 'str'>
##########################################################################################
# s1 = '{'k1':123}'
import json
li = '["alex","eric"] '
ret = json.loads(li)   # 将字符串格式转化成python基本数据类型,反序列化时列表内一定要使用""
print(ret,type(ret))

输出结果:
['alex', 'eric'] <class 'list'>
###########################################################################################
# # 基于天气API获取天气相关JSON数据
import requests
import json
response = requests.get('http://wthrcdn.etouch.cn/weather_mini?city=%E5%8C%97%E4%BA%AC')
response.encoding = 'utf-8'
print(response.text)       # 获取 http请求返回的数据

输出结果:
{"data":{"yesterday":{"date":"25日星期三","high":"高温 25℃","fx":"南风","low":"低温 11℃","fl":"<![CDATA[3-4级]]>","type":"多云"},"city":"北京","aqi":"101","forecast":[{"date":"26日星期四","high":"高温 26℃","fengli":"<![CDATA[<3级]]>","low":"低温 11℃","fengxiang":"南风","type":""},{"date":"27日星期五","high":"高温 25℃","fengli":"<![CDATA[3-4级]]>","low":"低温 13℃","fengxiang":"西南风","type":""},{"date":"28日星期六","high":"高温 27℃","fengli":"<![CDATA[3-4级]]>","low":"低温 17℃","fengxiang":"西南风","type":""},{"date":"29日星期天","high":"高温 29℃","fengli":"<![CDATA[<3级]]>","low":"低温 17℃","fengxiang":"南风","type":"多云"},{"date":"30日星期一","high":"高温 26℃","fengli":"<![CDATA[3-4级]]>","low":"低温 15℃","fengxiang":"东北风","type":"多云"}],"ganmao":"各项气象条件适宜,无明显降温过程,发生感冒机率较低。","wendu":"24"},"status":1000,"desc":"OK"}

ret = json.loads(response.text)    # 将http返回的字符串转化为python基本数据类型字典
print(ret)

 输出结果:
{"data":{"yesterday":{"date":"25日星期三","high":"高温 25℃","fx":"南风","low":"低温 11℃","fl":"<![CDATA[3-4级]]>","type":"多云"},"city":"北京","aqi":"101","forecast":[{"date":"26日星期四","high":"高温 26℃","fengli":"<![CDATA[<3级]]>","low":"低温 11℃","fengxiang":"南风","type":""},{"date":"27日星期五","high":"高温 25℃","fengli":"<![CDATA[3-4级]]>","low":"低温 13℃","fengxiang":"西南风","type":""},{"date":"28日星期六","high":"高温 27℃","fengli":"<![CDATA[3-4级]]>","low":"低温 17℃","fengxiang":"西南风","type":""},{"date":"29日星期天","high":"高温 29℃","fengli":"<![CDATA[<3级]]>","low":"低温 17℃","fengxiang":"南风","type":"多云"},{"date":"30日星期一","high":"高温 26℃","fengli":"<![CDATA[3-4级]]>","low":"低温 15℃","fengxiang":"东北风","type":"多云"}],"ganmao":"各项气象条件适宜,无明显降温过程,发生感冒机率较低。","wendu":"24"},"status":1000,"desc":"OK"}
{'data': {'yesterday': {'date': '25日星期三', 'high': '高温 25℃', 'fx': '南风', 'low': '低温 11℃', 'fl': '<![CDATA[3-4级]]>', 'type': '多云'}, 'city': '北京', 'aqi': '101', 'forecast': [{'date': '26日星期四', 'high': '高温 26℃', 'fengli': '<![CDATA[<3级]]>', 'low': '低温 11℃', 'fengxiang': '南风', 'type': ''}, {'date': '27日星期五', 'high': '高温 25℃', 'fengli': '<![CDATA[3-4级]]>', 'low': '低温 13℃', 'fengxiang': '西南风', 'type': ''}, {'date': '28日星期六', 'high': '高温 27℃', 'fengli': '<![CDATA[3-4级]]>', 'low': '低温 17℃', 'fengxiang': '西南风', 'type': ''}, {'date': '29日星期天', 'high': '高温 29℃', 'fengli': '<![CDATA[<3级]]>', 'low': '低温 17℃', 'fengxiang': '南风', 'type': '多云'}, {'date': '30日星期一', 'high': '高温 26℃', 'fengli': '<![CDATA[3-4级]]>', 'low': '低温 15℃', 'fengxiang': '东北风', 'type': '多云'}], 'ganmao': '各项气象条件适宜,无明显降温过程,发生感冒机率较低。', 'wendu': '24'}, 'status': 1000, 'desc': 'OK'}
###########################################################################################
# 将文件内容序列化和反序列化:dump(),load()
import json
li =[11,22,33]
json.dump(li,open('db1','w'))     # 把li列表转为字符串,再写入db文件中

ret = json.load(open('db1','r'))  # 先读db文件,然后再把文件中字符串数据反序列化为列表
print(ret,type(ret))

输出结果:
[11, 22, 33] <class 'list'>
###########################################################################################
# python 序列化之pickle,只提供python使用
import pickle
li = [11,22,33]
r = pickle.dumps(li)    # 序列化为python特定的格式
print(r)

输出结果:
b'\x80\x03]q\x00(K\x0bK\x16K!e.'
---------------------------------------------------------------------------------
ret = pickle.loads(r)   # 把特定的格式反序列化为原来的列表
print(ret)

输出结果:
[11, 22, 33]
###########################################################################################
import  pickle
li = [11,22,33,44]
pickle.dump(li,open('db2','wb'))  # pickle序列化列表数据类型到文件,必须以字节码写入
# 写入文件内容是python特定格式:�]q (KKK!K,e.
r = pickle.load(open('db2','rb'))  # 把文件乱码内容还原为列表数据
print(r)

输出结果:
[11, 22, 33, 44]
View Code

 总结:

  • json:只能处理python的基本数据类型(dict,lixt,tuple,str,int,float,True,False);支持各种编程语言数据的序列化,适合基本数据类型。

  • pickle:除了可以处理json的基本数据类型外,还可以用于复杂数据类型的操作。例如:可记忆存储游戏闯关类数据文档。但只支持python使用,python不同版本之间的序列化和反序列化,可能报错。

13.基于天气API获取天气相关JSON数据

# 基于天气API获取天气相关JSON数据
import requests
import json
response = requests.get('http://wthrcdn.etouch.cn/weather_mini?city=%E5%8C%97%E4%BA%AC')
response.encoding = 'utf-8'
print(response.text)       # 获取 http请求返回的数据

输出结果:
{"data":{"yesterday":{"date":"25日星期三","high":"高温 25℃","fx":"南风","low":"低温 11℃","fl":"<![CDATA[3-4级]]>","type":"多云"},"city":"北京","aqi":"101","forecast":[{"date":"26日星期四","high":"高温 26℃","fengli":"<![CDATA[<3级]]>","low":"低温 11℃","fengxiang":"南风","type":""},{"date":"27日星期五","high":"高温 25℃","fengli":"<![CDATA[3-4级]]>","low":"低温 13℃","fengxiang":"西南风","type":""},{"date":"28日星期六","high":"高温 27℃","fengli":"<![CDATA[3-4级]]>","low":"低温 17℃","fengxiang":"西南风","type":""},{"date":"29日星期天","high":"高温 29℃","fengli":"<![CDATA[<3级]]>","low":"低温 17℃","fengxiang":"南风","type":"多云"},{"date":"30日星期一","high":"高温 26℃","fengli":"<![CDATA[3-4级]]>","low":"低温 15℃","fengxiang":"东北风","type":"多云"}],"ganmao":"各项气象条件适宜,无明显降温过程,发生感冒机率较低。","wendu":"24"},"status":1000,"desc":"OK"}

ret = json.loads(response.text)    # 将http返回的字符串转化为python基本数据类型字典
print(ret)

 输出结果:
{"data":{"yesterday":{"date":"25日星期三","high":"高温 25℃","fx":"南风","low":"低温 11℃","fl":"<![CDATA[3-4级]]>","type":"多云"},"city":"北京","aqi":"101","forecast":[{"date":"26日星期四","high":"高温 26℃","fengli":"<![CDATA[<3级]]>","low":"低温 11℃","fengxiang":"南风","type":""},{"date":"27日星期五","high":"高温 25℃","fengli":"<![CDATA[3-4级]]>","low":"低温 13℃","fengxiang":"西南风","type":""},{"date":"28日星期六","high":"高温 27℃","fengli":"<![CDATA[3-4级]]>","low":"低温 17℃","fengxiang":"西南风","type":""},{"date":"29日星期天","high":"高温 29℃","fengli":"<![CDATA[<3级]]>","low":"低温 17℃","fengxiang":"南风","type":"多云"},{"date":"30日星期一","high":"高温 26℃","fengli":"<![CDATA[3-4级]]>","low":"低温 15℃","fengxiang":"东北风","type":"多云"}],"ganmao":"各项气象条件适宜,无明显降温过程,发生感冒机率较低。","wendu":"24"},"status":1000,"desc":"OK"}
{'data': {'yesterday': {'date': '25日星期三', 'high': '高温 25℃', 'fx': '南风', 'low': '低温 11℃', 'fl': '<![CDATA[3-4级]]>', 'type': '多云'}, 'city': '北京', 'aqi': '101', 'forecast': [{'date': '26日星期四', 'high': '高温 26℃', 'fengli': '<![CDATA[<3级]]>', 'low': '低温 11℃', 'fengxiang': '南风', 'type': ''}, {'date': '27日星期五', 'high': '高温 25℃', 'fengli': '<![CDATA[3-4级]]>', 'low': '低温 13℃', 'fengxiang': '西南风', 'type': ''}, {'date': '28日星期六', 'high': '高温 27℃', 'fengli': '<![CDATA[3-4级]]>', 'low': '低温 17℃', 'fengxiang': '西南风', 'type': ''}, {'date': '29日星期天', 'high': '高温 29℃', 'fengli': '<![CDATA[<3级]]>', 'low': '低温 17℃', 'fengxiang': '南风', 'type': '多云'}, {'date': '30日星期一', 'high': '高温 26℃', 'fengli': '<![CDATA[3-4级]]>', 'low': '低温 15℃', 'fengxiang': '东北风', 'type': '多云'}], 'ganmao': '各项气象条件适宜,无明显降温过程,发生感冒机率较低。', 'wendu': '24'}, 'status': 1000, 'desc': 'OK'}
View Code

14.python时间处理之time&datetime模块 

import time
import datetime

print(time.time())      #1 时间戳 (UNIX官方发布时间1970-01-01 00:00:00 距离当前时间段的秒数)  *****
print(time.ctime())     #2 打印当前时间
print(time.ctime(3600)) #3 把时间戳转为具体日期
print(time.mktime(time.localtime()))    #4 把当前时间转为距1970年的时间戳
print(time.sleep(3))  #5 CPU停止工作3秒   *****
print(time.clock())     #6 计算CPU执行时间
print(time.gmtime())    #7 结构化时间(元组格式),以世界UTC标准时间为标准输出,北京与UTC时间相差8小时。UTC=1000,北京=1800
print(time.localtime()) #8 输出本地当地当前时间,与本地PC时间相同  *****
print(time.strftime('%Y-%m-%d %H:%M:%S'))   #9 字符串格式化输出时间    *****
print(time.strptime('2018-04-27 10:43:39','%Y-%m-%d %H:%M:%S'))  #10 把字符串格式化时间转为结构化时间 *****
a = time.strptime('2018-04-27 10:43:39','%Y-%m-%d %H:%M:%S')
print(a.tm_year)    #11 可单独取出日期和时间的年、月、日 和 时,分,秒
print(a.tm_mon)     #12 只输出月份
print(a.tm_mday)    #13 只输出几号
print(a.tm_wday)    #14 当前日期是本周中的第几天 (周一:0)
print(a.tm_yday)    #15 当前日期是本年中的第几天

print(datetime.datetime.now())  #16 输出当前系统的规范格式时间


输出结果依次为以下16行:
1524799294.4669478
Fri Apr 27 11:21:34 2018
Thu Jan  1 09:00:00 1970
1524799294.0
None
7.2934459635882e-07
time.struct_time(tm_year=2018, tm_mon=4, tm_mday=27, tm_hour=3, tm_min=21, tm_sec=37, tm_wday=4, tm_yday=117, tm_isdst=0)
time.struct_time(tm_year=2018, tm_mon=4, tm_mday=27, tm_hour=11, tm_min=21, tm_sec=37, tm_wday=4, tm_yday=117, tm_isdst=0)
2018-04-27 11:21:37
time.struct_time(tm_year=2018, tm_mon=4, tm_mday=27, tm_hour=10, tm_min=43, tm_sec=39, tm_wday=4, tm_yday=117, tm_isdst=-1)
2018
4
27
4
117
2018-04-27 11:21:37.479549
# ###########################################################################################
# python中时间日期格式化符号:

# %y 两位数的年份表示(00-99)
# %Y 四位数的年份表示(000-9999)
# %m 月份(01-12)
# %d 月内中的一天(0-31)
# %H 24小时制小时数(0-23)
# %I 12小时制小时数(01-12)
# %M 分钟数(00=59)
# %S 秒(00-59)
# %a 本地简化星期名称
# %A 本地完整星期名称
# %b 本地简化的月份名称
# %B 本地完整的月份名称
# %c 本地相应的日期表示和时间表示
# %j 年内的一天(001-366)
# %p 本地A.M.或P.M.的等价符
# %U 一年中的星期数(00-53)星期天为星期的开始
# %w 星期(0-6),星期天为星期的开始
# %W 一年中的星期数(00-53)星期一为星期的开始
# %x 本地相应的日期表示
# %X 本地相应的时间表示
# %Z 当前时区的名称
# %% %号本身
View Code

15.python日志处理之logging模块

用于便捷记录日志且线程安全的模块

import logging
 
 
logging.basicConfig(filename='log.log',
                    format='%(asctime)s - %(name)s - %(levelname)s -%(module)s:  %(message)s',
                    datefmt='%Y-%m-%d %H:%M:%S %p',
                    level=10)
 
logging.debug('debug')
logging.info('info')
logging.warning('warning')
logging.error('error')
logging.critical('critical')
logging.log(10,'log')

对于level级别如下所示:

CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0

注:只有大于当前日志等级的操作才会被记录。

对于格式,有如下属性可以配置:

16.今日作业以及代码目录

第六章.python反射、重要模块以及正则表达式

1.ATM作业分析

2.python反射模块之getattr,hasattr,setattr,delattr

# python之反射概念:利用字符串的形式去对象(模块)中操作(查找/检查/删除/设置)成员(函数)
# 下面反射函数中m代表模块名,f代表与函数同名的字符串
# getattr(m,f):  用字符串f查找模块m ;
# hasattr(m,f):  判断字符串f是否再模块m中,函数返回True或False ;
# setattr(m,f,v) 给对象的属性赋值,如果此属性不存在,会先创建,然后再赋值 ;
# delattr(m,f):  delattr 函数用于删除属性。相当于del m.f() ; 如果属性不存在,会报错
###########################################################################################
# 创建文件名为commons.py,代码如下:
def login():
    print('login')
def logout():
    print('logout')
def home():
    print('home')
# -------------------------------------------------------------------------------------------
# 创建index.py文件
# import commons
# # 导入模块时,会先放在内存中;反射函数基于内存操作模块,重新reload模块,便可回复成员
#
def run():
    inp = input('请输入访问地址:')     # inp 表示输入的是字符串
    if hasattr(commons,inp):   # bool型,为真,执行下面函数
        func = getattr(commons,inp)   # 此处inp可以加入单个字符串形式的成员名,如:'login'
        func()              # 如果找到模块中的成员,则执行该成员函数
    else:
        print('404')


if __name__ == '__main__':
    run()
###########################################################################################
# 通过字符串查找任意模块及函数
# obj = __import__('commons')  # 表示导入commons模块,等价于 import commons
# obj.login()       # 导入后执行commons模块中的login()
import commons
def run():
    inp = input('请输入访问地址:')
    m,f = inp.split('/')    # 把输入的字符串用 m/f 形式分割为:模块名/函数名
    obj = __import__(m)     # m表示输入的字符串形式的模块名,如果导入一个库中所有模块,此处修改为(解释见下段代码):obj = __import__("lib."+m,fromlist=True)
    if hasattr(obj,f):
        func = getattr(obj,f)
        func()
    else:
        print('404')

if __name__ == '__main__':
    run()
###########################################################################################
# 假设所有模块在lib文件夹库中,需修改导入方式如下:
# 以下方法最常用,用一个主文件index导入一个库(文件夹里存储着很多模块文件)中的所有模块文件
obj = __import__("lib."+m,fromlist=True)
View Code

3.python模块中特殊变量

# 特殊全局变量:__file__, __doc__, __cached__, (__name__, __package__)最后两个必须掌握
print(vars(test1))       # 打印test1模块中的变量
print(test1.__dict__)    # 同上

print(__doc__)      # 获取当前文件中'''注释部分'''的文档,#号后的注释不获取
print(__cached__)   # python导入一个模块时,会生成一个*.pyc文件(字节码),__cached__指定pyc文件的路径
print(__file__)     # 打印当前py文件所在路径;如果跳到py所在目录下执行文件,只能取到py文件名
# -----------------------------------------------------------------------------------------
# print(__package__)  输出文件所在的包名
# 假设:s1导入s2,s2在bin目录下,那么在s1中代码如下:
from bin import s2
print(s2.__packge__)
输出结果:bin
# -----------------------------------------------------------------------------------------
# __name__ == __main__,只有执行当前文件时候,当前文件的特殊变量__name__=__main__
def fun():
    print('run')
if __name__ == "__main__":  # 此时 __name__ == "__main__"为真,所以执行下面函数;如果被另外文件调用fun(),则__name__ != "__main__",为假,不执行下面函数fun()
    fun()
###########################################################################################
import os
import sys
print(os.path.abspath(__file__))   # 永远取到的是文件的绝对路径,包含文件名
print(os.path.dirname(__file__))   # 返回原文件的上一级目录
ret = print(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))   # 返回原文件路径的上两级目录
sys.path.append(ret)    # 如果原文件上两级的目录添加到sys.path路径中,这样py文件所在的上两级目录放在任何地方都可以执行
View Code

4.python之sys模块

用于提供对解释器相关的操作

sys.argv           命令行参数List,第一个元素是程序本身路径
sys.exit(n)        退出程序,正常退出时exit(0)
sys.version        获取Python解释程序的版本信息
sys.maxint         最大的Int值
sys.path           返回模块的搜索路径,初始化时使用PYTHONPATH环境变量的值
sys.platform       返回操作系统平台名称
sys.stdout.write('please:')
val = sys.stdin.readline()[:-1]
View Code

5.python之os模块

用于提供系统级别的操作

os.getcwd() 获取当前工作目录,即当前python脚本工作的目录路径
os.chdir("dirname")  改变当前脚本工作目录;相当于shell下cd
os.curdir  返回当前目录: ('.')
os.pardir  获取当前目录的父目录字符串名:('..')
os.makedirs('dirname1/dirname2')    可生成多层递归目录
os.removedirs('dirname1')    若目录为空,则删除,并递归到上一级目录,如若也为空,则删除,依此类推
os.mkdir('dirname')    生成单级目录;相当于shell中mkdir dirname
os.rmdir('dirname')    删除单级空目录,若目录不为空则无法删除,报错;相当于shell中rmdir dirname
os.listdir('dirname')    列出指定目录下的所有文件和子目录,包括隐藏文件,并以列表方式打印
os.remove()  删除一个文件
os.rename("oldname","newname")  重命名文件/目录
os.stat('path/filename')  获取文件/目录信息
os.sep    输出操作系统特定的路径分隔符,win下为"\\",Linux下为"/"
os.linesep    输出当前平台使用的行终止符,win下为"\t\n",Linux下为"\n"
os.pathsep    输出用于分割文件路径的字符串
os.name    输出字符串指示当前使用平台。win->'nt'; Linux->'posix'
os.system("bash command")  运行shell命令,直接显示
os.environ  获取系统环境变量
os.path.abspath(path)  返回path规范化的绝对路径
os.path.split(path)  将path分割成目录和文件名二元组返回
os.path.dirname(path)  返回path的目录。其实就是os.path.split(path)的第一个元素
os.path.basename(path)  返回path最后的文件名。如何path以/或\结尾,那么就会返回空值。即os.path.split(path)的第二个元素
os.path.exists(path)  如果path存在,返回True;如果path不存在,返回False
os.path.isabs(path)  如果path是绝对路径,返回True
os.path.isfile(path)  如果path是一个存在的文件,返回True。否则返回False
os.path.isdir(path)  如果path是一个存在的目录,则返回True。否则返回False
os.path.join(path1[, path2[, ...]])  将多个路径组合后返回,第一个绝对路径之前的参数将被忽略
os.path.getatime(path)  返回path所指向的文件或者目录的最后存取时间
os.path.getmtime(path)  返回path所指向的文件或者目录的最后修改时间
View Code
  • os模块中几个重要的操作函数
import os
import sys
print(os.path.abspath(__file__))   # 永远取到的是文件的绝对路径,包含文件名
print(os.path.dirname(__file__))   # 返回原文件的上一级目录
ret = print(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))   # 返回原文件路径的上两级目录
sys.path.append(ret)    # 如果原文件上两级的目录添加到sys.path路径中,这样py文件所在的上两级目录放在任何地方都可以执行
###########################################################################################
import os

os.path.abspath(path='')        # 返回path规范化的绝对路径
os.path.dirname(path='')        # 返回path的目录。其实就是os.path.split(path)的第一个元素
os.path.join(path1[, path2[, ...]])   # 将多个路径组合后返回,第一个绝对路径之前的参数将被忽略

6.python之hashlib加密模块

用于加密相关的操作,代替了md5模块和sha模块,主要提供 SHA1, SHA224, SHA256, SHA384, SHA512 ,MD5 算法

import md5
hash = md5.new()
hash.update('admin')
print hash.hexdigest()
MD5—废弃
import sha

hash = sha.new()
hash.update('admin')
print hash.hexdigest()
SHA—废弃

hashlib用法:

import hashlib
 
# ######## md5 ########
 
hash = hashlib.md5()
hash.update('admin')
print hash.hexdigest()
 
# ######## sha1 ########
 
hash = hashlib.sha1()
hash.update('admin')
print hash.hexdigest()
 
# ######## sha256 ########
 
hash = hashlib.sha256()
hash.update('admin')
print hash.hexdigest()
 
 
# ######## sha384 ########
 
hash = hashlib.sha384()
hash.update('admin')
print hash.hexdigest()
 
# ######## sha512 ########
 
hash = hashlib.sha512()
hash.update('admin')
print hash.hexdigest()

以上加密算法虽然依然非常厉害,但时候存在缺陷,即:通过撞库可以反解。所以,有必要对加密算法中添加自定义key再来做加密。 

import hashlib
 
# ######## md5 ########
 
hash = hashlib.md5('898oaFs09f')
hash.update('admin')
print hash.hexdigest()

还不够吊?python 还有一个 hmac 模块,它内部对我们创建 key 和 内容 再进行处理然后再加密  

import hmac
h = hmac.new('wueiqi')
h.update('hellowo')
print h.hexdigest()

到这儿就顶天牛逼了!!!

应用示例:

# hashlib    各种加密对象都保存在hashlib模块中,必须先导入,再使用
# MD5        不可逆,只能加密,不能解密
import hashlib
obj = hashlib.md5(bytes('abcdef',encoding='utf-8'))  # 对123加密后的值,用abcdef进行再次加密
# obj = obj.update('123')     # 适用与于Python 2.X
obj.update(bytes('123',encoding='utf-8'))    # 适用与于Python 3.X
result = obj.hexdigest()   # 获取加密后的值
print(result)
View Code

7.configparser模块

 configparser用于处理特定格式的文件,其本质上是利用open来操作文件。

# 创建特定格式文件xxxooo.txt

[section1]    # 节点
  k1 = 123      # 键值对
  k2 = raymond
  k3:v3         # 键值对 


[section2]    # 节点
  k1 = 456      # 键值对


[section3]
     |
     |
[sectionx]    # 第x个节点块
View Code
  • 获取所有节点
import configparser
 
config = configparser.ConfigParser()
config.read('xxxooo', encoding='utf-8')
ret = config.sections()
print(ret)
  • 获取指定节点下所有的键值对
import configparser
 
config = configparser.ConfigParser()
config.read('xxxooo', encoding='utf-8')
ret = config.items('section1')
print(ret)
  • 获取指定节点下所有的键
import configparser
 
config = configparser.ConfigParser()
config.read('xxxooo', encoding='utf-8')
ret = config.options('section1')
print(ret)
  • 获取指定节点下指定key的值
import configparser
 
config = configparser.ConfigParser()
config.read('xxxooo', encoding='utf-8')
 
 
v = config.get('section1', 'k1')
# v = config.getint('section1', 'k1')
# v = config.getfloat('section1', 'k1')
# v = config.getboolean('section1', 'k1')
 
print(v)
  • 检查、删除、添加节点
import configparser
 
config = configparser.ConfigParser()
config.read('xxxooo', encoding='utf-8')
 
 
# 检查
has_sec = config.has_section('section1')
print(has_sec)
 
# 添加节点
config.add_section("SEC_1")
config.write(open('xxxooo', 'w'))
 
# 删除节点
config.remove_section("SEC_1")
config.write(open('xxxooo', 'w'))
  • 检查、删除、设置指定组内的键值对
import configparser
 
config = configparser.ConfigParser()
config.read('xxxooo', encoding='utf-8')
 
# 检查
has_opt = config.has_option('section1', 'k1')
print(has_opt)
 
# 删除
config.remove_option('section1', 'k1')
config.write(open('xxxooo', 'w'))
 
# 设置
config.set('section1', 'k10', "123")
config.write(open('xxxooo', 'w'))

8.shutil模块以及压缩包处理 

高级的 文件、文件夹、压缩包 处理模块 

  • shutil.copyfileobj(fsrc, fdst[, length])

  将文件内容拷贝到另一个文件中 

import shutil
 
shutil.copyfileobj(open('old.xml','r'), open('new.xml', 'w'))
  • shutil.copyfile(src, dst)

  拷贝文件 

shutil.copyfile('f1.log', 'f2.log')
  • shutil.copymode(src, dst)

  仅拷贝权限。内容、组、用户均不变

shutil.copymode('f1.log', 'f2.log')
  • shutil.copystat(src, dst)

  仅拷贝状态的信息,包括:mode bits, atime, mtime, flags

shutil.copystat('f1.log', 'f2.log')
  • shutil.copy(src, dst)

  拷贝文件和权限 

import shutil
 
shutil.copy('f1.log', 'f2.log')
  • shutil.copy2(src, dst)

  拷贝文件和状态信息 

import shutil
 
shutil.copy2('f1.log', 'f2.log')
  • shutil.ignore_patterns(*patterns)
  • shutil.copytree(src, dst, symlinks=False, ignore=None)

  递归的去拷贝文件夹 

import shutil
 
shutil.copytree('folder1', 'folder2', ignore=shutil.ignore_patterns('*.pyc', 'tmp*'))
import shutil

shutil.copytree('f1', 'f2', symlinks=True, ignore=shutil.ignore_patterns('*.pyc', 'tmp*'))
  • shutil.rmtree(path[, ignore_errors[, onerror]])

  递归的去删除文件 

import shutil
 
shutil.rmtree('folder1')
  • shutil.move(src, dst)

  递归的去移动文件,它类似mv命令,其实就是重命名。 

import shutil
 
shutil.move('folder1', 'folder3')
  • shutil.make_archive(base_name, format,...)

  创建压缩包并返回文件路径,例如:zip、tar

  创建压缩包并返回文件路径,例如:zip、tar

    • base_name: 压缩包的文件名,也可以是压缩包的路径。只是文件名时,则保存至当前目录,否则保存至指定路径,
      如:www                        =>保存至当前路径
      如:/Users/wupeiqi/www =>保存至/Users/wupeiqi/
    • format: 压缩包种类,“zip”, “tar”, “bztar”,“gztar”
    • root_dir: 要压缩的文件夹路径(默认当前目录)
    • owner: 用户,默认当前用户
    • group: 组,默认当前组
    • logger: 用于记录日志,通常是logging.Logger对象 
#将 /Users/wupeiqi/Downloads/test 下的文件打包放置当前程序目录
import shutil
ret = shutil.make_archive("wwwwwwwwww", 'gztar', root_dir='/Users/wupeiqi/Downloads/test')
  
  
#将 /Users/wupeiqi/Downloads/test 下的文件打包放置 /Users/wupeiqi/目录
import shutil
ret = shutil.make_archive("/Users/wupeiqi/wwwwwwwwww", 'gztar', root_dir='/Users/wupeiqi/Downloads/test')

shutil 对压缩包的处理是调用 ZipFile 和 TarFile 两个模块来进行的,示例如下: 

import zipfile

# 压缩
z = zipfile.ZipFile('laxi.zip', 'w')
z.write('a.log')
z.write('data.data')
z.close()

# 解压
z = zipfile.ZipFile('laxi.zip', 'r')
z.extractall()
z.close()

zipfile解压缩
zipfile解压缩
import tarfile

# 压缩
tar = tarfile.open('your.tar','w')
tar.add('/Users/wupeiqi/PycharmProjects/bbs2.log', arcname='bbs2.log')
tar.add('/Users/wupeiqi/PycharmProjects/cmdb.log', arcname='cmdb.log')
tar.close()

# 解压
tar = tarfile.open('your.tar','r')
tar.extractall()  # 可设置解压地址
tar.close()

tarfile解压缩
tarfile解压缩

9.subprocess模块 

可以执行shell命令的相关模块和函数有: 

  • os.system
  • os.spawn*
  • os.popen*          --废弃
  • popen2.*           --废弃
  • commands.*      --废弃,3.x中被移除
import commands

result = commands.getoutput('cmd')
result = commands.getstatus('cmd')
result = commands.getstatusoutput('cmd')
View Code

 以上执行shell命令的相关的模块和函数的功能均在 subprocess 模块中实现,并提供了更丰富的功能。

call 

执行命令,返回状态码

ret = subprocess.call(["ls", "-l"], shell=False)    # 只获取状态码,不获取命令执行结果
ret = subprocess.call("ls -l", shell=True)

check_call

执行命令,如果执行状态码是 0 ,则返回0,否则抛异常

subprocess.check_call(["ls", "-l"])    

subprocess.check_call("exit 1", shell=True)

check_output

执行命令,如果状态码是 0 ,则返回命令执行结果,否则抛异常 

subprocess.check_output(["echo", "Hello World!"])
subprocess.check_output("exit 1", shell=True)

subprocess.check_output("ls -l",shell=True)  # 获取命令执行结果

subprocess.Popen(...)

用于执行复杂的系统命令

参数:

    • args:shell命令,可以是字符串或者序列类型(如:list,元组)
    • bufsize:指定缓冲。0 无缓冲,1 行缓冲,其他 缓冲区大小,负值 系统缓冲
    • stdin, stdout, stderr:分别表示程序的标准输入、输出、错误句柄
    • preexec_fn:只在Unix平台下有效,用于指定一个可执行对象(callable object),它将在子进程运行之前被调用
    • close_sfs:在windows平台下,如果close_fds被设置为True,则新创建的子进程将不会继承父进程的输入、输出、错误管道。
      所以不能将close_fds设置为True同时重定向子进程的标准输入、输出与错误(stdin, stdout, stderr)。
    • shell:同上
    • cwd:用于设置子进程的当前目录
    • env:用于指定子进程的环境变量。如果env = None,子进程的环境变量将从父进程中继承。
    • universal_newlines:不同系统的换行符不同,True -> 同意使用 \n
    • startupinfo与createionflags只在windows下有效
      将被传递给底层的CreateProcess()函数,用于设置子进程的一些属性,如:主窗口的外观,进程的优先级等等 
import subprocess
ret1 = subprocess.Popen(["mkdir","t1"])
ret2 = subprocess.Popen("mkdir t2", shell=True)
执行普通命令

终端输入的命令分为两种:

  • 输入即可得到输出,如:ifconfig
  • 输入进行某环境,依赖再输入,如:python 
import subprocess
# 跳转到cwd目录下,执行mkdir命令
obj = subprocess.Popen("mkdir t3", shell=True, cwd='/home/dev',)   
View Code
import subprocess
#通过管道进行输入内容(stdin),输出内容(stdout)和捕捉错误内容(atderr)
obj = subprocess.Popen(["python"], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)  
obj.stdin.write('print 1 \n ')     # 输入4行内容
obj.stdin.write('print 2 \n ')
obj.stdin.write('print 3 \n ')
obj.stdin.write('print 4 \n ')
obj.stdin.close()

cmd_out = obj.stdout.read()    # 输出内容
obj.stdout.close()
cmd_error = obj.stderr.read()   # 捕捉错误内容
obj.stderr.close()

print cmd_out
print cmd_error
View Code
import subprocess

obj = subprocess.Popen(["python"], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
obj.stdin.write('print 1 \n ')
obj.stdin.write('print 2 \n ')
obj.stdin.write('print 3 \n ')
obj.stdin.write('print 4 \n ')

#以下语句同时捕捉输出管道和错误管道的内容,返回一个列表类型,存放输出和错误内容
out_error_list = obj.communicate() 
print out_error_list
View Code
import subprocess

obj = subprocess.Popen(["python"], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)


# 把字符串内容放入python解释器解释成python可执行代码
out_error_list = obj.communicate('print "hello"') 
print out_error_list
View Code

10.python之正则表达式

常用正则表达式符号 

'.'     默认匹配除\n之外的任意一个字符,若指定flag DOTALL,则匹配任意字符,包括换行
'^'     匹配字符开头,若指定flags MULTILINE,这种也可以匹配上(r"^a","\nabc\neee",flags=re.MULTILINE)
'$'     匹配字符结尾,或e.search("foo$","bfoo\nsdfsf",flags=re.MULTILINE).group()也可以
'*'     匹配*号前的字符0次或多次,re.findall("ab*","cabb3abcbbac")  结果为['abb', 'ab', 'a']
'+'     匹配前一个字符1次或多次,re.findall("ab+","ab+cd+abb+bba") 结果['ab', 'abb']
'?'     匹配前一个字符1次或0次
'{m}'   匹配前一个字符m次
'{n,m}' 匹配前一个字符n到m次,re.findall("ab{1,3}","abb abc abbcbbb") 结果'abb', 'ab', 'abb']
'|'     匹配|左或|右的字符,re.search("abc|ABC","ABCBabcCD").group() 结果'ABC'
'(...)' 分组匹配,re.search("(abc){2}a(123|456)c", "abcabca456c").group() 结果 abcabca456c
 
 
'\A'    只从字符开头匹配,re.search("\Aabc","alexabc") 是匹配不到的
'\Z'    匹配字符结尾,同$
'\d'    匹配数字0-9
'\D'    匹配非数字
'\w'    匹配[A-Za-z0-9]
'\W'    匹配非[A-Za-z0-9]
's'     匹配空白字符、\t、\n、\r , re.search("\s+","ab\tc1\n3").group() 结果 '\t'
 
'(?P<name>...)' 分组匹配 re.search("(?P<province>[0-9]{4})(?P<city>[0-9]{2})(?P<birthday>[0-9]{4})","371481199306143242").groupdict("city") 结果{'province': '3714', 'city': '81', 'birthday': '1993'}

 最常用的匹配语法

re.match 从头开始匹配
re.search 匹配包含
re.findall 把所有匹配到的字符放到以列表中的元素返回
re.splitall 以匹配到的字符当做列表分隔符
re.sub      匹配字符并替换

 

反斜杠的困扰
与大多数编程语言相同,正则表达式里使用"\"作为转义字符,这就可能造成反斜杠困扰。假如你需要匹配文本中的字符"\",那么使用编程语言表示的正则表达式里将需要4个反斜杠"\\\\":前两个和后两个分别用于在编程语言里转义成反斜杠,转换成两个反斜杠后再在正则表达式里转义成一个反斜杠。Python里的原生字符串很好地解决了这个问题,这个例子中的正则表达式可以使用r"\\"表示。同样,匹配一个数字的"\\d"可以写成r"\d"。有了原生字符串,你再也不用担心是不是漏写了反斜杠,写出来的表达式也更直观。 

 

仅需轻轻知道的几个匹配模式

re.I(re.IGNORECASE): 忽略大小写(括号内是完整写法,下同)
M(MULTILINE): 多行模式,改变'^'和'$'的行为(参见上图)
S(DOTALL): 点任意匹配模式,改变'.'的行为

11.python之正则表达式之分组

12.XML模块

浏览器返回的字符串类型有以下三种:

  • HTML
  • JSON
  • XML      1. 可做页面展示; 2. 可做配置文件使用

 XML是实现不同语言或程序之间进行数据交换的协议,XML文件格式如下:

<data>
    <country name="Liechtenstein">
        <rank updated="yes">2</rank>
        <year>2023</year>
        <gdppc>141100</gdppc>
        <neighbor direction="E" name="Austria" />
        <neighbor direction="W" name="Switzerland" />
    </country>
    <country name="Singapore">
        <rank updated="yes">5</rank>
        <year>2026</year>
        <gdppc>59900</gdppc>
        <neighbor direction="N" name="Malaysia" />
    </country>
    <country name="Panama">
        <rank updated="yes">69</rank>
        <year>2026</year>
        <gdppc>13600</gdppc>
        <neighbor direction="W" name="Costa Rica" />
        <neighbor direction="E" name="Colombia" />
    </country>
</data>
XML文件格式

1. 解析XML 

from xml.etree import ElementTree as ET


# 打开文件,读取XML内容
str_xml = open('xo.xml', 'r').read()

# 将字符串解析成xml特殊对象,root代指xml文件的根节点
root = ET.XML(str_xml)
利用ElementTree.XML将字符串解析成xml对象
from xml.etree import ElementTree as ET

# 直接解析xml文件,把文件加载到特殊对象tree中
tree = ET.parse("xo.xml")

# 获取xml文件的根节点
root = tree.getroot()
View Code

2. 操作XML

XML格式类型是节点嵌套节点,对于每一个节点均有以下功能,以便对当前节点进行操作: 

class Element:
    """An XML element.

    This class is the reference implementation of the Element interface.

    An element's length is its number of subelements.  That means if you
    want to check if an element is truly empty, you should check BOTH
    its length AND its text attribute.

    The element tag, attribute names, and attribute values can be either
    bytes or strings.

    *tag* is the element name.  *attrib* is an optional dictionary containing
    element attributes. *extra* are additional element attributes given as
    keyword arguments.

    Example form:
        <tag attrib>text<child/>...</tag>tail

    """

    当前节点的标签名
    tag = None
    """The element's name."""

    当前节点的属性

    attrib = None
    """Dictionary of the element's attributes."""

    当前节点的内容
    text = None
    """
    Text before first subelement. This is either a string or the value None.
    Note that if there is no text, this attribute may be either
    None or the empty string, depending on the parser.

    """

    tail = None
    """
    Text after this element's end tag, but before the next sibling element's
    start tag.  This is either a string or the value None.  Note that if there
    was no text, this attribute may be either None or an empty string,
    depending on the parser.

    """

    def __init__(self, tag, attrib={}, **extra):
        if not isinstance(attrib, dict):
            raise TypeError("attrib must be dict, not %s" % (
                attrib.__class__.__name__,))
        attrib = attrib.copy()
        attrib.update(extra)
        self.tag = tag
        self.attrib = attrib
        self._children = []

    def __repr__(self):
        return "<%s %r at %#x>" % (self.__class__.__name__, self.tag, id(self))

    def makeelement(self, tag, attrib):
        创建一个新节点
        """Create a new element with the same type.

        *tag* is a string containing the element name.
        *attrib* is a dictionary containing the element attributes.

        Do not call this method, use the SubElement factory function instead.

        """
        return self.__class__(tag, attrib)

    def copy(self):
        """Return copy of current element.

        This creates a shallow copy. Subelements will be shared with the
        original tree.

        """
        elem = self.makeelement(self.tag, self.attrib)
        elem.text = self.text
        elem.tail = self.tail
        elem[:] = self
        return elem

    def __len__(self):
        return len(self._children)

    def __bool__(self):
        warnings.warn(
            "The behavior of this method will change in future versions.  "
            "Use specific 'len(elem)' or 'elem is not None' test instead.",
            FutureWarning, stacklevel=2
            )
        return len(self._children) != 0 # emulate old behaviour, for now

    def __getitem__(self, index):
        return self._children[index]

    def __setitem__(self, index, element):
        # if isinstance(index, slice):
        #     for elt in element:
        #         assert iselement(elt)
        # else:
        #     assert iselement(element)
        self._children[index] = element

    def __delitem__(self, index):
        del self._children[index]

    def append(self, subelement):
        为当前节点追加一个子节点
        """Add *subelement* to the end of this element.

        The new element will appear in document order after the last existing
        subelement (or directly after the text, if it's the first subelement),
        but before the end tag for this element.

        """
        self._assert_is_element(subelement)
        self._children.append(subelement)

    def extend(self, elements):
        为当前节点扩展 n 个子节点
        """Append subelements from a sequence.

        *elements* is a sequence with zero or more elements.

        """
        for element in elements:
            self._assert_is_element(element)
        self._children.extend(elements)

    def insert(self, index, subelement):
        在当前节点的子节点中插入某个节点,即:为当前节点创建子节点,然后插入指定位置
        """Insert *subelement* at position *index*."""
        self._assert_is_element(subelement)
        self._children.insert(index, subelement)

    def _assert_is_element(self, e):
        # Need to refer to the actual Python implementation, not the
        # shadowing C implementation.
        if not isinstance(e, _Element_Py):
            raise TypeError('expected an Element, not %s' % type(e).__name__)

    def remove(self, subelement):
        在当前节点在子节点中删除某个节点
        """Remove matching subelement.

        Unlike the find methods, this method compares elements based on
        identity, NOT ON tag value or contents.  To remove subelements by
        other means, the easiest way is to use a list comprehension to
        select what elements to keep, and then use slice assignment to update
        the parent element.

        ValueError is raised if a matching element could not be found.

        """
        # assert iselement(element)
        self._children.remove(subelement)

    def getchildren(self):
        获取所有的子节点(废弃)
        """(Deprecated) Return all subelements.

        Elements are returned in document order.

        """
        warnings.warn(
            "This method will be removed in future versions.  "
            "Use 'list(elem)' or iteration over elem instead.",
            DeprecationWarning, stacklevel=2
            )
        return self._children

    def find(self, path, namespaces=None):
        获取第一个寻找到的子节点
        """Find first matching element by tag name or path.

        *path* is a string having either an element tag or an XPath,
        *namespaces* is an optional mapping from namespace prefix to full name.

        Return the first matching element, or None if no element was found.

        """
        return ElementPath.find(self, path, namespaces)

    def findtext(self, path, default=None, namespaces=None):
        获取第一个寻找到的子节点的内容
        """Find text for first matching element by tag name or path.

        *path* is a string having either an element tag or an XPath,
        *default* is the value to return if the element was not found,
        *namespaces* is an optional mapping from namespace prefix to full name.

        Return text content of first matching element, or default value if
        none was found.  Note that if an element is found having no text
        content, the empty string is returned.

        """
        return ElementPath.findtext(self, path, default, namespaces)

    def findall(self, path, namespaces=None):
        获取所有的子节点
        """Find all matching subelements by tag name or path.

        *path* is a string having either an element tag or an XPath,
        *namespaces* is an optional mapping from namespace prefix to full name.

        Returns list containing all matching elements in document order.

        """
        return ElementPath.findall(self, path, namespaces)

    def iterfind(self, path, namespaces=None):
        获取所有指定的节点,并创建一个迭代器(可以被for循环)
        """Find all matching subelements by tag name or path.

        *path* is a string having either an element tag or an XPath,
        *namespaces* is an optional mapping from namespace prefix to full name.

        Return an iterable yielding all matching elements in document order.

        """
        return ElementPath.iterfind(self, path, namespaces)

    def clear(self):
        清空节点
        """Reset element.

        This function removes all subelements, clears all attributes, and sets
        the text and tail attributes to None.

        """
        self.attrib.clear()
        self._children = []
        self.text = self.tail = None

    def get(self, key, default=None):
        获取当前节点的属性值
        """Get element attribute.

        Equivalent to attrib.get, but some implementations may handle this a
        bit more efficiently.  *key* is what attribute to look for, and
        *default* is what to return if the attribute was not found.

        Returns a string containing the attribute value, or the default if
        attribute was not found.

        """
        return self.attrib.get(key, default)

    def set(self, key, value):
        为当前节点设置属性值
        """Set element attribute.

        Equivalent to attrib[key] = value, but some implementations may handle
        this a bit more efficiently.  *key* is what attribute to set, and
        *value* is the attribute value to set it to.

        """
        self.attrib[key] = value

    def keys(self):
        获取当前节点的所有属性的 key

        """Get list of attribute names.

        Names are returned in an arbitrary order, just like an ordinary
        Python dict.  Equivalent to attrib.keys()

        """
        return self.attrib.keys()

    def items(self):
        获取当前节点的所有属性值,每个属性都是一个键值对
        """Get element attributes as a sequence.

        The attributes are returned in arbitrary order.  Equivalent to
        attrib.items().

        Return a list of (name, value) tuples.

        """
        return self.attrib.items()

    def iter(self, tag=None):
        在当前节点的子孙中根据节点名称寻找所有指定的节点,并返回一个迭代器(可以被for循环)。
        """Create tree iterator.

        The iterator loops over the element and all subelements in document
        order, returning all elements with a matching tag.

        If the tree structure is modified during iteration, new or removed
        elements may or may not be included.  To get a stable set, use the
        list() function on the iterator, and loop over the resulting list.

        *tag* is what tags to look for (default is to return all elements)

        Return an iterator containing all the matching elements.

        """
        if tag == "*":
            tag = None
        if tag is None or self.tag == tag:
            yield self
        for e in self._children:
            yield from e.iter(tag)

    # compatibility
    def getiterator(self, tag=None):
        # Change for a DeprecationWarning in 1.4
        warnings.warn(
            "This method will be removed in future versions.  "
            "Use 'elem.iter()' or 'list(elem.iter())' instead.",
            PendingDeprecationWarning, stacklevel=2
        )
        return list(self.iter(tag))

    def itertext(self):
        在当前节点的子孙中根据节点名称寻找所有指定的节点的内容,并返回一个迭代器(可以被for循环)。
        """Create text iterator.

        The iterator loops over the element and all subelements in document
        order, returning all inner text.

        """
        tag = self.tag
        if not isinstance(tag, str) and tag is not None:
            return
        if self.text:
            yield self.text
        for e in self:
            yield from e.itertext()
            if e.tail:
                yield e.tail
节点功能一览表 

由于 每个节点 都具有以上的方法,并且在上一步骤中解析时均得到了root(xml文件的根节点),so   可以利用以上方法进行操作xml文件。

a. 遍历XML文档的所有内容

from xml.etree import ElementTree as ET

############ 解析方式一 ############
"""
# 打开文件,读取XML内容
str_xml = open('xo.xml', 'r').read()

# 将字符串解析成xml特殊对象,root代指xml文件的根节点
root = ET.XML(str_xml)
"""
############ 解析方式二 ############

# 直接解析xml文件
tree = ET.parse("xo.xml")

# 获取xml文件的根节点
root = tree.getroot()


### 操作

# 顶层标签
print(root.tag)


# 遍历XML文档的第二层
for child in root:
    # 第二层节点的标签名称和标签属性
    print(child.tag, child.attrib)
    # 遍历XML文档的第三层
    for i in child:
        # 第二层节点的标签名称和内容
        print(i.tag,i.text)
View Code

b、遍历XML中指定的节点 

from xml.etree import ElementTree as ET

############ 解析方式一 ############
"""
# 打开文件,读取XML内容
str_xml = open('xo.xml', 'r').read()

# 将字符串解析成xml特殊对象,root代指xml文件的根节点
root = ET.XML(str_xml)
"""
############ 解析方式二 ############

# 直接解析xml文件
tree = ET.parse("xo.xml")

# 获取xml文件的根节点
root = tree.getroot()


### 操作

# 顶层标签
print(root.tag)


# 遍历XML中所有的year节点
for node in root.iter('year'):
    # 节点的标签名称和内容
    print(node.tag, node.text)
View Code

c、修改节点内容 

由于修改的节点时,均是在内存中进行,其不会影响文件中的内容。所以,如果想要修改,则需要重新将内存中的内容写到文件。

from xml.etree import ElementTree as ET

############ 解析方式一 ############

# 打开文件,读取XML内容
str_xml = open('xo.xml', 'r').read()

# 将字符串解析成xml特殊对象,root代指xml文件的根节点
root = ET.XML(str_xml)

############ 操作 ############

# 顶层标签
print(root.tag)

# 循环所有的year节点
for node in root.iter('year'):
    # 将year节点中的内容自增一
    new_year = int(node.text) + 1
    node.text = str(new_year)

    # 设置属性
    node.set('name', 'alex')
    node.set('age', '18')
    # 删除属性
    del node.attrib['name']


############ 保存文件 ############
tree = ET.ElementTree(root)
tree.write("newnew.xml", encoding='utf-8')
解析字符串方式,修改,保存
from xml.etree import ElementTree as ET

############ 解析方式二 ############

# 直接解析xml文件
tree = ET.parse("xo.xml")

# 获取xml文件的根节点
root = tree.getroot()

############ 操作 ############

# 顶层标签
print(root.tag)

# 循环所有的year节点
for node in root.iter('year'):
    # 将year节点中的内容自增一
    new_year = int(node.text) + 1
    node.text = str(new_year)

    # 设置属性
    node.set('name', 'alex')
    node.set('age', '18')
    # 删除属性
    del node.attrib['name']


############ 保存文件 ############
tree.write("newnew.xml", encoding='utf-8')
解析文件方式,修改,保存

d、删除节点

from xml.etree import ElementTree as ET

############ 解析字符串方式打开 ############

# 打开文件,读取XML内容
str_xml = open('xo.xml', 'r').read()

# 将字符串解析成xml特殊对象,root代指xml文件的根节点
root = ET.XML(str_xml)

############ 操作 ############

# 顶层标签
print(root.tag)

# 遍历data下的所有country节点
for country in root.findall('country'):
    # 获取每一个country节点下rank节点的内容
    rank = int(country.find('rank').text)

    if rank > 50:
        # 删除指定country节点
        root.remove(country)

############ 保存文件 ############
tree = ET.ElementTree(root)
tree.write("newnew.xml", encoding='utf-8')
解析字符串方式打开,删除,保存
from xml.etree import ElementTree as ET

############ 解析文件方式 ############

# 直接解析xml文件
tree = ET.parse("xo.xml")

# 获取xml文件的根节点
root = tree.getroot()

############ 操作 ############

# 顶层标签
print(root.tag)

# 遍历data下的所有country节点
for country in root.findall('country'):
    # 获取每一个country节点下rank节点的内容
    rank = int(country.find('rank').text)

    if rank > 50:
        # 删除指定country节点
        root.remove(country)

############ 保存文件 ############
tree.write("newnew.xml", encoding='utf-8')
解析文件方式打开,删除,保存 

3. 创建XML文档

from xml.etree import ElementTree as ET


# 创建根节点
root = ET.Element("famliy")


# 创建节点大儿子
son1 = ET.Element('son', {'name': '儿1'})
# 创建小儿子
son2 = ET.Element('son', {"name": '儿2'})

# 在大儿子中创建两个孙子
grandson1 = ET.Element('grandson', {'name': '儿11'})
grandson2 = ET.Element('grandson', {'name': '儿12'})
son1.append(grandson1)
son1.append(grandson2)


# 把儿子添加到根节点中
root.append(son1)
root.append(son1)

tree = ET.ElementTree(root)
tree.write('oooo.xml',encoding='utf-8', short_empty_elements=False)
创建方式1
from xml.etree import ElementTree as ET

# 创建根节点
root = ET.Element("famliy")


# 创建大儿子
# son1 = ET.Element('son', {'name': '儿1'})
son1 = root.makeelement('son', {'name': '儿1'})
# 创建小儿子
# son2 = ET.Element('son', {"name": '儿2'})
son2 = root.makeelement('son', {"name": '儿2'})

# 在大儿子中创建两个孙子
# grandson1 = ET.Element('grandson', {'name': '儿11'})
grandson1 = son1.makeelement('grandson', {'name': '儿11'})
# grandson2 = ET.Element('grandson', {'name': '儿12'})
grandson2 = son1.makeelement('grandson', {'name': '儿12'})

son1.append(grandson1)
son1.append(grandson2)


# 把儿子添加到根节点中
root.append(son1)
root.append(son1)

tree = ET.ElementTree(root)
tree.write('oooo.xml',encoding='utf-8', short_empty_elements=False)
创建方式2
from xml.etree import ElementTree as ET


# 创建根节点
root = ET.Element("famliy")


# 创建节点大儿子
son1 = ET.SubElement(root, "son", attrib={'name': '儿1'})
# 创建小儿子
son2 = ET.SubElement(root, "son", attrib={"name": "儿2"})

# 在大儿子中创建一个孙子
grandson1 = ET.SubElement(son1, "age", attrib={'name': '儿11'})
grandson1.text = '孙子'


et = ET.ElementTree(root)  #生成文档对象
et.write("test.xml", encoding="utf-8", xml_declaration=True, short_empty_elements=False)
创建方式3

由于原生保存的XML时默认无缩进,如果想要设置缩进的话, 需要修改保存方式:

from xml.etree import ElementTree as ET
from xml.dom import minidom


def prettify(elem):
    """将节点转换成字符串,并添加缩进。
    """
    rough_string = ET.tostring(elem, 'utf-8')
    reparsed = minidom.parseString(rough_string)
    return reparsed.toprettyxml(indent="\t")

# 创建根节点
root = ET.Element("famliy")


# 创建大儿子
# son1 = ET.Element('son', {'name': '儿1'})
son1 = root.makeelement('son', {'name': '儿1'})
# 创建小儿子
# son2 = ET.Element('son', {"name": '儿2'})
son2 = root.makeelement('son', {"name": '儿2'})

# 在大儿子中创建两个孙子
# grandson1 = ET.Element('grandson', {'name': '儿11'})
grandson1 = son1.makeelement('grandson', {'name': '儿11'})
# grandson2 = ET.Element('grandson', {'name': '儿12'})
grandson2 = son1.makeelement('grandson', {'name': '儿12'})

son1.append(grandson1)
son1.append(grandson2)


# 把儿子添加到根节点中
root.append(son1)
root.append(son1)


raw_str = prettify(root)

f = open("xxxoo.xml",'w',encoding='utf-8')
f.write(raw_str)
f.close()
View Code

13.本周作业

 

 

posted @ 2018-01-29 17:44  zgfraymond  阅读(371)  评论(0编辑  收藏  举报