python 简明笔记

python 简明笔记

基础内置类型

数值类型

字面量

3.14e-10
3.14E-10
3.14e+10
#八进制
0o123
#十六进制
0xabf
#二进制
0b10101

#进制转换函数
#把一个整数数值转换成三种进制的字符串
hex(I)
oct(I)
bin(I)
#把三种进制的字符串转换成数字
int(str_num, jinzhi)
str_num = "0xff"
int(str_num, 16)

#小数取整
import math
#向下取整
math.floor(num_f)
#向零取整
math.trunc(num_f)
int(num_f)
#四舍六入  五向偶舍入
round(num_f) #保留整数部分
round(num_f, n) #保留小数点后n位

#开平方
import math
math.sqrt(144)
144**0.5
#指数
pow(5,2)
5**2

#随机
import random
#产生一个(0,1)的小数
random.random()
#产生一个[1,3]之间的整数
random.randint(1,3)

#从数组arr中随机挑选一个,返回挑选出的元素
random.choice(arr)
#将数组arr打乱,没有返回
random.shuffle(arr)

集合

不可变对象的无序集合

  • 集合只能包含不可变对象,因此集合和字典不能嵌入到集合中,元祖可以。
  • 用来过滤重复项
  • 借助集合进行顺序无关的等价性测试
  • 性质:无序,不重复
s1 = {1, 2, 3} #集合
s2 = {} #字典

x = set("abcd")
y = set("abCD")

print(x | y)
print(x & y)
print(x ^ y) #去掉两个集合的交集
print(x < y) #真子集
print(x <= y) #子集
print(x - y)

#插入一个项目
x.add("EF")

#原地求并集
z.update({1, 2})

#根据值删除一个元素
z.remove(1)

#集合表达式通常需要两个集合,他们基于方法的对应形式往往可以对任何可迭代类型有效
#这些都不是原地修改
z.union([1,2,3,4])
z.intersection([4,5,6])
z.issubset([1,2,3,4,5,6,7,8])

动态类型

每一个对象不仅仅有足够的空间来表示它的值,还包含其他数据结构

  • 类型标志符
  • 引用计数器

类型属于对象,而不是变量

可原位置修改

  • 列表
  • 字典
  • 集合
#列表拷贝
arr = [1, 2, 3, 4]
arr_temp = arr[:]

#通用拷贝
import copy
arr_temp = copy.copy(arr)
arr_temp = copy.deepcopy(arr)

字符串

  • 不可原位置修改
  • 调用字符串方法,一般通过返回值来体现变化
############################################
# 字符串

#不允许 + 表达式中混合数字和字符串
#切片 前闭后开

ord('s') == 115
chr(115) == 's'
#若没有逗号,python 会自动拼接相邻的字符串字面量
#原始字符串,防止转义
s = r"\nasdfj\t"

#逆序切片,大下标写在前
s = '0123456789'
print(s[8:2:-2])

#不能在原位置修改
s = s.replace("1", "111")
print(s)

#替换前n个
s = s.replace("1", "111",n) 

#替换前3个,否则全部替换
s = s.replace("old", "nwe", 3) 

#可原位置于不可原位置修改对象调用函数时,返回值对比
s = "1010101010101"
s = s.replace("1","*****",)

arr = [1,2,3,4,0]
arr.sort()


#按值搜索,返回下标,找不到返回-1
s = "abcdefg"
index = s.find('cde')

#将列表中的字符串穿在一起,并用**分隔
s = "**".join([ "1", "2", "3" ])

#分割字符串,放到列表中
l = s.split("**")

#是否是字母(全部由字母组成)
s.isalpha()
#是否是数字
s.isdigit()
#返回大、小写
s.upper()
s.lower()
#开头、结尾检测
s.endswith("xx")
s.startswith("xx")

#去处空白
s = "   123   "
s = s.lstrip()
print(s)

