python_day3

一.字符编码

1、字符编码的发展史

  阶段一:ASCII

      一个Bytes代表一个字符(英文字符/键盘上的所有其他字符),1Bytes=8bit,8bit可以表示256(2**8)个字符。

  阶段二:GBK

      为了满足中文,中国人定制了GBK,2Bytes代表一个字符。

  阶段三:Unicode(万国码)

      Unicode编码系统为表达任意语言的任意字符而设计,规定所有的字符和符号最少由 16 位来表示(2个字节),即:2 **16 = 65536

  阶段四:UTF-8

      对Unicode编码的压缩和优化,ascii码中的内容用1个字节保存、欧洲的字符用2个字节保存,东亚的字符用3个字节保存。

注:

  Unicode:简单粗暴,所有字符都是2Bytes。

      优点:字符->数字的转换速度快

      缺点:占用空间大

  utf-8:精准,对不同的字符用不同的长度表示

      优点:节省空间

      缺点:字符->数字的转换速度慢,因为每次都需要计算出字符需要多长的Bytes才能够准确表示

  内存中使用的编码是unicode:

      用空间换时间(程序都需要加载到内存才能运行,因而内存应该是尽可能的保证快)
  硬盘中或者网络传输用utf-8:

      网络I/O延迟或磁盘I/O延迟要远大与utf-8的转换延迟,而且I/O应该是尽可能地节省带宽,保证数据传输的稳定性。

2、文本编辑器存取文件的原理(nodepad++,pycharm,word)

    打开编辑器就启动了 一个进程,是在内存中的,所以在编辑器编写的内容也都是存放于内存中的,断电后数据丢失,因而需要保存到硬盘上。

  点击保存按钮,就从内存中把数据刷到了硬盘上。在这一点上,我们编写一个py文件(没有执行),跟编写其他文件没有任何区别,都只是在编写一堆字符而已。

    无论是何种编辑器,要防止文件出现乱码,核心法则就是,文件以什么编码保存的,就以什么编码方式打开。

3、Python解释器执行py文件的原理 (python test.py)

  阶段一:python解释器启动,此时就相当于启动了一个文本编辑器

  阶段二:python解释器相当于文本编辑器,去打开test.py文件,从硬盘上将test.py的文件内容读入到内存中

  阶段三:python解释器解释执行刚刚加载到内存中test.py的代码

注:

  (1)文件编码:# -*- coding:utf-8 -*-(在py文件中加此注释:告诉python解释器,用什么编码来执行源代码,并防止用py2时出错)

  (2)Python解释器编码:(py3:utf-8;py2:ascii)

  (3)#!/usr/bin/python(在py文件中加此注释:防止脚本在Linux上使用)

    ①必须是文件的第一行
    ②#!开头的,说明是脚本
    ③/path/to/script/interpreter是脚本解释器的全路径名

    ④有时不太清楚脚本解释器的具体全路径名;或者开发环境与运行环境的安装路径不同。为了保证兼容性,也可以写作:
      #!/usr/bin/env python3
                这样运行时会自动搜索脚本解释器的绝对路径

4、python2和python3的一些不同

  (1)python2中默认使用ascii,python3中默认使用utf-8

  (2)Python2中,str就是编码后的结果bytes,str=bytes,所以s只能decode。

  (3)python3中的字符串与python2中的u'字符串',都是unicode,只能encode,所以无论如何打印都不会乱码,因为可以理解为从内存打印到内存,即内存->内存,unicode->unicode。

  (4)python3中,str是unicode,当程序执行时,无需加u,str也会被以unicode形式保存新的内存空间中,str可以直接encode成任意编码格式,s.encode('utf-8'),s.encode('gbk')。

#unicode(str)-----encode---->utf-8(bytes)
#utf-8(bytes)-----decode---->unicode

  (5)在windows终端编码为gbk,linux是UTF-8。

二.文件处理

文件处理

一、文件处理流程

  1、打开文件,得到文件句柄并赋值给一个变量

  2、通过句柄对文件进行操作

  3、关闭文件

