Day02:数据类型、字符编码、文件处理

 

一.基础数据类型与其内置方法

1. int基本使用:int(3.1)

  • 用途:记录年龄,职级等
  • 只能将包含纯数字的字符串类型转换成整形
  • 特点:1.存一个值。 2.不可变

2.float基本使用 float(3.1)

  • 用途:记录身高,薪资等
  • 特点:1.存一个值。 2.不可变

了解知识点:

十进制转二进制:除2取余法

  print(bin(8))

十进制转八进制:除2取余法

  print(oct(101))

十进制转十六进制:除2取余法

  print(hex(16))

 3.str字符串基本使用

用途:记录的是描述性质的状态,比如名字,爱好,家庭住址

定义方式:在单引号,双引号,三引号内包含的一串字符

  msg="hello 'world'"

特点:1.存一个值 2.有序 3.不可变

可以将任意数据类型都转成字符串类型

  res1=str(1)

  res2=str(1.2)

  res3=str([1,2,3])

  print(type(res1),type(res2),type(res3))

str的常用操作+内置方法:

优先掌握的操作:

1).索引:(正向取+反向取):只能取,不能改值

msg="hello world"

print(msg[1]) #返回e

print(msg[5]) #返回空格

print(msg[-1]) #返回d

msg[1]='aaa' #会报错,无法改值

2).切片:从一个大字符串中切除一个子字符串(顾头不顾尾,步长:不指定默认为1,可以为负值)

msg="hello world"

print(msg[1:3])  # el

print(msg[1:])  # ello world

print(msg[6:11:2]) # world  #wrd

print(msg[-1:-6:-1])  # dlrow

print(msg[::-1]) #dlrow olleh

3).长度len:取字符串长度

msg="hello world"

print(len(msg)) #长度是11,索引最大到10

4).成员运算:in, not in

5).移除空白:strip

msg="     hello world   "

res=msg.strip()

print(res) #hello world  默认去除字符串两边的空格,中间的不会去除

msg="*****hello world******"

res=msg.strip('*')

print(res) #hello world  去除字符串两边的*,中间的不会去除

msg="*/** *hello*world*@*"

res=msg.strip(*)

print(msg.strip('*/ @')) #hello world 去除字符串两边的特殊字符,中间的不会去除

name=input('>>>: ').strip()

 6).切分split:把一个字符串按照某种分隔符切成一个列表

  info='root:x:0:0:admin:user:/root:/bin/bash'

  res=info.spit(':')

  print(res,type(res))

  print(res[0])

cmd='get a.txt 33333'

res=cmd.split(' ',maxsplit=1)

print(res)

info='root:x:0:0:admin:user:/root:/bin/bash'

res=info.split(':') #把字符串切成列表

print(res,type(res))

info1=':'.join(res)  #‘root'+':'+'x'+':'+'0' #把列表又转换成了字符串,列表中的元素为字符串

print(info1)

 

l=['andy',123,'mail'] #列表中含数字的话用join会报错

s1=':'.join(l)

print(s1,type(s1)) #会报错

7).循环

while循环:依赖索引,适用于指定循环次数,做重复的事

msg='hello world'

i=0

while i < len(msg):

  print(msg[i])

  i+=1

for循环:不依赖于索引, 通常用来取值

msg='hello world'

for item in msg:

  print(item)

 补充知识:

else的子代码块会在循环结束后并没有被break打断的情况下执行

#while+else:

n=1

while n<=3:

  n+=1

else: #这样可以知道循环结束了

  print('run......')

#for+else:

for i in [1,2,3,4]:

  if i == 4:

    break #退出循环,不进入else逻辑

  print(i)

else:

  print('run...')

 

name=input('username>>: ').strip()

pwd=input('passwd>>: ').strip()

待补充

 

for i in range(0,5,2):  #0  2  4  

  print(i)

names=['andy','tom','alex','lily','rocky']