#格式化输出
s = " %d   %s" % (1, "haha")
s = " %(name)s 今天 %(age)d 岁了" % D #D是一个字典
s = " {0}  {1}".format(1, "haha")
s = "{name} 今年 {age} 岁了".format(name="nana",age=17)

列表

任意对象的有序集合

############################################
# 列表
L = [1,2,3,4]

#尾部添加
L.append(5)

#尾部迭代添加
L.extend("abc")

#插入
L.insert(1,8)

#索引
L.index(1)

#统计出现数量
L.count(1)

#排序,原地排序
L = [1,67,23,90]
L.sort()
L.sort(reverse=True)

#反转
L.reverse()

#拷贝
L_temp = L.copy()

#清除
L.clear()

#删除i处元素,并返回
L = [1,67,12]
i = 1
L.pop(i)

#删除所有x
x = 1
L.remove(x)

#范围删除
L = [1,67,23,90]
i = 1
j = 3
del L[i]
del L[i:j]

L[i:j] = []

#切片赋值 先删除,然后迭代插入
L = list("123456789")
L[1:4] = [8,8,8]

#列表推导
l = [f(x) for x in range(19)]

字典

  • 任何不可变对象都可以作为键(字符串、元祖、数字)
  • keys,values,items 都返回视图对象
  • 视图对象是可迭代对象,每次只产生一个结果项的对象,而不是在内存中立即产生结果列表
  • 视图对象创建后,会随着字典的变化,动态的反应字典的修改
  • keys的返回对象,支持集合操作
  • 稀疏数据结构使用字典,用元祖作为键
  • 字典模拟结构体
  • 键的存在性 用 in测试
############################################
# 字典

#这种方式键是字符串
D = dict(name = "qwj" ,age = 19)

keyslist = ['name','age']
valueslist = ['qwj',19]

D = dict(zip(keyslist,valueslist))
D = dict([keyslist,valueslist])

#尝试获取,如果不存在返回default
D.get(key, "default")
#尝试删除,如果key存在,返回对应值,如果不存在返回default
D.pop(key, "default")
#如果key不存在,添加 key:default。如果key存在,返回【key】
D.setdefault(key, "default")


#删除所有键值对
D.popitem()
#浅层拷贝
D1 = D.copy()

#通过键来合并,有相同键,将D1按照D2更新
D1.update(D2)

#获取值
D = dict(zip(keyslist,valueslist))
val = D.get('name', "没有")

#删除键,并返回
D = dict(zip(keyslist,valueslist))
val = D.pop('name', "没有")

#若没有才插入 
D = dict(zip(keyslist,valueslist))
D.setdefault('age','nana')

#最简单的异常捕捉
try:
    print(D[1])
except:
    print("出错了")
else:
    print("没出错")

元组

  • 任意对象的有序集合
  • 元祖不可原位置更改,元祖内部元素不需要是不可变元素
  • 与列表相似,元祖应当被看做对象引用的数组
  • 不可变性只是限制顶层元素
T = (1,)
T = tuple("hello")
L = list("hello")
S = set("hello")

文件

output = open(r"data", 'w')
output = open('f.bin','rb') # 制文件
Input = open("data", 'r')
Input = open("data") # 默认是读
aString = input.read() # 整个文件读入一个字符串对象/bytes对象
aString = input.read(N) # 试读取N个字符到一个字符串
aString = input.readline() # 取一行(包含\n) 到一个字符串,只能用于文本文件
aList = input.readlines() # 读取整个文件到一个字符串列表 (每行包括换行),只能用于文本文件
output.write(aString) # 将字符串(或者字节序)写入文件
output.writelines(aList) # 将列表内的所有字符串写入文件中
output.close()
output.flush() # 写入的文件可能不会立即从内存移动到磁盘
anyFile.seek(N)

for line in open("data"): pass

#with 文件上下文管理器
with open('txt') as myfile: 
    for x in myfile:
        print(x)

模式

