nsd1905_py02_day02

关键字参数

函数的参数写为key=val这种形式,称作关键字参数,只有一个参数,如arg,称作位置参数。

  1. >>> def func1(name, age):
  2. ... print('%s is %s years old' % (name, age))
  3. >>> func1('bob', 20) # OK
  4. bob is 20 years old
  5. >>> func1(20, 'bob') # 语法正确,语义不对
  6. 20 is bob years old
  7. >>> func1(age=20, name='bob') # OK
  8. bob is 20 years old
  9. >>> func1(age=20, 'bob') # 语法错误,位置参数必须在关键字参数前
  10. File "<stdin>", line 1
  11. SyntaxError: positional argument follows keyword argument
  12. >>> func1(20, name='bob') # 错误,name得到了多个值
  13. Traceback (most recent call last):
  14. File "<stdin>", line 1, in <module>
  15. TypeError: func1() got multiple values for argument 'name'
  16. >>> func1('bob', age=20) # OK
  17. bob is 20 years old

参数组

  • 定义参数时,参数前加*表示使用元组接收参数
  • 定义参数时,参数前加**表示使用字典接收参数
>>> def func1(*args):
...   print(args)
>>> func1()
()
>>> func1(123)
(123,)
>>> func1(123, 'bob', 'hello')
(123, 'bob', 'hello')
>>> def func2(**kwargs):
...   print(kwargs)
... 
>>> func2()
{}
>>> func2(name='bob', age=20)
{'name': 'bob', 'age': 20}
  • 传参时,参数前加*表示把序列对象拆开
  • 传参时,参数前加**表示把字典拆开
>>> def add(x, y):
...   return x + y
... 
>>> nums = [1, 2]
>>> nums2 = (10, 20)
>>> add(*nums)
3
>>> add(*nums2)
30
>>> nums3 = {'y': 100, 'x': 5}
>>> add(**nums3)   # add(y=100, x=5)
105
>>> nums4 = {'a': 10, 'b': 3}
>>> add(**nums4)   # add(a=10, b=5)  # Error,没有参数a/b

匿名函数

  • 一般函数使用def定义,def后面是函数名
  • 匿名函数就是没有名字的函数
  • 使用lambda关键字定义
>>> def add(x, y):
...   return x + y
... 
>>> myadd = lambda x, y: x + y
>>> myadd(1, 2)
3
>>> add(1, 2)
3

filter(func, seq)函数

  • 是一个高阶函数,它的第一个参数是函数,第二个参数是序列对象
  • 传给filter函数的函数(第一个参数),它接受一个参数,执行的结果必须为True或False
  • 序列对象中每一个元素分别作为函数的参数,计算结果为True则保留,为False舍弃
from random import randint

def func1(x):
    return True if x % 2 == 1 else False

if __name__ == '__main__':
    nums = [randint(1, 100) for i in range(10)]
    print(nums)
    result = filter(func1, nums)
    print(list(result))
    result2 = filter(lambda x: True if x % 2 == 1 else False, nums)
    print(list(result2))

map(func, seq)函数

  • map是一个高阶函数,它的第一个参数是函数,第二个参数是序列对象
  • 序列对象中的每个元素都将作为函数的参数进行处理,处理的结果全部保存下来
def func1(s):
    return s + '.com'

if __name__ == '__main__':
    alist = ['qq', 'sohu', '163']
    result = map(func1, alist)
    print(list(result))
    result2 = map(lambda s: s + '.com', alist)
    print(list(result2))

变量

全局变量:在函数外定义的变量,全局变量从它定义的位置到程序结束,一直可见可用

局部变量:在函数内定义的变量,只能在函数内使用

>>> x = 10
>>> def func1():
...   print(x)
... 
>>> func1()
10
>>> def func2():
...   y = 100
...   print(y)
... 
>>> func2()
100
>>> print(y)  # 报错,局部变量只能在函数内使用

# 如果局部和全局有同名变量,局部变量将会遮盖住全局变量的值
>>> def func3():
...   x = 'hello world'
...   print(x)
... 
>>> func3()
hello world
>>> print(x)
10

# 如果需要通过局部改变全局变量,需要使用global关键字
>>> def func4():
...   global x
...   x = 100
...   print(x)
... 
>>> func4()
100
>>> print(x)
100