for i in range(0,len(names)):  # i=0

  print(i,names[i])

python3中优化了range的内存使用,不会直接返回range中的数据

需要掌握的操作:

1).strip(去两边),   lstrip(去左),       rstrip(去右)

2).lower,upper

3).startswith, endswith

print('alex is sb'.startswith('al'))

print('alex is sb'.startswith('sb'))

4).format的三种玩法

print('my name is %s  . my age is %s' %('andy',18))

 

print('my name is {name}  . my age is {age}'.format(age=18,name='andy'))

print('my name is {}  . my age is {}'.format('andy',18))

print('my name is {0}{0}{0} my age is {1}'.format(‘andy’,18))

5).split, rsplit

cmd='get|a.txt|3333'
print(cmd.split('|',1))
print(cmd.rsplit('|',1))

6).join

7).replace

msg='my name is andy,andy say hello'

print(msg.replace('andy'),'haha',1)

print (msg)

8).isdigit:只有在字符串中包含的是纯数字才为True

print('10222'.isdigit())

age_of_db=50

age_of_inp=input('>>>: ').strip()

if age_of_inp.isdigt():

if age_of_inp > age_of_db:

  print('too big')

elif age_of_inp < age_of_db:

  print('too small')

else:

  print('you got it')

else:

  print('必须输入数字')

其他操作(了解即可)

1).find, rfind, index, rindex, count

msg='my namej is andy, andy is nb'

print(msg.find('andy'),1,3)

print(msg.index('andy'),1,3)

print(msg.rfind('andy'))

print(msg.rindex('andy'))

print(msg.count('andy'))

2).center, ljust, rjust, zfill

print('andy'.center(50.'*'))

print('andy'.ljust(50.'='))

print('andy'.rjust(50.'0'))

print('andy'.zfill(50)) #zero fill, 同上

3).expandtabs

print('aaabbb',end='') #去除print默认自带的换行符

print('cccc',end='') #去除print默认自带的换行符

print('aaa\tbbb'.expandtabs(tabsize=3))

4).captalize,swapcase,title

print('my name is andy'.captalize())

print('AnDy'.swapcase())

print('my name is andy'.title())

5).is数字系列

6).is其他

print('asdalkjsd1'.isalpha())  #必须包含权威字母

print('asdalkjsd1'.isalnum())  #必须包含权威字母或数字

print('A Is  Asss'.istitle())  #

print('A Is  Asss'.upper())  #

 

num1=b'4' #bytes

num2=u'4' #unicode, python3中无需加u就是unicode

num3='壹' #中文数字

num='Ⅳ'   #罗马数字

#isdigit: butes, unicode, 常用,但无法识别中文和罗马数字

print(num1.isdigit()) # True

print(num2.isdigit()) # True

print(num3.isdigit()) # False

print(num4.isdigit()) # False

#isdecimal:unicode

#isnumberic:unicode, 中文,罗马 #仅财务相关软件才会用到

 4.列表

用途:存放多个值,记录多个爱好,多个人名

定义方式:在[ ]内用逗号分隔开多个任意类型的值

l=[1,'aa',3.1,[1,2]]

特点:1.存多个值  2. 有序  3. 列表可变:指的列表内索引对应的内存地址可以改变

list类型转换的工作原理:

1.先造一个空列表

2.类似调用一个for循环,从items里取出一个值放入空列表中,循环往复直到取干净为止

 常用操作+内置方法:

1).索引:(正向取+反向取:可以取值,也可以改值

2).切片:从一个大列表中切出一个子列表(顾头不顾尾,步长)

3).长度len

4).成员运算in和not in

5).追加与插入

l=['a','b','c','d']

l.append('aaa')

l.insert(1,'B')

6).删除 #单纯的删除,没有返回值

l=['a','b','andy','d']

l.remove('andy') # remove仅为列表独有的删除

del l[2] # 非字符串独有的删除,是一种通用的删除方式

print(l)

# 从列表中拿走一个值:

1. 删除一个值

2. 将该元素当作返回值返回

res=l.pop(1)

7).循环

l=['a','b','andy','d']

for itrm in l:

  print (item)

 需要掌握的操作:

l1=[1,2,2.3,'a','a','b','a']

print (l1.count('a'))

l2=[4,5,6]

l1.extend(l2)

print(l1)

nums=[9,2,-2,2,34,100]

nums.reverse()

print(nums)

nums.sort()

l1.sort() #会报错,数字无法和字符串类型比较大小

print(nums)

5.元组基本使用

用途:不可变的列表

定义方式:()内用逗号分隔开多个任意类型的元素

特点:1.多个值  2.有序  3.元组不可变:指的是元组内索引对应的内存地址不变

t=('a',1,3.3)

t1=tuple('hello') #任意可以被for循环的数据类型都可以被tuple转成元组

常用操作+内置方法

优先掌握的操作:

同字符串,索引只能取值

需要掌握的做操:

t=('a','b','a','a')

t.index('c')

6.字典基本使用

用途:存多个种类不同的值

定义方式:在{ }内用逗号分隔开多个元素,每一个元素都是key:value的形式,key应该对value有描述性的功能。

特点:

注意:value可以是任意类型,而key必须是不可变类型

即字典的key可以是int, float, tuple, str, 通常是字符串类型

常用操作+内置方法:

d={'name':'andy','age':'18'}

print(id(d))

d['name']='tom'

print(id(d))

成员运算,判断的是key

删除:pop删除key对应的元素,并返回value值

d={'name':'andy','age':'18'}

print(d.keys())

print(d.values())

print(d.items())

get取值:适用于key不存在的情况

d={'name':'andy','age':'18'}

res1=d.get('sex',Value is None)

print(res1)

res2=d,popitem() #随机删除

d.update({'x':1,'name':ANDY}) #老字典d没有的则添加,有的则修改

d.setdefault('name','') #当key存在时,不修改值,会返回key对应的原value

d.setdefault('sex','mail') #当key不存在时,则新增了一个元素‘sex’:'male'

 

items=('name','age','sex')

dic=d.fromkeys(items,None) #快速创建字典,返回 {‘name’:None,‘age’:None,‘sex’:None}

 

二.字符编码

 三个重要的阶段:

阶段一:现代计算机起源于美国,最早诞生也是基于英文考虑的ASCII
  ASCII:一个Bytes代表一个字符(英文字符/键盘上的所有其他字符),1Bytes=8bit,8bit可以表示0-2**8-1种变化,即可以表示256个字符
  ASCII最初只用了后七位,127个数字,已经完全能够代表键盘上所有的字符了(英文字符/键盘的所有其他字符),后来为了将拉丁文也编码进了ASCII表,将最高位也占用了
阶段二:为了满足中文和英文,中国人定制了GBK
  GBK:2Bytes代表一个中文字符,1Bytes表示一个英文字符
  为了满足其他国家,各个国家纷纷定制了自己的编码
  日本把日文编到Shift_JIS里,韩国把韩文编到Euc-kr里
阶段三:各国有各国的标准,就会不可避免地出现冲突,结果就是,在多语言混合的文本中,显示出来会有乱码。如何解决这个问题呢???
  说白了乱码问题的本质就是不统一,如果我们能统一全世界,规定全世界只能使用一种文字符号,然后统一使用一种编码,那么乱码问题将不复存在,
  ps:就像当年秦始皇统一中国一样,书同文车同轨,所有的麻烦事全部解决
  很明显,上述的假设是不可能成立的。很多地方或老的系统、应用软件仍会采用各种各样的编码,这是历史遗留问题。于是我们必须找出一种解决方案或者说编码方案,需要同时满足:
    1、能够兼容万国字符
    2、与全世界所有的字符编码都有映射关系,这样就可以转换成任意国家的字符编码
    这就是unicode(定长), 统一用2Bytes代表一个字符, 虽然2**16-1=65535,但unicode却可以存放100w+个字符,因为unicode存放了与其他编码的映射关系,准确地说unicode并不是一种严格意义上的字符编码表,下载pdf来查看unicode的详情:
链接:https://pan.baidu.com/s/1dEV3RYp
  很明显对于通篇都是英文的文本来说,unicode的式无疑是多了一倍的存储空间(二进制最终都是以电或者磁的方式存储到存储介质中的)
  于是产生了 UTF-8(可变长,全称Unicode Transformation Format),对英文字符只用1Bytes表示,对中文字符用3Bytes,对其他生僻字用更多的Bytes去存

总结:内存中统一采用unicode,浪费空间来换取可以转换成任意编码(不乱码),硬盘可以采用各种编码,如utf-8,保证存放于硬盘或者基于网络传输的数据量很小,提高传输效率与稳定性。
 

  基于目前的现状,内存中的编码固定就是unicode,我们唯一可变的就是硬盘的上对应的字符编码。
此时你可能会觉得,那如果我们以后开发软时统一都用unicode编码,那么不就都统一了吗,关于统一这一点你的思路是没错的,但我们不可会使用unicode编码来编写程序的文件,因为在通篇都是英文的情况下,耗费的空间几乎会多出一倍,这样在软件读入内存或写入磁盘时,都会徒增IO次数,从而降低程序的执行效率。因而我们以后在编写程序的文件时应该统一使用一个更为精准的字符编码utf-8(用1Bytes存英文,3Bytes存中文),再次强调,内存中的编码固定使用unicode。
  1、在存入磁盘时,需要将unicode转成一种更为精准的格式,utf-8:全称Unicode Transformation Format,将数据量控制到最精简

  2、在读入内存时,需要将utf-8转成unicode
所以我们需要明确:内存中用unicode是为了兼容万国软件,即便是硬盘中有各国编码编写的软件,unicode也有相对应的映射关系,但在现在的开发中,程序员普遍使用utf-8编码了,估计在将来的某一天等所有老的软件都淘汰掉了情况下,就可以变成:内存utf-8<->硬盘utf-8的形式了。

综述:

  1、保证不乱码的核心法则就是,字符按照什么标准而编码的,就要按照什么标准解码,此处的标准指的就是字符编码
  2、在内存中写的所有字符,一视同仁,都是unicode编码,比如我们打开编辑器,输入一个“你”,我们

  不能说“你”就是一个汉字,此时它仅仅只是一个符号,该符号可能很多国家都在使用,根据我们使用的输入法不同这个字的样式可能也不太一样。只有在我们往硬盘保存或者基于网络传输时,才能确定”你“到底是一个汉字,还是一个日本字,这就是unicode转换成其他编码格式的过程了

执行python程序的三个阶段:

  阶段一:启动python解释器

  阶段二:python解释器此时就是一个文本编辑器,负责打开文件test.py,即从硬盘中读取test.py的内容到内存中

  阶段三:读取已经加载到内存的代码(unicode编码格式),然后执行,执行过程中可能会开辟新的内存空间,比如x="egon"

三.文件处理

  我们用python或其他语言编写的应用程序若想要把数据永久保存下来,必须要保存于硬盘中,这就涉及到应用程序要操作硬件,众所周知,应用程序是无法直接操作硬件的,这就用到了操作系统。操作系统把复杂的硬件操作封装成简单的接口给用户/应用程序使用,其中文件就是操作系统提供给应用程序来操作硬盘虚拟概念,用户或应用程序通过操作文件,可以将自己的数据永久保存下来。

1.打开文件的过程:

a. 打开文件,得到文件句柄并赋值给一个变量
 f=open('a.txt','r',encoding='utf-8') #默认打开模式就为r, 不指定编码的话,windows默认:gbk, linux默认:utf-8
b. 通过句柄对文件进行操作
 data=f.read()