模式
r 默认,读
w
a 在文件尾部追加(写)内容
b 处理二进制文件
+ 同时支持读写
open('test', mode="w+", encodeing='utf-8')

文件的空行是含有换行符的字符串,而不是空字符串

存储python对象

pickle

import pickle
F = open("datafile.pkl", 'wb')

D = {
        "name" : "qwj",
        "age" : 17
        }

pickle.dump(D, F)
F.close()

F = open("datafile.pkl", 'rb')
E = pickle.load(F)
print(E)

杂记

复合对象

  • 列表、字典、元组可包含任何对象
  • 字典的键、集合的内容 只能是不可变对象
  • 列表、字典、集合可以动态扩容缩小

列表与元祖的异同

    • 列表可以修改顶层元素、元素数量
    • 元素都是指针
    • 都是有有序

复制

import copy
x = copy.copy(y) #顶层复制
z = copy.deepcopy(y) #深层递归复制

等价性测试 ==:python递归的比较所有内嵌对象

同一性测试 is:测试两个对象在内存中的位置是否相同

#False
""
[]
{}
None #函数默认返回值
L = [None] * 100

#每个核心类型都有一个内置名
dict
list
str
tuple
int
float
complex
bytes
set
type
#type(x) 返回对象x的类型对象,类型也是一个对象

#类型判断(待测试对象,内置名)
isinstance(obj, list)

语句

while 1:print(x)

while True:
    reply = input("输入一个数:")
    if reply == "stop" : break
    try:
        num = int(reply)
    except:
        print("bad" * 8)
    else:
        print(num ** 2)

赋值

nana, qwj = 18, 19
#带*的名称可能只能匹配到单个项,但总会将其赋值为一个列表
x, *y = "hello"
*x, y = "hello"
x, *y, z = "hello"
x, y, *z = "hello"
x, *y = "h"
x = y = z = "hello"

命名规则

  • 以单一下划线开头的名称(_x)不会被 from module import * 语句导入
  • 类名以大写字母开头,模块名以小写字母开头
for _ in range(90):
    print(100)

打印 print

  • seq 分隔的字符串,默认 " "
  • end 结尾的字符串,默认 "/n"
  • file 输出流,默认"sys.stdout"
  • flush 是否刷新输出缓冲区,默认"false"

重定向

#在python中
import sys
sys.stdout = open('log.txt', 'a')
#在shell 中
# < inputfile 输入重定向
# > outputfile 输出重定向
# 2> errfile 错误重定向

python没有switch、case,可使用字典来近似代替

逻辑

x and y
x or y
not x

三元运算

#选出最大的
x = 10
y = 20
z = x is x > y else y

while、for

while test:
    if test: break
    statements
else:
    statements  # 当while没有被break的时候执行else,或者理解break会跳过所有,包括else
    
for x in object:
    if test: break
    statements
else:
    statements  # 当while没有被break的时候
    

range

arr_1 = list(range(5))
arr_2 = list(range(1,5))
arr_3 = list(range(2,10,2))

[0, 1, 2, 3, 4]
[1, 2, 3, 4]
[2, 4, 6, 8]

enumerate 同时给出偏移量和元素

arr_1 = [1, 3, 5, 7, 9]
for i, x in enumerate(arr_1):
    print(i, x)

迭代和推导

可迭代对象

  • 一次产生一个结果的对象
  • 是序列概念的一种通用化
  • 包括实际的序列,以及能按照需求就算的虚拟序列

可迭代对象与迭代器

  • 可迭代对象:迭代的调用对象。拥有 _iter_ 方法,这个方法会被 iter函数调用

迭代器对象:可迭代对象的返回结果,在迭代过程中提供值的对象。拥有 _next_ 方法,这个方法会被 next函数调用,并在结束时触发 StopIteration

  • 有些对象即是可迭代对象,也是迭代器对象,他们会在iter调用中返回他们自己
  • 迭代器对象通常是临时的,它们在迭代工具内部被使用

