• Python基础:Python函数、文件操作、递归


    函数参数

    函数参数包括位置参数,关键字参数,动态参数(*args, **args)三种。

    传参的过程是形式参数的赋值。

    *args传入的参数是元组形式,**args传入的参数是字典形式。

    示例代码如下:(这部分直接看代码实例会更清楚静态参数与动态参数如何混用)

      1 #!/usr/bin/env python
      2 # -*- coding:utf-8 -*-
      3 # def story(**kwargs):
      4 #     return 'Once upon a time,there was a '\
      5 #             '%(job)s called %(name)s.' % kwargs
      6 # print(story(job = 'king',name = 'bolen'))
      7 #
      8 # def power(x,y,*others):
      9 #     if others:
     10 #         print('received redundant parameters:',others)
     11 #     return pow(x,y)
     12 # power(2,3,)
     13 
     14 def interval(start,stop = None,step = 1):
     15     if stop is None:
     16         start,stop=0,start
     17     result = []
     18     i = start
     19     while i < stop:
     20         result.append(i)
     21         i+=step
     22     return  result
     23 
     24 -----------------------shell excute-------------------------------
     25 >>> story(job = 'king',name = 'bolen')
     26 'Once upon a time,there was a king called bolen.'
     27 >>> parms = {'job':'engineer','name':'jack'}
     28 >>> story(**parms)
     29 'Once upon a time,there was a engineer called jack.'
     30 >>> del parms['job']
     31 >>> parms
     32 {'name': 'jack'}
     33 >>> story(job = '小王子',**parms)
     34 'Once upon a time,there was a 小王子 called jack.'
     35 
     36 >>> power(2,3)
     37 8
     38 >>> power(y=3,x=2)
     39 8
     40 >>> parms = (5,)*2
     41 >>> type(parms)
     42 <class 'tuple'>
     43 >>> power(*parms)
     44 3125
     45 >>> parms
     46 (5, 5)
     47 
     48 
     49 >>> interval(10)
     50 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
     51 >>> interval(1,6)
     52 [1, 2, 3, 4, 5]
     53 >>> interval(2,12,3)
     54 [2, 5, 8, 11]
     55 >>> power(*interval(3,7))
     56 received redundant parameters: (5, 6)
     57 81
     58 
    函数参数示例


    变量作用域

    函数内部的变量称为局部变量,全局无法访问局部变量,函数内部正常也无法访问全局变量,除非以如下方式:

    函数内读取全局变量:(慎重引用全局变量,容易出错)

      1 >>> def com(para):
      2 	print(para+globals()['para'])
      3 >>> com('yingying')
      4 yingyingbolen

    函数内声明全局变量:

      1 >>> def ch_global():
      2 	global x
      3 	x +=1
      4 >>> x =  1
      5 >>> ch_global()
      6 >>> x
      7 2


    Python内置函数

    详细介绍请点击:官网内置函数详解

    Python文件操作:open函数和with open(管理上下文)

    open函数用于文件处理。一般步骤是打开文件,然后操作文件。

      1 文件句柄 = open('文件路径','模式')
      句柄是WONDOWS用来标识被应用程序所建立或使用的对象的唯一整数,WINDOWS使用各种各样的句柄标识诸如应用程序实例,窗口,控制,位图,GDI对象等等。
    句柄是一个标识符,是拿来标识对象或者项目的,它就象我们的姓名一样,每个人都会有一个,不同的人的姓名不一样,但是,也可能有一个名字和你一样的人。从数据类型上来看它只是一个16位的无符号整数。应用程序几乎总是通过调用一个WINDOWS函数来获得一个句柄,之后其他的WINDOWS函数就可以使用该句柄,以引用相应的对象。  

      文件句柄在文件I/O中,要从一个文件读取数据,应用程序首先要调用操作系统函数并传送文件名,并选一个到该文件的路径来打开文件。该函数取回一个顺序号,即文件句柄(file handle),该文件句柄对于打开的文件是唯一的识别依据。要从文件中读取一块数据,应用程序需要调用函数ReadFile,并将文件句柄在内存中的地址和要拷贝的字节数传送给操作系统。当完成任务后,再通过调用系统函数来关闭该文件。

    打开后获得该文件句柄,后面通过此文件句柄对文件操作。

    一、打开文件

    打开文件的模式有:

    • r ,只读模式【默认】
    • w,只写模式【不可读;不存在则创建;存在则清空内容;】
    • x, 只写模式【不可读;不存在则创建,存在则报错】
    • a, 追加模式【可读;   不存在则创建;存在则只追加内容;】

    "+" 表示可以同时读写某个文件

    • r+, 读写【可读,可写】
    • w+,写读【可读,可写】
    • x+ ,写读【可读,可写】
    • a+, 写读【可读,可写】

    "b"表示以字节的方式操作

    • rb  或 r+b
    • wb 或 w+b
    • xb 或 w+b
    • ab 或 a+b

    注:以b方式打开时,读取到的内容是字节类型,写入时也需要提供字节类型。

    二、文件操作

      1 class TextIOWrapper(_TextIOBase):
      2     """
      3     Character and line based layer over a BufferedIOBase object, buffer.
      4 
      5     encoding gives the name of the encoding that the stream will be
      6     decoded or encoded with. It defaults to locale.getpreferredencoding(False).
      7 
      8     errors determines the strictness of encoding and decoding (see
      9     help(codecs.Codec) or the documentation for codecs.register) and
     10     defaults to "strict".
     11 
     12     newline controls how line endings are handled. It can be None, '',
     13     '\n', '\r', and '\r\n'.  It works as follows:
     14 
     15     * On input, if newline is None, universal newlines mode is
     16       enabled. Lines in the input can end in '\n', '\r', or '\r\n', and
     17       these are translated into '\n' before being returned to the
     18       caller. If it is '', universal newline mode is enabled, but line
     19       endings are returned to the caller untranslated. If it has any of
     20       the other legal values, input lines are only terminated by the given
     21       string, and the line ending is returned to the caller untranslated.
     22 
     23     * On output, if newline is None, any '\n' characters written are
     24       translated to the system default line separator, os.linesep. If
     25       newline is '' or '\n', no translation takes place. If newline is any
     26       of the other legal values, any '\n' characters written are translated
     27       to the given string.
     28 
     29     If line_buffering is True, a call to flush is implied when a call to
     30     write contains a newline character.
     31     """
     32     def close(self, *args, **kwargs): # real signature unknown
     33         关闭文件
     34         pass
     35 
     36     def fileno(self, *args, **kwargs): # real signature unknown
     37         文件描述符
     38         pass
     39 
     40     def flush(self, *args, **kwargs): # real signature unknown
     41         刷新文件内部缓冲区
     42         pass
     43 
     44     def isatty(self, *args, **kwargs): # real signature unknown
     45         判断文件是否是同意tty设备
     46         pass
     47 
     48     def read(self, *args, **kwargs): # real signature unknown
     49         读取指定字节数据
     50         pass
     51 
     52     def readable(self, *args, **kwargs): # real signature unknown
     53         是否可读
     54         pass
     55 
     56     def readline(self, *args, **kwargs): # real signature unknown
     57         仅读取一行数据
     58         pass
     59 
     60     def seek(self, *args, **kwargs): # real signature unknown
     61         指定文件中指针位置
     62         pass
     63 
     64     def seekable(self, *args, **kwargs): # real signature unknown
     65         指针是否可操作
     66         pass
     67 
     68     def tell(self, *args, **kwargs): # real signature unknown
     69         获取指针位置
     70         pass
     71 
     72     def truncate(self, *args, **kwargs): # real signature unknown
     73         截断数据,仅保留指定之前数据
     74         pass
     75 
     76     def writable(self, *args, **kwargs): # real signature unknown
     77         是否可写
     78         pass
     79 
     80     def write(self, *args, **kwargs): # real signature unknown
     81         写内容
     82         pass
     83 
     84     def __getstate__(self, *args, **kwargs): # real signature unknown
     85         pass
     86 
     87     def __init__(self, *args, **kwargs): # real signature unknown
     88         pass
     89 
     90     @staticmethod # known case of __new__
     91     def __new__(*args, **kwargs): # real signature unknown
     92         """ Create and return a new object.  See help(type) for accurate signature. """
     93         pass
     94 
     95     def __next__(self, *args, **kwargs): # real signature unknown
     96         """ Implement next(self). """
     97         pass
     98 
     99     def __repr__(self, *args, **kwargs): # real signature unknown
    100         """ Return repr(self). """
    101         pass
    102 
    103     buffer = property(lambda self: object(), lambda self, v: None, lambda self: None)  # default
    104 
    105     closed = property(lambda self: object(), lambda self, v: None, lambda self: None)  # default
    106 
    107     encoding = property(lambda self: object(), lambda self, v: None, lambda self: None)  # default
    108 
    109     errors = property(lambda self: object(), lambda self, v: None, lambda self: None)  # default
    110 
    111     line_buffering = property(lambda self: object(), lambda self, v: None, lambda self: None)  # default
    112 
    113     name = property(lambda self: object(), lambda self, v: None, lambda self: None)  # default
    114 
    115     newlines = property(lambda self: object(), lambda self, v: None, lambda self: None)  # default
    116 
    117     _CHUNK_SIZE = property(lambda self: object(), lambda self, v: None, lambda self: None)  # default
    118 
    119     _finalizing = property(lambda self: object(), lambda self, v: None, lambda self: None)  # default
    120 
    121 3.x
    Python3中的文件操作


    三、管理上下文

    由于文件读写时都有可能产生IOError,一旦出错,后面的f.close()就不会调用。所以,为了保证无论是否出错都能正确地关闭文件,我们可以使用try ... finally来实现:

      1 try:
      2     f = open('/path/to/file', 'r')
      3     print(f.read())
      4 finally:
      5     if f:
      6         f.close()
      7 

    但是每次都这么写实在太繁琐,所以,Python引入了with语句来自动帮我们调用close()方法:

      1 with open('/path/to/file', 'r') as f:
      2     print(f.read())
      3 

    这和前面的try ... finally是一样的,但是代码更佳简洁,并且不必调用f.close()方法。

    在Python 2.7 及以后,with又支持同时对多个文件的上下文进行管理,即:

      1 with open('log1') as obj1, open('log2') as obj2:
      2 	pass
      3 
      1 import sys
      2 import json
      3 with open ('c:/Users/zliyong/filo.txt','a+',encoding='utf-8') as f:
      4     #f.write('first line\nsecondline\n3rd line\n 4rd line')
      5     # f.tell()#查看当前指针位置
      6     # f.seek(2)#指定当前指针位置
      7     ret = f.truncate(100) #从指定位置向前截取
      8     print(f.tell())
      9     print(f.read())
     10     for line in f.readlines():
     11         print(line.strip())
    Python3中的文件操作实例

    如果文件很小,read()一次性读取最方便;如果不能确定文件大小,反复调用read(size)比较保险;如果是配置文件,调用readlines()最方便。

    open()函数返回的这种有个read()方法的对象,在Python中统称为file-like Object。除了file外,还可以是内存的字节流,网络流,自定义流等等。file-like Object不要求从特定类继承,只要写个read()方法就行。

    StringIO就是在内存中创建的file-like Object,常用作临时缓冲。

    二进制文件

    前面讲的默认都是读取文本文件,并且是UTF-8编码的文本文件。要读取二进制文件,比如图片、视频等等,用'rb'模式打开文件即可:

      1 >>> f = open('/Users/michael/test.jpg', 'rb')
      2 >>> f.read()
      3 b'\xff\xd8\xff\xe1\x00\x18Exif\x00\x00...' # 十六进制表示的字节
      4 
    字符编码

    要读取非UTF-8编码的文本文件,需要给open()函数传入encoding参数,例如,读取GBK编码的文件:

      1 >>> f = open('/Users/michael/gbk.txt', 'r', encoding='gbk')
      2 >>> f.read()
      3 '测试'
      4 

    遇到有些编码不规范的文件,你可能会遇到UnicodeDecodeError,因为在文本文件中可能夹杂了一些非法编码的字符。遇到这种情况,open()函数还接收一个errors参数,表示如果遇到编码错误后如何处理。最简单的方式是直接忽略:

      1 >>> f = open('/Users/michael/gbk.txt', 'r', encoding='gbk', errors='ignore')

    写文件注意事项:

    可以反复调用f.write来进行写文件,但是一定要记得用f.close来关闭文件。因为操作系统在往磁盘里写文件时,往往不会立即写入磁盘,而是放在内存中缓存起来,待空闲了再慢慢进行写操作,所以只有调用f.close()方法才能保证操作系统文件完整写入到磁盘,否则经常会使文件部分写入磁盘,剩下的丢失了。


    操作文件和目录

    Python中的内置os模块提供了调用系统接口函数的功能,实现简单的系统操作。

      1 >>>import os
      2 >>>os.name()  #获取操作系统名字
      3 'nt'
      4 >>> os.environ #获取操作系统全部的环境变量
      5 >>> os.environ.get('PATH')#获取操作系统中某个环境变量的值
      6 
      7 
      8 

    注意:操作文件和目录的函数一部分放在os模块中,一部分放在os.path模块中。创建、删除目录,路径拼接等可以如下调用:

      1 >>> os.path.abspath('.')
      2 'C:\\Users\\zliyong\\AppData\\Local\\Programs\\Python\\Python35'
      3 >>> os.path.join('Users/zliyong','test.dir') #路径拼接
      4 'Users/zliyong\\test.dir'
      5 >>> os.mkdir('c:/Users/zliyong/test.dir')
      6 >>> os.rmdir('c:/Users/zliyong/test.dir')
      7 >>> os.path.split('c:/Users/zliyong/test.dir')
      8 ('c:/Users/zliyong', 'test.dir')
      9 >>> os.path.splitext('c:/Users/zliyong/test.dir/test.txt')
     10 ('c:/Users/zliyong/test.dir/test', '.txt')
     11 >>> os.rename('c:/Users/zliyong/test.dir','c:/Users/zliyong/pyrename.dir')

    但是复制文件的函数居然在os模块中不存在!原因是复制文件并非由操作系统提供的系统调用。理论上讲,我们通过上一节的读写文件可以完成文件复制,只不过要多写很多代码。

    幸运的是shutil模块提供了copyfile()的函数,你还可以在shutil模块中找到很多实用函数,它们可以看做是os模块的补充。

      1 import shutil
      2 >>> shutil.copyfile('c:/Users/zliyong/pyrename.dir/test.txt','c:/Users/zliyong/pyrename.dir/test2.txt')
      3 'c:/Users/zliyong/pyrename.dir/test2.txt'

    最后看看如何利用Python的特性来过滤文件。比如我们要列出当前目录下的所有目录,只需要一行代码:

      1 >>> [x for x in os.listdir('.') if os.path.isdir(x)]
      2 ['DLLs', 'Doc', 'include', 'Lib', 'libs', 'Scripts', 'tcl', 'Tools']
      3 >>> [x for x in os.listdir('.') if os.path.isfile(x) and os.path.splitext(x)[1]=='.py']
      4 []


    lambda表达式

    lambda表达式又称为匿名函数,适用于某些简单函数的语法糖。如下这个lambda表达式结合列表推导式的例子是很tricky的:

      1 >>> result = [lambda x: x + i for i in range(10)]
      2 >>> print(result[0](10))
      3 19
      4 >>> print(result)
      5 [<function <listcomp>.<lambda> at 0x000001D664C7C7B8>, <function <listcomp>.<lambda> at 0x000001D667100F28>, <function <listcomp>.<lambda> at 0x000001D667105048>, <function <listcomp>.<lambda> at 0x000001D6671050D0>, <function <listcomp>.<lambda> at 0x000001D667105158>, <function <listcomp>.<lambda> at 0x000001D6671051E0>, <function <listcomp>.<lambda> at 0x000001D667105268>, <function <listcomp>.<lambda> at 0x000001D6671052F0>, <function <listcomp>.<lambda> at 0x000001D667105378>, <function <listcomp>.<lambda> at 0x000001D667105400>]

    首先执行range函数,然后生成10个lamda函,当调用result函数时i=9,所以result是一个10个元素都是19的列表。


    递归函数

    简单地说,递归就是自己调用自己。

    例如阶乘就可以用递归来简单的实现。由阶乘的定义可知fact(n) = fact(n-1)*n(n=1时要作特别处理)。用递归函数可以表达如下:

      1 >>> def fact(n):
      2 	if n == 1:
      3 		return 1
      4 	return fact(n-1)*n
      5 
      6 >>> fact(10)
      7 3628800

    最典型的应用就是斐波那契数列:

      1 def func(arg1,arg2,stop):
      2     if arg1 == 0:
      3         print(arg1,'\n',arg2)
      4     arg3 = arg1 + arg2
      5     print(arg3)
      6     if arg3 < stop:
      7         func(arg2,arg3,stop)
      8 
      9 func(1,0,30)

    使用递归函数的优点是逻辑简单清晰,缺点是过深的调用会导致栈溢出。

    针对尾递归优化的语言可以通过尾递归防止栈溢出。尾递归事实上和循环是等价的,没有循环语句的编程语言只能通过尾递归实现循环。

    Python标准的解释器没有针对尾递归做优化,任何递归函数都存在栈溢出的问题。

  • 相关阅读:
    Android 常见adb命令
    下载安装JDK,并且配置java环境变量
    安装黑苹果教程
    创建不死目录、不死文件
    win10下安装centos7双系统
    Hadoop 3.0完全分布式集群搭建方法(CentOS 7+Hadoop 3.2.0)
    Hadoop 2.0完全分布式集群搭建方法(CentOS7+Hadoop 2.7.7)
    启动HBase脚本start-hbase.sh时报Class path contains multiple SLF4J bindings.解决方法
    HQuorumPeer和QuorumPeerMain进程的区别
    Zookeeper集群安装与配置
  • 原文地址:https://www.cnblogs.com/bolenzhang/p/7004423.html
Copyright © 2020-2023  润新知