Python基础精选

python2和pythn3的区别

python2python3
input接收的是输入的类型input接收的都是字符串
ASCIIUNICODE
相对路径进行import绝对路径的方式进行 import
旧式类新式类(object)
1 个 tab 和 8 个 space 是等价的不可互相替代

废弃类差异、修改类差异、第三方工具包差异

python列表,元组,集合,字典的区别

列表:

支持索引切片成员操作符重复遍历
列表值类型可以不同
增删改查:

li.append('a')
service.extend(["b','c'])
service.insert(1,'d')
删:
li.pop()
li.pop(1)
li.remove('a')
改:
li[0] = 'e'
li[:2] = ['f','g']
元组:

支持索引切片成员操作符重复遍历
元组值类型可以不同
元祖的内容不支持更改,当元祖中有列表的时候支持更改。
只有一个值时,必须加‘,’才可以成为元组,
可以通过元组给多个变量赋值
元组没有排序,可以先变为列表,在排序
增:

a=(1,2,3)
b=(4,5)
print(a+b) #(1, 2, 3, 4, 5)
print(a*3) #(1, 2, 3, 1, 2, 3, 1, 2, 3)
删:
a=(1,2,3)
del a
print(a) #name ‘a’ is not defined 会报错

#***********
del a[1]
print(a) #报错,元组不支持元素单独项删除
集合:

集合里的元素不可重复。并且从小到大排列。
空集类型就变为了字典。
集合不支持,索引、切片、重复、连接,只支持成员操作符,遍历和枚举。
增删改查:

s.add(1)
s.update({5,3,2})
s.pop()
s.remove(6)
字典:

字典是一个键值对,他的key不是不可变的,如数字字符串,元组
只支持成员操作符和遍历
可以对多个key设置同一个值
增删改查:

services = {
    'http':80,
    'ftp':21,
    'ssh':22
}
services['mysql'] = 3306
print(services)
services['http'] = 443
print(services)

批量更新:
services = {
    'http':80,
    'ftp':21,
    'ssh':22
}
services_backup = {
    'https':443,
    'tomcat':8080,
    'http':8080
}
services.update(services_backup)

services.pop('https')
services.popitem()		删除最后一个
查:
print(services.keys())
print(services.values())
print(services.items())
print(services['http'])

python 垃圾回收机制

  1. 引用计数:
  2. 标记删除
  3. 分代收集

垃圾回收机制

小数据池和代码块

代码块
Python程序是由代码块构造的。块是一个python程序的文本,他是作为一个单元执行的。
代码块:一个模块,一个函数,一个类,一个文件等都是一个代码块。
而作为交互方式输入的每个命令都是一个代码块。

执行同一个代码块时,遇到初始化对象的命令时,他会将初始化的这个变量与值存储在一个字典中,在遇到新的变量时,会先在字典中查询记录,如果有同样的记录那么它会重复使用这个字典中的之前的这个值。

代码块的缓存机制:

  • int(float):任何数字在同一代码块下都会复用。
  • bool:True和False在字典中会以1,0方式存在,并且复用。
  • str:几乎所有的字符串都会符合缓存机制,
    • 非乘法得到的字符串都满足代码块的缓存机制:
    • 乘数为1时,任何字符串满足代码块的缓存机制:
    • 乘数>=2时:仅含大小写字母,数字,下划线,总长度<=20,满足代码块的缓存机制:

小数据池

目的:缓存我们字符串,整数,布尔值.在使用的时候不需要创建更多的对象,避免频繁的创建和销毁,提升效率,节约内存
不同代码块的缓存机制,也称为小整数缓存机制,前提是不在同一个代码块
缓存:int,str,bool

就是将~5-256的整数,和一定规则的字符串,放在一个‘池’(容器,或者字典)中,无论程序中那些变量指向这些范围内的整数或者字符串,那么他直接在这个‘池’中引用,言外之意,就是内存中之创建一个池。

str:
1.长度小于等于1,直接缓存
2.长度大于1.字符串中如果只有数字,字母,下划线,就会缓存
3.乘于1.同上,乘于大于1的数.仅包含数字,字母,下划线,最终长度小于20会缓存
4.使用sys模块中的intern()缓存字符串来指定驻留。

int数字:
-5256

布尔值:
True
False
a = 1000
b = 1000
print(id(a))	利用id可以获得数据对象的内存地址
print(id(b))
print(a == b)	== 是比较的两边的数值是否相等
print(a is b)	 is 是比较的两边的内存地址是否相等

输出:

2524884227984
2524884227984
True
True

看出内存地址相同。但是整型不是只有 -4~256才可以吗,就是代码块的功劳。因为两行在同一个文件中,属于同一个代码块,数字相同,所以代码块机制就将他们的id指向同一个。

小结
如果在同一代码块下,则采用同一代码块下的换缓存机制。
如果是不同代码块,则采用小数据池的驻留机制。

/pycharm 通过运行文件的方式执行下列代码:  这是在同一个文件下也就是同一代码块下,采用同一代码块下的缓存机制。
i1 = 1000
i2 = 1000
print(i1 is i2)  /结果为True 因为代码块下的缓存机制适用于所有数字


通过交互方式中执行下面代码:   /这是不同代码块下,则采用小数据池的驻留机制。
>>> i1 = 1000
>>> i2 = 1000
>>> print(i1 is i2)
False  /不同代码块下的小数据池驻留机制 数字的范围只是-5~256.

/虽然在同一个文件中,但是函数本身就是代码块,
所以这是在两个不同的代码块下,不满足小数据池(驻存机制),则指向两个不同的地址。
def func():
    i1 = 1000
    print(id(i1))  # 2288555806672

def func2():
    i1 = 1000
    print(id(i1))  # 2288557317392

func()
func2()	

range 和 xrange的区别

range 其实就是创建了一个list,需要在内存中保存所有的数据
xrange则是一个对象,它并没有保存这个list,而是计算出来的,他是一个生成器。

在范围不是很大时,二者的效率差不多,但当范围很大,或者经常break时,则使用xrange更合适

生成器,迭代器和装饰器

在python中,内部含有__Iter__方法并且含有__next__方法的对象就是迭代器。

话说py2时代,range()返回的是list,但如果range(10000000)的话,会消耗大量内存资源,所以,py2又搞了一个xrange()来解决这个问题。py3则只保留了xrange(),但写作range()。xrange()返回的就是一个迭代器,它可以像list那样被遍历,但又不占用多少内存。

generator(生成器)是一种特殊的迭代器,只能被遍历一次,遍历结束,就自动消失了。

总之,不管是迭代器还是生成器,都是为了避免使用list,从而节省内存。那么,如何得到迭代器和生成器呢?

python内置了迭代函数 iter,用于生成迭代器,用法如下:
str list tuple dic set range 为可迭代对象,因为他们的内部含有iter方法的对象,都是可迭代对象。

>>> a = [1,2,3]
>>> a_iter = iter(a)
>>> a_iter
<list_iterator object at 0x000001B2DE434BA8>
>>> for i in a_iter:
	print(i, end=', ')

1, 2, 3, 

yield 则是用于构造生成器的。比如,我们要写一个函数,返回从0到某正整数的所有整数的平方,传统的代码写法是这样的:

>>> def get_square(n):
	result = list()
	for i in range(n):
		result.append(pow(i,2))
	return result

>>> print(get_square(5))
[0, 1, 4, 9, 16]

但是如果计算1亿以内的所有整数的平方,这个函数的内存开销会非常大,这是 yield 就可以大显身手了:

>>> def get_square(n):
	for i in range(n):
		yield(pow(i,2))

>>> a = get_square(5)
>>> a
<generator object get_square at 0x000001B2DE5CACF0>
>>> for i in a:
	print(i, end=', ')

0, 1, 4, 9, 16, 

如果再次遍历,则不会有输出了。

“”"
装饰器:
把一个函数当作参数,返回一个替代版的函数
本质上就是一个返回函数的函数

“在不改变原函数的基础上,给函数增加功能”

放置于函数的上方,以@开头,加上定义的装饰器函数,就可以直接调用装饰器的函数,先运行装饰器函数,在运行已经定义的函数。
“”"

def decorator(fun):
    def wrapper():
        print('linux to linux')
        fun()
    return wrapper
@decorator         #装饰器      
def f1():
    print('hello world')

f1()

在这里插入图片描述

三目运算

一般支持三目运算符的语言(如C语言)的语法格式一般是这样的:

判断条件(返回布尔值)?为真时的结果:为假时的结果

比如:

x = x%2==1 ? x+1:x;

python并不支持? :这种符号所表达的先判断再选择的含义,但仍然有相应的语法支持:

  1. Python 的语法支持
为真时的结果 if 判断条件 else 为假时的结果(注意,没有冒号)

顺序略有不同,

x = x+1 if x%2==1 else x

深拷贝和浅拷贝

首先,我们知道Python3中,有6个标准的数据类型,他们又分为可以变和不可变。
不可变:Number(数字)、String(字符串)、Tuple(元组)。
可以变:List(列表)、Dictionary(字典)、Set(集合)。

1、浅拷贝

使用copy模块里面的copy方法实现。对象地址改变,但里面的所有值地址不变。

改变原始对象中为可变类型的元素的值,会同时影响拷贝对象;

改变原始对象中为不可变类型的元素的值,不会响拷贝对象。

2、深拷贝

copy模块里面的deepcopy方法实现。

深拷贝,除了顶层拷贝,还对子元素也进行了拷贝。

原始对象和拷贝对象所有的可变元素地址都不一样了。但不可变元素地址仍相同

改变原始对象中所有类型的值,都不会影响拷贝对象。

断言assert

在测试用例中,执行完测试用例后,最后一步是判断测试结果是pass还是fail,自动化测试脚本里面一般把这种生成测试结果的方法称为断言(assert)。

常用的断言方法:
在这里插入图片描述
assert作用:断言函数是对表达式布尔值的判断,要求表达式计算值必须为真。可用于自动调试。如果表达式为假,触发异常;如果表达式为真,不执行任何操作。

assert(1==1)

输出:
在这里插入图片描述
可以看出什么都没有输出。

assert(1==1)
# assert(1==2)
assert(1>100)

输出:
在这里插入图片描述
就报错了。

对列表的断言:

a = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
b = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
assert(a == b)

正常,无输出。

python 抛出异常 raise Exception

一旦执行了raise语句,raise后面的语句将不能执行。

def printError(v):
    if v == 2:
        print('yes')
    else:
        raise Exception('Not exiests `V`.')

printError(2)

输出:

C:\Users\Administrator\PycharmProjects\pythonProject\venv\Scripts\python.exe C:/Users/Administrator/PycharmProjects/pythonProject/12-5/raise.py
yes

def printError(v):
    if v == 2:
        print('yes')
    else:
        raise Exception('Not exiests `V`.')

printError(3)

输出:

在这里插入图片描述

就会抛出异常。

time模块中的不同时间类型

元组类型:time.localtime()
时间戳类型:time.mktime() os.path.getctime(’/etc/shadow’) #unix的计算时间方式
字符串时间:time.strftime time.ctime

python中的 if __name__ == ‘__main__’ 的作用

对于很多编程语言来说,程序都必须要有一个入口,C 和 C++ 都需要有一个 main 函数来作为程序的入口,也就是程序的运行会从 main 函数开始。而 Python 则有不同,它属于脚本语言,不像编译型语言那样先将程序编译成二进制再运行,而是动态的逐行解释运行。也就是从脚本第一行开始运行,没有统一的入口。

一个 Python 源码文件除了可以被直接运行外,还可以作为模块(也就是库)被导入。不管是导入还是直接运行,最顶层的代码都会被运行(Python 用缩进来区分代码层次)。而实际上在导入的时候,有一部分代码我们是不希望被运行的。

我们就可以使用if __name__ == '__main__来实现。
通俗的理解__name__ == ‘__main__’:假如你叫小明.py,在朋友眼中,你是小明(__name__ == ‘小明’);在你自己眼中,你是你自己(__name__ == ‘__main__’)。

if name == 'main’的意思是:当.py文件被直接运行时,if name == 'main’之下的代码块将被运行;当.py文件以模块形式被导入时(from test import PI ,test是一个python文件,PI是这个文件中的一个变量),if name == 'main’之下的代码块不被运行。

源地址

python的内存池机制

Python提供了对内存的垃圾收集机制,但是它将不用的内存放到内存池而不是返回给操作系统。

1,Pymalloc机制。为了加速Python的执行效率,Python引入了一个内存池机制,用于管理对小块内存的申请和释放。

2,Python中所有小于256个字节的对象都使用pymalloc实现的分配器,而大的对象则使用系统的malloc。

3,对于Python对象,如整数,浮点数和List,都有其独立的私有内存池,对象间不共享他们的内存池。也就是说如果你分配又释放了大量的整数,用于缓存这些整数的内存就不能再分配给浮点数。

python多线程

threading模块
python多线程详解

Python中的编码

ASCII : 最早的编码. ⾥⾯有英⽂⼤写字⺟, ⼩写字⺟, 数字, ⼀些特殊字符. 没有中⽂, 8个01代码, 8个bit, 1个byte

GBK: 中⽂国标码, ⾥⾯包含了ASCII编码和中⽂常⽤编码. 16个bit, 2个byte

UNICODE: 万国码, ⾥⾯包含了全世界所有国家⽂字的编码. 32个bit, 4个byte, 包含了 ASCII

UTF-8: 可变⻓度的万国码. 是unicode的⼀种实现. 最⼩字符占8位   1.英⽂: 8bit 1byte   2.欧洲⽂字:16bit 2byte   3.中⽂:24bit 3byte

综上, 除了ASCII码以外, 其他信息不能直接转换. 在python3的内存中. 在程序运⾏阶段. 使⽤的是unicode编码. 因为unicode是万国码. 什么内容都可以进⾏显⽰. 那么在数据传输和存储的时候由于unicode比较浪费空间和资源. 需要把 unicode转存成UTF-8或者GBK进⾏存储. 怎么转换呢. 在python中可以把⽂字信息进⾏编码. 编码之后的内容就可以进⾏传输了. 编码之后的数据是bytes类型的数据.其实啊. 还是原来的 数据只是经过编码之后表现形式发⽣了改变⽽已.

s = "alex"
print(s.encode("utf-8")) # 将字符串编码成UTF-8
print(s.encode("GBK")) # 将字符串编码成GBK

s = "中"
print(s.encode("UTF-8")) # 中⽂编码成UTF-8
print(s.encode("GBK")) # 中⽂编码成GBK

结果:
在这里插入图片描述

可见,英⽂编码之后的结果和源字符串⼀致. 中⽂编码之后的结果根据编码的不同. 编码结果也不同。
⼀个中⽂的UTF-8编码是3个字节. ⼀个GBK的中⽂编码是2个字节.   
编码之后的类型就是bytes类型. 在⽹络传输和存储的时候我们python是发送和存储的bytes 类型.   
那么在对⽅接收的时候. 也是接收的bytes类型的数据.

我们可以使⽤decode()来进⾏解码操作.

s = "我叫李嘉诚"
print(s.encode("utf-8")) #
b'\xe6\x88\x91\xe5\x8f\xab\xe6\x9d\x8e\xe5\x98\x89\xe8\xaf\x9a'
print(b'\xe6\x88\x91\xe5\x8f\xab\xe6\x9d\x8e\xe5\x98\x89\xe8\xaf\x9a'.decode("utf-8")) # 解码

结果:
在这里插入图片描述
可以使用decode进行解码,编码和解码的时候都需要制定编码格式.

s = "我是⽂字" 
bs = s.encode("GBK")  #编码
s = bs.decode("GBK") # 解码,把GBK解码为unicode格式
bss = s.encode("UTF-8") # 重新编码 
print(bss)

在这里插入图片描述
Unicode就相当于他们之间的桥梁,可以实现他们之前相互编码,但是我们在编码和解码的时候必须使用同一个密码本.

Python中读取文件的绝对路径和相对路径

相对路径:同一个文件夹下面的文件,直接写文件名就可以。
f = open('护士少妇萝莉',mode='rb')



绝对路径:从根目录下开始一直到文件名。
我们在使用绝对路径的时候因为有\这样程序是不能识别的,解决方法:

open('C:\Users\Meet')  /这样程序是不识别的

解决方法一:
open('C:\\Users\\Meet') /这样就成功的将\进行转义   两个\\代表一个\

解决方法二:
open(r'C:\Users\Meet') /这样相比上边的还要省事,在字符串的前面加个小r也是转义的意思  推荐使用这种

Python中读取文件的各种模式

模式描述
r以只读方式打开文件。文件的指针将会放在文件的开头。这是默认模式。
rb以二进制格式打开一个文件用于只读。文件指针将会放在文件的开头。这是默认模式。
r+打开一个文件用于读写。文件指针将会放在文件的开头。
rb+以二进制格式打开一个文件用于读写。文件指针将会放在文件的开头。
w打开一个文件只用于写入。如果该文件已存在则将其覆盖(等于清空文件内容在重写)。如果该文件不存在,创建新文件。
wb以二进制格式打开一个文件只用于写入。
w+打开一个文件用于读写。如果该文件已存在则将其覆盖。如果该文件不存在,创建新文件。
wb+以二进制格式打开一个文件用于读写。
a打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。也就是说,新的内容将会被写入到已有内容之后。如果该文件不存在,创建新文件进行写入。
ab以二进制格式打开一个文件用于追加。
a+打开一个文件用于读写。如果该文件已存在,文件指针将会放在文件的结尾。文件打开时会是追加模式。如果该文件不存在,创建新文件用于读写。
ab+以二进制格式打开一个文件用于追加。

可以看出b模式是只读字节的模式,以二进制的方式显示。

f = open('护士少妇萝莉',mode='rb')	/rb 读出来的数据是bytes类型,在rb模式下,不能encoding字符集
f = open(联系方式.txt',mode='r',encoding='utf-8')	/不加b的模式就可以指定字符集

我们可以用with open 来打开,这样更安全。

with open(r'C:\Users\Administrator\Desktop\新建文本文档.txt','r') as f:
    print(f.read())

在这里插入图片描述

with open(r'C:\Users\Administrator\Desktop\新建文本文档.txt','r',encoding='UTF-8') as f:
    print(f.read())

结果:
在这里插入图片描述
为windows系统中记事本中写的内容编码是GBK,所以打开会有问题,我们可以通过参数进行修改。

with open(r'C:\Users\Administrator\Desktop\新建文本文档.txt','rb') as f:	/rb以二进制方式显示
    print(f.read())

在这里插入图片描述

python中的格式化输出

wo = '曹源'
age = 18
addr = '刘妍市临潼区'

print('我叫%s,今年%d岁了,我来自%s' %(wo,age,addr))		/第一种方式

msg = f'我叫{wo},今年{age}岁了,我来自{addr}'		/第二种方式
// msg = F'我叫{wo},今年{age}岁了,我来自{addr}' 	/用大F也可以
print(msg)

在这里插入图片描述
可见输出的结果都是一样的。

第二种方式是python3.6引入的标准库的格式化输出新的写法,f-strings字符串格式化,这个格式化输出比之前的%s 或者 format 效率高并且更加简化,非常的好用。

其他用法:

print(f'计算3*21:{3*21}')

name = 'barry'
print(f'全部大写:{name.upper()}')

# 字典也可以
teacher = {'name': '宝元', 'age': 18}
msg = f"The teacher is {teacher['name']}, aged {teacher['age']}"
print(msg)  

# 列表也行
l1 = ['宝元', 18]
msg = f'姓名:{l1[0]},年龄:{l1[1]}.'
print(msg)

在这里插入图片描述

多行F:

name = 'barry'
age = 18
ajd = 'handsome'

speaker1 = f'''Hi {name}.
You are {age} years old.
You are a {ajd} guy!'''

speaker2 = f'Hi {name}.'\
          f'You are {age} years old.'\
          f'You are a {ajd} guy!'
print(speaker1)
print(speaker2)

在这里插入图片描述
其他细节:

print(f"{{73}}")  # {73}
print(f"{{{73}}}")  # {73}
print(f"{{{{73}}}}")  # {{73}}
m = 21
/ ! , : { } ;这些标点不能出现在{} 这里面。
/ print(f'{;12}')  # 报错
/ 所以使用lambda 表达式会出现一些问题。
/ 解决方式:可将lambda嵌套在圆括号里面解决此问题。
x = 5
print(f'{(lambda x: x*2) (x)}')  # 10
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值