for循环、其他迭代工具

  • 将可迭代对象传入内置函数iter,并由此拿到一个迭代器对象(可能返回自身)
  • iter返回的迭代器对象有着所需的 _next_ 方法
  • 每次迭代中调用 _next_ 方法,并通过捕捉StopIteration异常来确定何时离开。

for 与 while 的性能

while循环比基于迭代器的for循环运行得更慢,因为迭代器对象在python内部是以C语言速度运行的,而while则是通过python虚拟机运行python字节码。

多次迭代

列表以及很多其他内置对象,由于自身不是迭代器,因此支持多次迭代。

map、filter、zip

  • 他们本身就是迭代器对象,因此不能拥有多个位于不同位置的迭代器
# map将每一个可迭代对象传入func函数,并将所有的结果收集起来,返回一个可迭代对象
def func(x):
    return abs(x)
arr = [1, -5, 8, -34]
re = map(func, arr)

[1, 5, 8, 34]

def func(x):
    if x > 0:
        return True
    else:
        return False
arr = [1, -5, 8, -34]
re = filter(func, arr)
[1, 8]

列表推导

x = [i**2 for i in range(10) if i > 3]

生成器表达式

#  记住了生产规则,但是还没有进行生产
x = (i**2 for i in range(10) if i > 3)
<generator object <genexpr> at 0x7f60c7bce110>
# 通过使用yield语句,用户定义的函数可以被转换成可迭代的生成器函数
def func(x):
    for i in range(x):
        yield i
x = func(5)
for i in x:
    print(i)

帮助

help(list)
help(list.pop)
arr = [1,23,3]
help(arr)

函数

  • 默认返回值None
  • 函数是运行时创建的

作用域

  • 查找顺序: 局部 -> 外层def -> 全局 -> 内置

  • 内层不能直接修改外层,但可以读,如要写,使用nolocal和global

  • 模块导入之后,全局变量变成模块的属性

  • 全局作用域仅限于单个文件,当听到全局时,就应该联想到模块

global

C 语言中,函数可以直接读写全局变量。在python中,函数可以读全局变量,如要要写全局变量,必须使用global 声明一下。

  • global 能创建一个不存在的全局变量
  • global 声明会将变量映射到外层模块
g_x = 99

def func():
    global g_x
    global g_x = 111 # 这是错误写法,global只能用来声明
    g_x = 100
func()
print(g_x) # 100

nolocal

闭包会将外层def中的变量包入函数中。nolocal 声明一个外层def的变量,便可修改外层def 中的变量

lambad

lambda是一个表达式,而不是语句。lambda是为编写简单函数而设计的

# :之前是参数,:之后是返回值
lambda x : x**2
lambda x, y=10, z=100 : x + y + z

参数

不可变参数: 本质上传入了值

可变参数: 本质上传入了指针

  • 默认参数必须在最右侧

参数顺序

  • 定义时

    • 一般参数
    • 默认参数
    • *name
    • keyword-only
    • **name
  • 调用时

    • 基于位置的参数
    • 关键字参数
    • *iteration
    • **dict

记录函数调用状态

# 以记录函数调用次数为例子
def maker():
    count = 0
    def func(x):
        nonlocal count
        count += 1
        print(x, count)
    return func
f = maker()

def func(x):
    func.count +=1
    print(x, func.count)
func.count = 0

函数注释

def func(a: "spam", b: (1,100), c: float) -> int:
    return a + b + c
def func(a: "spam" = 4, b: (1,100) = 5, c: float = 6) -> int:
    return a + b + c

map

对每一个元素都进行一个操作,并把其结果(return值)收集起来。放在一个可迭代对象中。

def inc(x): return x + 10
arr = [1, 2, 3, 4]
I = map(inc, arr)

filter

依次传入元素,若以该元素为参数的函数返回True,则将该元素保留,最终返回包含全部元素的可迭代对象