c. 关闭文件
 f.close()
2.打开文件的模式
1). 打开文件的模式有(默认为文本模式):
  r ,只读模式【默认模式,文件必须存在,不存在则抛出异常】
  w,只写模式【不可读;不存在则创建;存在则清空内容】
  a, 之追加写模式【不可读;不存在则创建;存在则只追加内容】
2). 对于非文本文件,我们只能使用b模式,"b"表示以字节的方式操作(而所有文件也都是以字节的形式存储的,使用这种模式无需考虑文本文件的字符编码、图片文件的jgp格式、视频文件的avi格式)
  rb
  wb
  ab
  注:以b方式打开时,读取到的内容是字节类型,写入时也需要提供字节类型,不能指定编码
3). 了解部分
  "+" 表示可以同时读写某个文件
  r+, 读写【可读,可写】
  w+,写读【可读,可写】
  a+, 写读【可读,可写】

  x, 只写模式【不可读;不存在则创建,存在则报错】
  x+ ,写读【可读,可写】
  xb
3.操作文件的方法
重点:
  f.read() #读取所有内容,光标移动到文件末尾
  f.readline() #读取一行内容,光标移动到第二行首部
  f.readlines() #读取每一行内容,存放于列表中
  f.write('1111\n222\n') #针对文本模式的写,需要自己写换行符
  f.write('1111\n222\n'.encode('utf-8')) #针对b模式的写,需要自己写换行符
  f.writelines(['333\n','444\n']) #文件模式
  f.writelines([bytes('333\n',encoding='utf-8'),'444\n'.encode('utf-8')]) #b模式
了解
  f.readable() #文件是否可读
  f.writable() #文件是否可读
  f.closed #文件是否关闭
  f.encoding #如果文件打开模式为b,则没有该属性
  f.flush() #立刻将文件内容从内存刷到硬盘
  f.name
4.文件的光标移动

玩法一: read(3):

  1. 文件打开方式为文本模式时,代表读取3个字符

  2. 文件打开方式为b模式时,代表读取3个字节

玩法二: 其余的文件内光标移动都是以字节为单位如seek,tell,truncate

注意:

  1. seek有三种移动方式0,1,2,其中1和2必须在b模式下进行,但无论哪种模式,都是以bytes为单位移动的

  2. truncate是截断文件,所以文件的打开方式必须可写,但是不能用w或w+等方式打开,因为那样直接清空文件了,所以truncate要在r+或a或a+等模式下测试效果

import time
with open('test.txt','rb') as f:
    f.seek(0,2)
    while True:
        line=f.readline()
        if line:
            print(line.decode('utf-8'))
        else:
            time.sleep(0.2)
 
 
5.文件的修改

文件的数据是存放于硬盘上的,因而只存在覆盖、不存在修改这么一说,我们平时看到的修改文件,都是模拟出来的效果,具体的说有两种实现方式:

方式一:将硬盘存放的该文件的内容全部加载到内存,在内存中是可以修改的,修改完毕后,再由内存覆盖到硬盘(word,vim,nodpad++等编辑器)

import os
with open('a.txt') as read_f,open('.a.txt.swap','w') as write_f:
    data=read_f.read() #全部读入内存,如果文件很大,会很卡
    data=data.replace('alex','SB') #在内存中完成修改
    write_f.write(data) #一次性写入新文件
os.remove('a.txt')
os.rename('.a.txt.swap','a.txt')

方式二:将硬盘存放的该文件的内容一行一行地读入内存,修改完毕就写入新文件,最后用新文件覆盖源文件

import os
with open('a.txt') as read_f,open('.a.txt.swap','w') as write_f:
    for line in read_f:
        line=line.replace('alex','SB')
        write_f.write(line)
os.remove('a.txt')
os.rename('.a.txt.swap','a.txt')
posted @ 2018-07-01 09:40  ice_Ding  阅读(155)  评论(0编辑  收藏  举报