二、文件对象的方法

1、打开文件

①open(file, mode='r', encoding=None),结束操作文件后,需使用close(file)关闭文件

    file:文件的相对或绝对路径

    mode:文件打开模式

    encoding:编码方式

②with open(file1, mode='r',encoding=None) as f1,open(file2, mode='r', encoding=None) as f2:  #(可以同时打开多个文件)结束操作文件后,会自动关闭
      #操作文件

1 f = open('a.txt', 'w', encoding='utf-8')
2 f.write('哈哈哈哈哈!')
3 f.close()
4  
5 with open('a.txt', 'r',encoding='utf-8') as f1,open('b.txt', 'w', encoding='utf-8') as f2:
6     #文件操作
7     content = f1.read()
8     f2.write(content)
View Code

 

2、检测文件是否可读:

1 #fileObject.readable()
2  
3 f = open('a.txt', 'a+', encoding='utf-8')
4 print(f.readable())
5 f.close()
View Code

3、检测文件是否可写:

1 #fileObject.writable()
2  
3 f = open('a.txt', 'r+',encoding='utf-8')
4 print(f.writable())
5 f.close()
View Code

4、检测文件是否已关闭:

1 #fileObject.closed
2  
3 f = open('a.txt', 'r+',encoding='utf-8')
4 f.close()
5 print(f.closed)
View Code

5、检测文件是否连接到一个终端设备:

  #fileObject.isatty()

6、关闭文件

1 #fileObject.close()
2  
3 f.write('啊啊啊')
4 print(f.read())
5 f.close()
View Code

7、读文件

①从文件中读取指定字符数,不加参数默认读取全文:

1 #fileObject.read(size)
2     #size:从文件中读取的字符数
3 f = open('a.txt', 'r+', encoding='utf-8')
4 print(f.read(3))
5 f.close()
View Code

②读取整行,包括 " " 字符:

1 #fileObject.readline()
2  
3 f = open('a.txt', 'r+', encoding='utf-8')
4 print(f.readline())
5 f.close()
View Code

③读取所有行并返回列表:

1 #fileObject.readlines()<br><br>f = open('a.txt', 'r+',encoding='utf-8')
2 print(f.readlines())
3 f.close()
View Code

8、写文件

①将字符串写入文件,返回写入的字符数

1 fileObject.write( [ str ])
2     #str:要写入文件的字符串
3  
4 f = open('a.txt', 'r+',encoding='utf-8')
5 print(f.write('我就是我啊哈哈'))
6 f.seek(0)
7 print(f.read())
8 f.close()
View Code

②向文件中写入一序列的字符串,换行需要制定换行符