list(filter((lambda x: x>0), range(-5,8)))

reduce

from functools import reduce
re = reduce((lambda x,y : x+y), [1,2,3,4,5])
re == 10
# 返回结果,并不返回可迭代对象

标准推导语法

# x,y,z 是嵌套关系,并不是并列(像zip那样)
[ f(x,y,z)  for x in iterable1 if condition1 
 			for y in iterable2 if conditoin2
 			for z in iterable3 if condition3
]

res = [ x+y for x in [0,1,2]  if x > 1 
       		for y in [100,200,300] if y > 200
      ]
res == [302]

生成器函数

生成器将产生一些列值的时间分散到每一次循环迭代中去

def func(N):
    for x in range(N):
        yield x**2

f = func(4) # f是一个迭代器对象
print(next(f))
print(next(f))
print(next(f))
print(next(f))
print(next(f))

❯ python try.py
0
1
4
9
Traceback (most recent call last):
  File "/home/orange/code/python/try.py", line 10, in <module>
    print(next(f))
StopIteration

生成器表达式

是单遍迭代对象

G = (x**2 for x in range(100))
G is iter(G) #true

模块

import执行时,会逐行运行在目标文档中的语句从而构建其中的对象

import 步骤

  • 找到模块文件
  • 编译字节码(.pyc文件,如果需要的话)
  • 执行模块的代码来创建其定义的对象

python会把已加载的模块存储到一个名为sys.modules的表中,并在每次导入操作的开始检查该表。如果模块不存在,则启动三个步骤。

字节码集中存放在 __pycache__子目录中,并在文件名中加入python版本号

模块搜索路径

  1. 程序主目录
  2. PYTHONPATH目录 (环境变量)
  3. 标准库目录
  4. 任何.pth 文件中的内容,文本文件一行一行列出目录(如果存在的话)
  5. 第三方拓展应用的 site-packages 主目录
  6. sys.path 里面存放着所有的路径,可以修改
from module import xxx
from module import *
from module import func as mfunc
from module2 import func as m2func
import m as my_m

import 和 from 是赋值语句

  • import 将整个模块对象赋值给一个单独的名称
  • from 将一个或多个名称赋值给另一个模块中的同名对象
# small.py
x = 1
y = [1,2]

# main.py
from small import x,y
# 等价于 x = small.x  y = small.y
x = 100
y[0] = 99

import m

print(m.x) #1
print(m.l) #[99,2]

# small.x == 1 
# small.y== [99,2]

模块中的函数,修改全局变量,永远修改的是自己模块中的全局变量

重新加载

reload 会在原位置修改模块对象,reload 并不会删除并重新创建模块对象

import module
from imp import reload
reload(module)

模块包

python代码的目录被称为包,包导入是把计算机上的目录变成另一个python命名空间,其属性对应于目录中所包含的子目录和模块文件。

# dir0/dir1/dir2/mod.py
import dir1.dir2.mod
from dir1.dir2 import x
# dir0 位于搜索路径中,或者没有dir0就是顶层py文件所在的目录,即main.py 与dir1在同一文件夹下

#说明
# dir0/dir1/dir2/mod.py
import dir1.dir2.mod
#dir1和dir2中必须含有一个 __init__.py文件,而dir0不需要
#dir0必须在搜索路径中

#__init__.py 中的python代码会在第一次导入一个路径的时候被自动执行,所以他们也被用作执行包的初始化步骤的钩子


import x.y.mym as mylib
mylib.func()

❯ tree
.
├── main.py
└── x
    ├── __init__.py
    ├── __pycache__
    │   └── __init__.cpython-310.pyc
    └── y
        ├── __init__.py
        ├── mym.py
        └── __pycache__
            ├── __init__.cpython-310.pyc
            └── mym.cpython-310.pyc
            
posted @ 2022-04-09 19:16  orangeQWJ  阅读(58)  评论(0编辑  收藏  举报