python基础补漏1

python基础补漏系列一

本部分用于python再次深入学习,之前只是粗浅的掌握了python的使用,没有进行相对实际应用、复杂的利用,仅仅是编写一些简单的脚本,本次借助本次重新学习,将python的深入应用活起来,前面部分是对基础内容一些需要提醒自己或者有点遗忘的部分做一些简要的记录,后续更为详细。

转义

print (r"\n") #字符串前附加r可以使得解析字符串时候内部转移字符均不进行解析

多行

    print (r'''line1
...line2
    ...tab-line2''')
#''' ...  ''' 可以实现多行拼接

变量指向

当我们书写一个赋值语句a = 'ABC’时,Python 解释器干了两件事情:

  1. 在内存中创建了一个’ABC’的字符串;
  2. 在内存中创建了一个名为 a 的变量,并把它指向’ABC’。

当我们进行操作:

a = 'ABC'
b = a
a = 'XYZ'
print(b)

b会输出什么值呢?

我们进行逐步分解:

1.执行 a = ‘ABC’,解释器创建了字符串’ABC’和变量 a,并把 a 指向’ABC’:

2.执行 b = a,解释器创建了变量 b,并把 b 指向 a 指向的字符串’ABC’:

3.执行 a = ‘XYZ’,解释器创建了字符串’XYZ’,并把 a 的指向改为’XYZ’。

其中变量存放的都是地址,而且是直接指向字符串的。所以自然输出是ABC。

除法

python中有两种触发,’/’(精确除)和’//’(地板除)

编码问题

ASCII编码是1个字节,而 Unicode 编码通常是 2 个字节。
字母 A 用 ASCII 编码是十进制的 65,二进制的 01000001;
字符 0 用 ASCII 编码是十进制的 48,二进制的 00110000,注意字符’0’和整数 0 是不同的;

汉字“中”已经超出了 ASCII 编码的范围,用 Unicode 编码是十进制的 20013,二进制的 01001110 00101101。

你可以猜测,如果把 ASCII 编码的 A 用 Unicode 编码,只需要在前面补0 就可以,因此,A 的 Unicode 编码是 00000000 01000001。

但是呢,如果统一都用Unicode就又会出现一些浪费的问题,常用的英文本来是可以用一个字节表示的,但是现在都需要用两个字节进行表示,空间比原来浪费了一倍。

本着节约的精神,又出现了把 Unicode 编码转化为“可变长编码”的 UTF-8 编码。UTF-8 编码把一个 Unicode 字符根据不同的数字大小编码成 1-6 个字节,常用的英文字母被编码成 1 个字节,汉字通常是 3 个字节,只有很生僻的字符才会被编码成 4-6 个字节。

字符ASCIIUnicodeUTF-8
A0100000100000000 0100000101000001
X01001110 0010110111100100 10111000 10101101

所以经常会遇到一些很奇怪的编码问题就可以根据上述的内容很好的理解该怎么转换了。

这里再谈一下这几种编码的一些转化方面的问题。

计算机系统通用的字符编码工作方式

在计算机内存中,统一使用 Unicode 编码,当需要保存到硬盘或者需要传输的时候,就转换为 UTF-8 编码。

用记事本编辑的时候,从文件读取的 UTF-8 字符被转换为 Unicode 字符
到内存里,编辑完成后,保存的时候再把 Unicode 转换为 UTF-8 保存到
文件中。

浏览网页的时候,服务器会把动态生成的 Unicode 内容转换为 UTF-8 再
传输到浏览器。

在这里插入图片描述

字符串中的编码问题

遇到这个问题讨论的时候,回想起之前用pwntool的时候,python3环境下直接使用p64、p32等打包函数会出现问题的问题,感觉这个应该是正解了。

#单个字符的编码
ord()  #获取字符的整数表示
chr()  #把编码转换成对应的字符

如果直到字符的整数编码,十六进制还可以直接写str:

'\u4e2d\u6587'    #等价于'中文'

