Python开发3——字符编码、文件处理、函数

字符编码

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:  #(可以同时打开多个文件)结束操作文件后,会自动关闭
      #操作文件

f = open('a.txt', 'w', encoding='utf-8')
f.write('哈哈哈哈哈!')
f.close()

with open('a.txt', 'r',encoding='utf-8') as f1,open('b.txt', 'w', encoding='utf-8') as f2:
    #文件操作
    content = f1.read()
    f2.write(content)

2、检测文件是否可读:

#fileObject.readable()

f = open('a.txt', 'a+', encoding='utf-8')
print(f.readable())
f.close()

3、检测文件是否可写:

#fileObject.writable()

f = open('a.txt', 'r+',encoding='utf-8')
print(f.writable())
f.close()

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

#fileObject.closed

f = open('a.txt', 'r+',encoding='utf-8')
f.close()
print(f.closed)

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

  #fileObject.isatty()

6、关闭文件

#fileObject.close()

f.write('啊啊啊')
print(f.read())
f.close()

7、读文件

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

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

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

#fileObject.readline()

f = open('a.txt', 'r+', encoding='utf-8')
print(f.readline())
f.close()

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

#fileObject.readlines()

f = open('a.txt', 'r+',encoding='utf-8') print(f.readlines()) f.close()

8、写文件

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

#fileObject.write( [ str ])
	#str:要写入文件的字符串

f = open('a.txt', 'r+',encoding='utf-8')
print(f.write('我就是我啊哈哈'))
f.seek(0)
print(f.read())
f.close()

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

#fileObject.writelines( [ str ])
	#str:要写入文件的字符串序列

	f = open('a.txt', 'r+',encoding='utf-8')
print(f.writelines('我就是我\n啊哈哈ha'))
f.seek(0)
print(f.read())
f.close()

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

#fileObject.seek(offset[, whence])
	#offset:偏移量,即需要移动的字节数
	#whence:可选,默认值为 0。0:从文件开头开始算起,1:从当前位置开始算起,2:从文件末尾算起(1,2模式只允许在二进制b模式下使用)

f = open('a.txt', 'r+',encoding='utf-8')
f.writelines('我就是我\n啊哈哈ha')
f.seek(3)
print(f.tell())
print(f.read())
f.close()

10、返回文件当前位置:

#fileObject.tell()

f = open('a.txt', 'br+')
f.seek(-1,2)
print(f.tell())
print(f.read())
f.close()

11、截断文件

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

12、刷新缓冲区

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

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

  #fileObject.fileno()

函数

一、函数的分类

1、内置函数:

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

2、自定义函数:

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

二、定义函数

1、定义函数的语法

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

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

2、定义函数的三种形式

①无参数函数

②有参函数

③空函数:  

#在一开始思考代码架构时,可以先把扩展功能写下来,后期完善
def insert(): """插入功能""" pass def select(): """查询功能""" pass

注:三元表达式

x=10
y=2
# if x > y:
#     print(x)
# else:
#     print(y)
#

 res=x if x > y else y print(res)

二、函数调用

三、参数传递

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 传不可变对象实例:

def ChangeInt( a ):
    a = 10

b = 2
ChangeInt(b)
print( b ) # 结果是 2

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

  ②传可变对象实例:

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

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

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

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

四、函数的参数

1、位置参数

def foo(x,y,z):#位置形参:必须被传值的参数
    print(x,y,z)

foo(1,2,3) #位置实参:与形参一一对应

2、关键字参数

def foo(x,y,z):
    print(x,y,z)

foo(z=3,x=1,y=2)

#关键字参数需要注意的问题:
# 1:关键字实参必须在位置实参后面
# 2: 不能重复对一个形参传值

# foo(1,z=3,y=2) #正确
# foo(x=1,2,z=3) #错误
# foo(1,x=1,y=2,z=3)#错误	

3、默认参数

def register(name,age,sex='male'): #形参:默认参数
    print(name,age,sex)

register('asb',age=40)
register('a1sb',39)

register('钢蛋',20,'female')
register('钢蛋',sex='female',age=19)

#默认参数需要注意的问题:
#	一:默认参数必须跟在非默认参数后
# def register(sex='male',name,age): #在定义阶段就会报错
#     print(name,age,sex)

#	二:默认参数在定义阶段就已经赋值了,而且只在定义阶段赋值一次
# a=100000000
# def foo(x,y=a):	
#     print(x,y)
# a=0		#a在函数外的指向变化,对函数中的y值无影响
# foo(1)

#三:默认参数的值通常定义成不可变类型

4、可变长参数

①*args:

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

def foo(x,y,*args): 
    print(x,y)
    print(args)
foo(1,2,*[3,4,5]) foo(1,2,3,4,5)  

输出:

1 2
(3, 4, 5)

1 2 (3, 4, 5)

②**kwargs:

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

def foo(name,age,**kwargs):
    print(name,age)
  for k in kwargs.keys():
    print(kwargs[k]) foo('egon',18,**{'sex':'male','height':'185'})
#foo('egon',18,sex='male',height='185')
foo('egon',18,sex='male')

输出:

egon 18
male
185
egon 18
male

5、命名关键字参数

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

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

注:

  传值顺序:位置参数、默认参数、*args、命名关键字参数、**kwargs

 

五、匿名函数

 

posted @ 2017-05-19 15:27  下一步之外  阅读(155)  评论(0)    收藏  举报