偏函数

  • 改造现有函数,将现有函数的一些参数固定下来,生成新函数
>>> def add(a, b, c, d, e):
...   return a + b + c + d + e
... 
>>> add(10, 20, 30, 40, 5)
105
>>> add(10, 20, 30, 40, 2)
102
>>> add(10, 20, 30, 40, 8)
108

# 改造add函数,将前4个参数固定下来,生成新的函数
>>> from functools import partial
>>> myadd = partial(add, 10, 20, 30, 40)
>>> myadd(5)
105
>>> myadd(8)
108

>>> int('11', base=2)  # 将2进制数11转为10进制数
3
>>> int('11000011', base=2)
195
>>> int2 = partial(int, base=2)
>>> int2('11')
3
>>> int16 = partial(int, base=16)
>>> int16('11')
17

递归函数

  • 函数调用自己,就是递归函数
# 5!=5x4x3x2x1
# 5!=5x4!
# 5!=5x4x3!
# 5!=5x4x3x2!
# 5!=5x4x3x2x1!

生成器

生成器潜在可以生成很多数据,但是不会立即生成。运行时节约空间。

实现的方法有两种:生成器表达式和函数的形式

>>> nums = (randint(1, 100) for i in range(10))
>>> nums
<generator object <genexpr> at 0x7f0dd3a19308>
>>> list(nums)
[32, 53, 83, 72, 5, 71, 26, 36, 90, 44]
# 生成器对象只能用一次,再用就没有值可取了
>>> nums = (randint(1, 100) for i in range(10))
>>> for i in nums:
...   print(i)

# 生成器函数可以通过yield返回很多中间结果
>>> def scq():
...   yield 10
...   n = 10 + 20
...   yield n
...   yield 100
... 
>>> a = scq()
>>> list(a)
[10, 30, 100]

>>> b = scq()
>>> for i in b:
...   print(i)

模块

导入模块时,python从sys.path定义的路径查找模块

>>> sys.path   # 空串表示当前目录
['', '/usr/local/lib/python36.zip', '/usr/local/lib/python3.6', '/usr/local/lib/python3.6/lib-dynload', '/root/nsd1905/lib/python3.6/site-packages']

自定义模块,如果希望在任何位置都可以导入,那么,可以把模块拷贝到site-packages目录。也可以通过环境变量PYTHONPATH定义路径

(nsd1905) [root@room8pc16 day02]# export PYTHONPATH=/path/to/module
# 把自己写的模块放到/path/to/module,在任意位置就都可以导入自定义模块了

python把目录当成特殊的模块

(nsd1905) [root@room8pc16 py02]# pwd
/var/ftp/nsd2019/nsd1905/py02
(nsd1905) [root@room8pc16 py02]# ls day02/qsort.py 
>>> import day02.qsort
>>> day02.qsort.qsort('hello')
['e', 'h', 'l', 'l', 'o']

hashlib模块

# 计算数据的md5值
>>> import hashlib
>>> m = hashlib.md5(b'123456')
>>> m.hexdigest()
'e10adc3949ba59abbe56e057f20f883e'

# 计算文件的md5值
>>> with open('/etc/hosts', 'rb') as fobj:
...   data = fobj.read()
... 
>>> m1 = hashlib.md5(data)
>>> m1.hexdigest()
'1b8f16e6e10c1a822dfc36cc4256344d'

>>> m2 = hashlib.md5()
>>> m2.update(b'12')
>>> m2.update(b'34')
>>> m2.update(b'56')
>>> m2.hexdigest()
'e10adc3949ba59abbe56e057f20f883e'

tarfile模块

实现tar包操作

# 打包并使用gz压缩
>>> import tarfile
# 以写方式打开,并且启用gzip压缩
>>> tar = tarfile.open('/tmp/mytest.tar.gz', 'w:gz')
>>> tar.add('/etc/security')
>>> tar.add('/etc/hosts')
>>> tar.close()

# 解压到/var/tmp目录
>>> tar = tarfile.open('/tmp/mytest.tar.gz')
>>> tar.extractall(path='/var/tmp')  # 不写参数,解压到当前目录
>>> tar.close()