由于 Python 的字符串类型是 str,在内存中以 Unicode 表示,一个字符对应若干个字节。如果要在网络上传输,或者保存到磁盘上,就需要把str 变为以字节为单位的 bytes。

Python 对 bytes 类型的数据用带 b 前缀的单引号或双引号表示。

>>> a=b'a'
>>> b='a'
>>> a==b
False
#后者是 str,后者虽然内容显示得和前者一样,但 bytes 的每个字符都只占用一个字节。

以 Unicode 表示的 str 通过 encode()方法可以编码为指定的 bytes。纯英文的 str 可以用 ASCII 编码为 bytes,内容是一样的,含有中文的 str可以用 UTF-8 编码为 bytes。含有中文的 str 无法用 ASCII 编码,因为中文编码的范围超过了 ASCII 编码的范围,Python 会报错。

>>> 'a'.encode('ascii')
b'a'
>>> '中'.encode('utf-8')
b'\xe4\xb8\xad'
>>> '中'.encode('ascii')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeEncodeError: 'ascii' codec can't encode character '\u4e2d' in position 0: ordinal not in range(128)

反过来,如果我们从网络或磁盘上读取了字节流,那么读到的数据就是bytes。要把 bytes 变为 str,就需要用 decode()方法:

要计算 str 包含多少个字符,可以用 len()函数,1 个中文字符经过 UTF-8 编码后通常会占用 3 个字节,而 1 个英文字符只占用 1 个字节。在操作字符串时,我们经常遇到 str 和 bytes 的互相转换。为了避免乱码问题,应当始终坚持使用 UTF-8 编码对 str 和 bytes 进行转换。

>>> b'\xe4\xb8\xad'.decode('utf-8')
'中'

## 如果需要直接转unicode的话,需要用unicode-escape。
>>> b'\xe4\xb8\xad'.decode('Unicode')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
LookupError: unknown encoding: Unicode
>>> b'\xe4\xb8\xad'.decode('unicode-escape')
'ä¸\xad'

由于 Python 源代码也是一个文本文件,所以,当你的源代码中包含中
文的时候,在保存源代码时,就需要务必指定保存为 UTF-8 编码。当
Python 解释器读取源代码时,为了让它按 UTF-8 编码读取,我们通常
在文件开头写上这两行:

#!/usr/bin/env python3     #告诉 Linux/OS X 系统,这是一个 Python 可执行程序,Windows 系统会忽略这个注释;
# -*- coding: utf-8 -*-    #告诉 Python 解释器,按照 UTF-8 编码读取源代码,否则,你在源代码中写的中文输出可能会有乱码。

但是呢,很多时候在ide中编辑运行的时候会发现明明申明了,但是还是会乱码,因为不仅仅文件中要进行设置,文本编辑器中也需要进行设置(如果用ide编辑,则ide为文本编辑器),我们还需要确保文本编辑器也正在使用UTF-8 without BOM 编码。

格式化输出

>>> 'Hi, %s, you have $%d.' % ('Michael', 1000000)
'Hi, Michael, you have $1000000.'
#常见占位符
%d  整数
%f  浮点数
%s  字符串
%x  十六进制整数
#其中,格式化整数和浮点数还可以指定是否补 0 和整数与小数的位数:
>>> '%2d-%02d' % (3, 1)
' 3-01'
>>> '%.2f' % 3.1415926
'3.14'

其中如果有类型不是很确定,可以直接用%s,它会将任何数据类型转换成字符串。如果要输出%,则通过%%转义表示一个%。

list

Python 内置的一种数据类型是列表:list。list 是一种有序的集合,可以随时添加和删除其中的元素。

#1.len() 可以获得一个列表的长度
#2.append() 追加元素到末尾
#3.insert() 插入指定位置
#4.pop() 删除指定位置
#索引
--可以通过直接索引去访问列表的任意随机地址,(索引是从0开始的)
--可以通过索引直接修改列表内容
--可以套娃列表(参考C的多维数组)

tuple

相比list列表而言元组的区别在于一旦初始化就不能修改,这种设定更加安全。

特殊分析

初始化只有一个元素的元组