1 #fileObject.writelines( [ str ])
2     #str:要写入文件的字符串序列
3  
4     f = open('a.txt', 'r+',encoding='utf-8')
5 print(f.writelines('我就是我
啊哈哈ha'))
6 f.seek(0)
7 print(f.read())
8 f.close()
View Code

9、移动文件指针到指定位置:

 1 #fileObject.seek(offset[, whence])
 2     #offset:偏移量,即需要移动的字节数
 3     #whence:可选,默认值为 00:从文件开头开始算起,1:从当前位置开始算起,2:从文件末尾算起(1,2模式只允许在二进制b模式下使用)
 4  
 5 f = open('a.txt', 'r+',encoding='utf-8')
 6 f.writelines('我就是我
啊哈哈ha')
 7 f.seek(3)
 8 print(f.tell())
 9 print(f.read())
10 f.close()
View Code

10、返回文件当前位置:

1 #fileObject.tell()
2  
3 f = open('a.txt', 'br+')
4 f.seek(-1,2)
5 print(f.tell())
6 print(f.read())
7 f.close()
View Code

11、截断文件

1 #fileObject.truncate( [ size ])
2     '''
3     从文件的首行首字符开始截取,截取文件为size个字节;无size表示从当前位置起截取;
4     截取之后size后面的所有字符被删除。其中win下的换行代表2个字符大小。
5     '''
6 f = open('a.txt', 'r+',encoding='utf-8')
7 f.truncate(15)
8 print(f.read())
9 f.close()
View Code

12、刷新缓冲区

1 #fileObject.flush()
2     #即将缓冲区中的数据立刻写入文件,同时清空缓冲区
3     #一般情况,文件关闭后会自动刷新缓冲区,但有时你需要在关闭前刷新它,这时就可以使用 flush() 方法
View Code

13、返回一个整型的文件描述符,可用于底层操作系统的 I/O 操作

  #fileObject.fileno()

14.上下文管理with语句

1 with open("/tmp /foo.txt") as file:
2     data = file.read()
View Code

with的基本思想是with所求值的对象必须有一个__enter__()方法,一个__exit__()方法。紧跟with后面的语句被求值后,返回对象的__enter__()方法被调用,这个方法的返回值将被赋值给as后面的变量。当with后面的代码块全部被执行完之后,将调用前面返回对象的__exit__()方法。

15.补充

模拟   tail -f access.log

 1 #!/usr/bin/env python
 2 # -*- coding:utf-8 -*-
 3 
 4 # tail -f access.log
 5 import time
 6 with open('access.log','r',encoding='utf-8') as f:
 7     f.seek(0,2)
 8     while True:
 9         line=f.readline().strip()
10         if line:
11             print('新增一行日志',line)
12         time.sleep(0.5)
View Code

函数

一、函数的分类

1、内置函数:

  python本身自己定义的函数,可直接调用。

2、自定义函数:

  自己根据需求,按照函数定义方法去自定函数。

二、定义函数

1、定义函数的语法

  Python 定义函数使用 def 关键字,一般格式如下:

    def 函数名(参数列表):
      函数体

2、定义函数的三种形式

①无参数函数

②有参函数

③空函数:  

1 #在一开始思考代码架构时,可以先把扩展功能写下来,后期完善<br>def insert():
2     """插入功能"""
3     pass
4 def select():
5     """查询功能"""
6     pass
View Code

注:三元表达式

1 x=10
2 y=2
3 # if x > y:
4 #     print(x)
5 # else:
6 #     print(y)
7 #
8  
9  res=x if x > y else y print(res)
View Code

二、函数调用

三、参数传递

1、在 python 中,类型属于对象,变量是没有类型的:

    a=[1,2,3]
    a="Runoob"

  以上代码中,[1,2,3] 是 List 类型,"Runoob" 是 String 类型,而变量 a 是没有类型,它仅仅是一个对象的引用(一个指针)。

2、可更改(mutable)与不可更改(immutable)对象

    在 python 中,strings, tuples, 和 numbers 是不可更改的对象,而 list,dict 等则是可以修改的对象。

  ①不可变类型:

      变量赋值 a=5 后再赋值 a=10,这里实际是新生成一个 int 值对象 10,再让 a 指向它,而 5 被丢弃,不是改变a的值,相当于新生成了a。

  ②可变类型:

      变量赋值 la=[1,2,3,4] 后再赋值 la[2]=5 则是将 list la 的第三个元素值更改,本身la没有动,只是其内部的一部分值被修改了。

3、python 函数的参数传递

    python 中一切都是对象,严格意义我们不能说值传递还是引用传递,我们应该说传不可变对象和传可变对象

  ①不可变类型:

      类似 c++ 的值传递,如 整数、字符串、元组。如fun(a),传递的只是a的值,没有影响a对象本身。
  ②可变类型:

      类似 c++ 的引用传递,如 列表,字典。如 fun(la),则是将 la 真正的传过去,修改后fun外部的la也会受影响。

4、python参数传递实例

  ①python 传不可变对象实例:

1 def ChangeInt( a ):
2     a = 10
3  
4 b = 2
5 ChangeInt(b)
6 print( b ) # 结果是 2
View Code

实例中有 int 对象 2,指向它的变量是 b,在传递给 ChangeInt 函数时,按传值的方式复制了变量 b,a 和 b 都指向了同一个 Int 对象,在 a=10 时,则新生成一个 int 值对象 10,并让 a 指向它。

  ②传可变对象实例:

    可变对象在函数里修改了参数,那么在调用这个函数的函数里,原始的参数也被改变了。例如:

 1 def changeme( mylist ):
 2    '''修改传入的列表'''
 3    mylist.append([1,2,3,4]);
 4    print ("函数内取值: ", mylist)
 5    return
 6   
 7 # 调用changeme函数
 8 mylist = [10,20,30];
 9 changeme( mylist );
10 print ("函数外取值: ", mylist)
View Code

传入函数的和在末尾添加新内容的对象用的是同一个引用。故输出结果如下:

1 函数内取值:  [10, 20, 30, [1, 2, 3, 4]]
2 函数外取值:  [10, 20, 30, [1, 2, 3, 4]]
View Code

四、函数的参数

1、位置参数

1 def foo(x,y,z):#位置形参:必须被传值的参数
2     print(x,y,z)
3  
4 foo(1,2,3) #位置实参:与形参一一对应
View Code

2、关键字参数

 1 def foo(x,y,z):
 2     print(x,y,z)
 3  
 4 foo(z=3,x=1,y=2)
 5  
 6 #关键字参数需要注意的问题:
 7 # 1:关键字实参必须在位置实参后面
 8 # 2: 不能重复对一个形参传值
 9  
10 # foo(1,z=3,y=2) #正确
11 # foo(x=1,2,z=3) #错误
12 # foo(1,x=1,y=2,z=3)#错误 
View Code

3、默认参数

 1 def register(name,age,sex='male'): #形参:默认参数
 2     print(name,age,sex)
 3  
 4 register('asb',age=40)
 5 register('a1sb',39)
 6  
 7 register('钢蛋',20,'female')
 8 register('钢蛋',sex='female',age=19)
 9  
10 #默认参数需要注意的问题:
11 #   一:默认参数必须跟在非默认参数后
12 # def register(sex='male',name,age): #在定义阶段就会报错
13 #     print(name,age,sex)
14  
15 #   二:默认参数在定义阶段就已经赋值了,而且只在定义阶段赋值一次
16 # a=100000000
17 # def foo(x,y=a):  
18 #     print(x,y)
19 # a=0       #a在函数外的指向变化,对函数中的y值无影响
20 # foo(1)
21  
22 #三:默认参数的值通常定义成不可变类型
View Code

4、可变长参数

①*args:

*会把溢出的按位置定义的实参都接收,以元组的形式赋值给args。

1 def foo(x,y,*args):
2     print(x,y)
3     print(args)<br>
4 foo(1,2,*[3,4,5])
5 foo(1,2,3,4,5)  
View Code

输出:

1 1 2
2 (3, 4, 5)<br><br>1 2
3 (3, 4, 5)
View Code

②**kwargs:

    **会把溢出的按关键字定义的实参都接收,以字典的形式赋值给kwargs

1 def foo(name,age,**kwargs):
2     print(name,age)<br>  for k in kwargs.keys():<br>    print(kwargs[k])
3  
4 foo('egon',18,**{'sex':'male','height':'185'})
5 #foo('egon',18,sex='male',height='185')
6 foo('egon',18,sex='male')
View Code

输出:

1 egon 18
2 male
3 185
4 egon 18
5 male
View Code

5、命名关键字参数

  如下,*后定义的命名关键字参数必须被传值,且必须以关键字实参的形式传值

1 def foo(name,age,*,sex='male',height):
2     print(name,age)
3     print(sex)
4     print(height)
5 #*后定义的参数为命名关键字参数,这类参数,必须被传值,而且必须以关键字实参的形式去传值
6 foo('egon',17,height='185')
View Code

注:

五、匿名函数


 
原文地址:https://www.cnblogs.com/you0329/p/6875839.html