设为首页 收藏本站
查看: 1698|回复: 0

[经验分享] python 学习笔记day07-python函数高级应用

[复制链接]

尚未签到

发表于 2018-8-16 12:45:10 | 显示全部楼层 |阅读模式
  函数高级应用
  变量作用域
  全局变量
  标识符的作用域是定义为其声明在程序里的可应用范围,也就是变量的可见性
  在一个模块中最高级别的变量有全局作用域
  全局变量的一个特征是除非被删除掉,否则它们的存活到脚本运行结束,且对于所有的函数,他们的值都是可以被访问的
  局部变量
  局部变量只是暂时地存在,仅仅只依赖于定义他们的函数现阶段是否处于活动
  当一个函数调用出现时,某局部变量就进入声明他们的作用域,在那一刻,一个新的局部变量名为那个对象创建了
  一旦函数完成,框架被释放,变量将会离开作用域
  如果局部与全局有相同名称的变量,那么函数运行时,局部变量的名称将会把全局变量名称遮盖住
  >>> x = 4
  >>> def foo():
  ...   x = 10
  ...   print "in foo,x = ",x
  ...
  >>> foo()
  in foo,x =  10
  >>> print "in main,x =",x
  in main,x = 4
  global语句
  >>> x = 10
  >>> def foo():
  ...   global x
  ...   x = 30
  ...
  >>> x
  10
  >>> foo()
  >>> x
  30
  注意事项:列表、字典可变对象,全局变量会被修改。如下所示。不可变对象,全局变量不会修改
  >>> alist = [10]
  >>> def foo():
  ...   alist.append(20)
  ...
  >>> foo()
  >>> alist
  [10, 20]
  >>> def bar(adict):
  ...   adict['name'] = 'bob'
  ...
  >>> bdict = {}
  >>> bar(bdict)
  >>> bdict
  {'name': 'bob'}
  >>> def foobar(astr):
  ...   astr = 'hello'
  ...
  >>> bstr = ''
  >>> foobar(bstr)
  >>> bstr
  ''
  名字空间
  任何时候,总有一个到三个活动的作用域(内建、全局和局部)
  标识符的搜索顺序依次是局部、全局和内建
  提到名字空间,可以想象是否有这个标识符
  提到变量作用域,可以想象是否可以“看见”这个标识符
  函数式编程
  偏函数
  偏函数的概念是将函数式编程的概念和默认参数以及可变参数结合在一起
  一个带有多个参数的函数,如果其中某些参数基本上固定的,那么就可以通过偏函数为这些参数赋默认值
  >>> from operator import add
  >>> from functools import partial
  >>> add10 = partial(add,10)
  >>> print add10(25)
  35
  偏函数实例列举:
  vim -o u2d.py d2u.py
  2 files to edit
  [root@sail qh1]# vim -O u2d.py d2u.py
  2 files to edit
  [root@sail qh1]# cat u2d.py
  #!/usr/bin/env python
  import sys
  def unix2dos(fname,sep='\r\n'):
  dst_name = fname + '.txt'
  with open(fname) as src_fobj:
  with open(dst_name,'w') as dst_fobj:
  for line in src_fobj:
  dst_fobj.write("%s%s" % (line.rstrip('\r\n'),sep))
  if __name__ == '__main__':
  unix2dos(sys.argv[1])
  [root@sail qh1]# cat d2u.py
  #!/usr/bin/env python
  import sys
  import u2d
  from functools import partial
  dos2unix = partial(u2d.unix2dos,seq='\n')
  if __name__ == '__main__':
  dos2unix(sys.argv[1])
  简单GUI类的例子
  编写一个窗口程序,要求如下
  1、窗口程序提供三个按钮
  2、其中两个按钮的前景色均为白色,背景色为蓝色
  3、第三个按钮前景色为红色,背景色为红色
  4、按下第三个按钮后,程序退出
  #!/usr/bin/env python
  import Tkinter
  from functools import partial
  root = Tkinter.tk()
  MyButton = partial(Tkinter.Button,root,fg='white',bg='blue')
  b1 = MyButton(text='Button1')
  b2 = MyButton(text='Button2')
  qb = MyButton(text='quit',command = root.quit)
  b1.pack()
  b2.pack()
  qb.pack()
  Tkinter.mainloop()
  递归函数
  如果函数包含了对其自身的调用,该函数就是递归的
  在操作系统中,查看某一目录内所有文件、修改权限等都是递归的应用
  #!/usr/bin/env python
  def func(num):
  if num == 1:
  return num
  return num * func(num - 1)
  if __name__ == '__main__':
  print func(5)
  print func(6)
  $ mkdir -p demo/{aaa/bbb,ccc}
  $ cp /etc/hosts /home/qihang/demo/
  $ touch /home/qihang/demo/d.txt
  $ touch /home/qihang/demo/aaa/{a1,a2}.txt
  $ touch /home/qihang/demo/aaa/bbb/b.txt
  $ touch /home/qihang/demo/ccc/{c1,c2}.txt
  $ ls -R /home/qihang/demo/
  /home/qihang/demo/:
  ?  aaa  ccc  d.txt  hosts
  /home/qihang/demo/aaa:
  a1.txt  a2.txt  bbb
  /home/qihang/demo/aaa/bbb:
  b.txt
  /home/qihang/demo/ccc:
  c1.txt  c2.txt
  编写程序实现ls -R /home/qihang/demo/的功能
  #!/usr/bin/env python
  import os
  import sys
  def lsdir(folder):
  contents = os.listdir(folder)
  print "%s:\n%s\n" %(folder,contents)
  for item in contents:
  full_path = os.path.join(folder,item)
  if os.path.isdir(full_path):
  lsdir(full_path)
  if __name__ == '__main__':
  lsdir(sys.argv[1])
  os模块有这个递归的函数
  >>> os.walk('/home/qihang/demo/')
  
  >>> list(os.walk('/home/qihang/demo/'))
  [('/home/qihang/demo/', ['aaa', 'ccc'], ['hosts', 'd.txt']), ('/home/qihang/demo/aaa', ['bbb'], ['a1.txt', 'a2.txt']), ('/home/qihang/demo/aaa/bbb', [], ['b.txt']), ('/home/qihang/demo/ccc', [], ['c2.txt', 'c1.txt'])]
  >>> a = os.walk('/home/qihang/demo/')
  >>> a.next()
  ('/home/qihang/demo/', ['aaa', 'ccc'], ['hosts', 'd.txt'])
  >>>
  >>> a.next()
  ('/home/qihang/demo/aaa', ['bbb'], ['a1.txt', 'a2.txt'])
  >>> a.next()
  ('/home/qihang/demo/aaa/bbb', [], ['b.txt'])
  >>> a.next()
  ('/home/qihang/demo/ccc', [], ['c2.txt', 'c1.txt'])
  >>> a.next()
  Traceback (most recent call last):
  File "", line 1, in
  StopIteration
  #!/usr/bin/env python
  import os
  import sys
  def lsdir(folder):
  for path,dirs,files in os.walk(folder):
  print '%s:\n%s\n' % (path,(dirs + files))
  if __name__ == '__main__':
  lsdir(sys.argv[1])
  内部函数
  闭包
  闭包将内部函数自己的代码和作用域以及外部函数的作用结合起来
  闭包的词法变量不属于全局名字空间域或者局部的--而属于其他的名字空间,带着“流浪”的作用域
  闭包对于安装计算,隐藏状态,以及在函数对象和作用域中随意的切换是很有用的
  闭包也是函数,但是它们能携带一些额外的作用域
  闭包实例
  在电子商务平台下,每件商品都有一个计数器说明该商品售出数量,这个计算器就可以通过闭包实现
  >>> def counter(start_at = 0):
  ...   count = [start_at]
  ...   def incr():
  ...     count[0] +=1
  ...     return count[0]
  ...   return incr
  ...
  >>> a = counter()
  >>> print a()
  1
  >>> b = counter(10)
  >>> print b()
  11
  >>> print a()
  2
  >>> print a()
  3
  安装Tkinter模块
  # sudo apt-get install python-tk
  # vim button.py
  #!/usr/bin/env python
  from functools import partial
  import Tkinter
  def say_hi(word):
  def greet():
  print "hello %s!" % word
  return greet
  root = Tkinter.Tk()
  MyButton = partial(Tkinter.Button,root,fg = 'white',bg='blue')
  b1 = MyButton(text='Button1',command = say_hi('world'))
  b2 = MyButton(text='Button2',command = say_hi('tedu'))
  qb = MyButton(text='quit',command = root.quit)
  b1.pack()
  b2.pack()
  qb.pack()
  Tkinter.mainloop()
  装饰器
  装饰器是在函数调用至上的修饰
  这些修饰仅是当声明一个函数或者方法的时候,才会应用的额外调用
  使用装饰器的情形有:
  - 引入日志
  - 增加计时逻辑来检测性能
  - 给函数加入事物的能力
  #!/usr/bin/env python
  import time
  def deco(func):
  def timeit():
  start = time.time()
  res = func()
  end = time.time()
  print "Program cost %5.3f seconds" %(end - start)
  return res
  return timeit
  @deco
  def loop():
  result = []
  for i in range(1,6):
  result.append(i)
  time.sleep(1)
  return result
  if __name__ == '__main__':
  print loop()
  #!/usr/bin/env python
  def color(func):
  def color_font(*argv):
  return "\033[31;1m%s\033[0m" % func(*argv)
  return color_font
  @color
  def say_hi(word):
  return "Hello %s." % word
  @color
  def greet(name):
  return 'Welcome %s!' % name
  if __name__ == '__main__':
  print say_hi('tedu')
  print greet('bob')
  生成器
  定义生成器
  从句法上讲,生成器是一个带yield语句的函数
  一个函数或者子程序只返回一次,但一个生成器能暂停执行并返回一个中间的结果
  yield语句返回一个值给调用者并暂停执行
  当生成器的next()方法被调用的时候,它会准确的从离开地方继续
  >>> def sim_gen():
  ...   yield 'hello'
  ...   yield 100
  ...   yield [10,20]
  ...
  >>> a = sim_gen()
  >>> a
  
  >>> a.next()
  'hello'
  >>> a.next()
  100
  >>> a.next()
  [10, 20]
  >>> a.next()
  Traceback (most recent call last):
  File "", line 1, in
  StopIteration
  >>> a = sim_gen()
  >>> for i in a:
  ...   print i
  ...
  hello
  100
  [10, 20]
  #!/usr/bin/env python
  def blocks(fobj):
  block =[]
  counter = 0
  for line in fobj:
  block.append(line)
  counter +=1
  if counter ==10:
  yield block
  counter = 0
  block =[]
  yield block
  if __name__ == '__main__':
  with open("/etc/passwd") as fobj:
  for lines in blocks(fobj):
  print lines
  生成器特性
  用户可以通过send()将值回送给生成器,还可以在生成器中抛出异常,以及要求生成器退出
  模块
  模块和文件
  什么是模块
  模块支持从逻辑上组织python代码
  当代码量变得相当大的时候,最好把代码分成一些有组织的代码段
  代码片段相互间有一定的练习,可能是一个包含数据成员和方法的类,也可能是一组相关但彼此独立的操作函数
  这些代码段是共享的,所以python允许“调入”一个模块,允许使用其他模块的属性来利用之前的工作成果,实现代码重用
  模块文件
  说模块十按照逻辑来组织python代码的方法,文件是物理层上组织模块的方法
  一个文件被看作是一个独立模块,一个模块也可以被看作是一个文件
  模块的文件名就是模块的名字加上扩展名py
  名称空间
  名称空间就是一个从名称到对象的关系映射集合
  给定一个模块名之后,只可能有一个模块被导入到python解释器中,所以不同模块间不会出现名称交叉现象
  每个模块都定义了它自己的唯一的名称空间
  echo 'x=10' > foo.py
  echo 'x="hello"' > bar.py
  >>> import foo
  >>> import bar
  >>> foo.x
  10
  >>> bar.x
  'hello'
  导入模块
  搜索路径
  模块的导入需要一个叫做“路径搜索”的过程
  python在文件系统“预定义区域”中查找要调用的模块
  搜索路径在sys.path中定义
  >>> import sys
  >>> print sys.path
  ['', '/usr/lib/python2.7', '/usr/lib/python2.7/plat-i386-linux-gnu', '/usr/lib/python2.7/lib-tk', '/usr/lib/python2.7/lib-old', '/usr/lib/python2.7/lib-dynload', '/usr/local/lib/python2.7/dist-packages', '/usr/lib/python2.7/dist-packages', '/usr/lib/python2.7/dist-packages/PILcompat', '/usr/lib/python2.7/dist-packages/ubuntu-sso-client']
  模块导入方法
  使用import导入模块
  可以在一行导入多个模块,但是可读性会下降
  可以只导入模块的某些属性
  导入模块时,可以为模块取别名
  >>> import time,os,sys
  >>> from random import choice
  >>> import cPickle as P
  避免模块不存在导入失败的小方法
  >>> try:
  ...   import cPickle as p
  ... except ImportError:
  ...   import pickle as p
  ...
  导入和加载
  当导入模块时,模块的顶层代码会被执行
  一个模块不管被导入(import)多少次,只会被加载(load)一次
  $ echo -e "hi = 'hello'\nprint hi" > foo.py
  >>> import foo  #第一次导入,执行print语句
  hello
  >>> import foo #再次导入,print语句不再执行
  从zip文件中导入
  在2.3版中,python加入了从ZIP归档文件导入模块的功能
  如果搜索路径中存在一个包含python模块(.py、.pyc、或.pyo文件)的.zip文件,导入时会把ZIP文件当作目录处理
  #导入sys模块,在搜索路径中加入相应的zip文件
  >>> import sys
  >>> sys.path.append('/root/pymodule.zip')
  >>> import foo #导入pymodule.zip压缩文件中的foo模块
  包
  目录机构
  包是一个有层次的目录结构,为平坦的名称空间加入有层次的组织结构
  允许程序员把有联系的模块组合到一起
  包目录下必须有一个__init__.py文件
  phone/
  __init__.py
  common_util.py
  voicedate/
  __init__.py
  post.py
  绝对导入
  包的使用越来越广泛,很多情况下导入子包会导致和真正的标准库模块发生冲突
  因此,所有的导入现在都被认为是绝对的,也就是说这些名字必须通过python路径(sys.path或PYTHONPATH)来访问
  相对导入
  绝对导入特性使得程序员失去了import的自由,为此出现了相对导入
  因为import语句总是绝对导入的,所以相对导入只应用与from-import语句
  内建模块
  hashlibs模块
  hashlib用来替换md5和sha模块,并使他们的API一致,专门提供hash算法
  包括md5,sha1,sha224,sha256,sha384,sha512,使用非常简单、方便
  >>> import hashlib
  >>> m = hashlib.md5()
  >>> m.update("hello world!")
  >>> m.hexdigest()
  'fc3ff98e8c6a0d3087d515c0473f8677'
  >>> import hashlib
  >>> m = hashlib.md5()
  >>> with open('/root/qh/py/ex6.py') as fobj:
  ...   while True:
  ...     date = fobj.read(4096)
  ...     if not date:
  ...       break
  ...     m.update(date)
  ...
  >>> m.hexdigest()
  '7daba44373fcb6c3aa8dfb25df1cf71a'
  tarfile模块
  tarfile模块允许创建、访问tar文件
  同时支持gzip、bzip2格式
  >>> import tarfile
  >>> tar = tarfile.open('/home/qihang/demo.tar.gz','w:gz') #创建tar文件,
  >>> tar.add('demo') #向tar文件中添加要打包的文件
  >>> tar.close()
  备份程序
  编写一个备份程序
  1、需要支持完全和增量备份
  2、周一执行完全备份
  3、其他时间执行增量备份
  4、备份文件需要打包为tar文件并使用gzip格式压缩


运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-552688-1-1.html 上篇帖子: python用print输出中文字符 下篇帖子: 保留日志文件最新的多少行(python)
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表