只有一个元素的元组不可以直接通过(X)进行初始化,因为()可以表示数学公式中的小括号,产生歧义,而python中规定这种情况下是按照小括号计算的。

所以要想初始化只有一个元素的元组需要通过如下的方式进行初始化:

t=(1,)
元组可变?
>>> t = ('a', 'b', ['A', 'B'])
>>> t[2][0] = 'X'
>>> t[2][1] = 'Y'
>>> t
('a', 'b', ['X', 'Y'])

通过下述的图示,可以很明显的看到,其实元组是没有改变的,它内部[2]的内容依然是指向一个列表的,只不过是列表变了罢了。举个很简单的例子,现在有三个黏在桌子上的箱子,箱子我们不能动,但是我们可以打开箱子换掉里面的东西。此外,假如箱子里面的东西还是一个被黏在里面的物品,那么我们也无法对它进行修改。(元组中套元组的情况)

在这里插入图片描述

dict

Python 内置了字典:dict 的支持,dict 全称 dictionary,在其他语言中也
称为 map,使用键-值(key-value)存储,具有极快的查找速度。

>>> ascii={'a':41,'b':42}
>>> print(ascii['a'])
41

dict 的实现原理和查字典是一样的。先在字典的索引表里(比如部首表)查这个字对应的页码,
然后直接翻到该页,找到这个字。无论找哪个字,这种查找速度都非常快,不会随着字典大小的增加而变慢。而list中是把字典从第一页往后翻,直到找到我们想要的字为止,这种方法就是在 list 中查找元素的方法,list 越大,查找越慢。

#操作
1.放入dict(由于一个 key 只能对应一个 value,所以,多次对一个 key 放入 value,
后面的值会把前面的值冲掉)
	-初始化
	-通过key放入:d['Adam'] = 67
2.in判断key是否存在。(如果直接通过索引获取,当值不存在的时候会报错)
3.d.get(“key”,moren)  get方法可以查找是否存在,如果不存在返回None或者自己指定的moren
4.d.pop('key')  删除对应key的键值

不可变对象

dict 根据 key 来计算 value 的存储位置,如果每次计算相同的key 得出的结果不同,那 dict 内部就完全混乱了,所以key必须是不可变对象。这个通过 key 计算位置的算法称为哈希算法(Hash)。

python中有可变对象和不可变对象,可变对象:list,dict.不可变对象有: int , string , float , tuple.

这里需要特别关注一个现象

>>> a = 'abc'
>>> a.replace('a', 'A')
'Abc'
>>> a
'abc'

这个的结果应证了字符串类型是不可变类型,但是怎么理解上面的过程呢?

>>> a = 'abc'
>>> b = a.replace('a', 'A')
>>> b 
'Abc'
>>> a
'abc'

通过这样的操作,我们似乎能猜测出一个结论。

实际上:我们需要知道一点a只是个变量,只有abc才是字符串对象。当我们调用 a.replace(‘a’, ‘A’)时,实际上replace是作用在’abc’上,这个replace方法虽然叫替换,但是却没有改变’abc’的内容,它只是返回了一个对应的字符串的拷贝版,其中出现被替换的部分则修改成需要被修改的部分。

    def replace(self, *args, **kwargs): # real signature unknown
        """
        Return a copy with all occurrences of substring old replaced by new.
        
          count
            Maximum number of occurrences to replace.
            -1 (the default value) means replace all occurrences.
        
        If the optional argument count is given, only the first count occurrences are
        replaced.
        """
        pass

set

set 和 dict 类似,也是一组 key 的集合,但不存储 value。由于 key 不能
重复,所以,在 set 中,没有重复的 key。

要创建一个 set,需要提供一个 list 作为输入集合,重复的元素被自动过滤。

#操作
1.初始化
>>> s = set([1, 2, 3])
>>> s
{1, 2, 3} 

2.set.add(key) 可以添加元素到set中,重复添加的无效
3.set可以看作数学上的无序和无重复元素集合,可以作数学意义上的交集和并集等操作。(&、|)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值