Py基础

一、预备节

1.0 小tips:

没有自增++,只能+=自增

1.1 标识符:

标识符由字母、数字、下划线组成。
不能以数字开头,区分大小写。

  • 下划线开头_foo的代表不能直接访问的类属性,需通过类提供的接口进行访问,不能用 from xxx import * 而导入。
  • 双下划线开头的__foo 代表类的私有成员。
  • 双下划线开头和结尾的__foo__ 代表 Python 里特殊方法专用的标识,如 __init__() 代表类的构造函数。

1.2 注释:

  • 单行注释:# 注释内容(选中后 ctrl+/ 可以快速多行)
  • 多行注释:''' 注释内容 ''' 或者""" 注释内容 """
    注释不支持嵌套

1.3 模块导入:

import 与 from...import... 导入相应的模块(module)。

一个 module 里面可以包括多个 function

  • 将整个模块module(somemodule)导入,格式为: import somemodule。调用模块中的函数时需要somemodule.func;
    • 如果import的语句比较长,导致后续引用不方便,可以使用import .. as 别名语法
  • 从somemodule模块中导入某个函数(function),格式为: from somemodule import function。调用这个函数则直接使用即可func;
  • 从somemodule模块中导入多个函数,格式为: from somemodule import firstfunc, secondfunc, thirdfunc;
  • 将某个模块中的全部函数导入,格式为: from somemodule import *;

1.4 时间等待

import time
import asyncio
import threading

time.sleep(1) # **所在线程**强制宕机1s(自己魂不守舍1s)
asyncio.sleep(1)  # 任务(所在函数)强制暂停1s(做的活1s之内自己不能碰它)
threading.Event().wait(1) # 类似sleep,如果内置flag为True将立即返回,否则阻塞线程至等待阻塞状态,等待其他线程调用set()

1.5 内置函数

1.5.1 eval(num)

执行一个字符串表达式,并返回表达式的值

本质上是 str -> int
eval(‘0x23’) 结果是 35

1.5.2 .replace('0x','')

将前者的字符、字符串替换成后者

1.6 计算

1.6.1 除法

1、 / 操作符(真除法)
计算器除法

2、 // 操作符(Floor除法)
取整除法

1.6.2 四舍五入 round()

round(num[,index]) 

不写index时默认 = 0 (四舍五入取整)
index只保留几位小数四舍五入

1.6.2 16bit R取高取低

R & 255  # 留低8位
R & 0xff    # 同上
R >> 8   # 留高8位
(R >> 2) & 3  # 取低3、4位 

1.7 数据类型

1.7.1 基本数据类型

1.7.2 Enum枚举

此小结为其他博主总结,原址,这里取自己想要的摘录
在py中普通的有穷集合可以使用class来实现,但是会有两个问题:

  1. 枚举项不能出现重复,即key不应该相同(左)
  2. 枚举值不能在外部修改,声明好了不能随意修改

这就可以使用继承枚举类的方法 :

from enum import Enum
#@unque           # 导入`unique`可以限制value也必须不同
class Weekday(Enum):
    monday = 1
    tuesday = 2
    wednesday = 3
    thirsday = 4
    friday = 5
    saturday = 6
    sunday = 7
    test = 3    # value 可以重复,但是name(key)不可以重复
 
print(Weekday.wednesday)         # Weekday.wednesday      
print(type(Weekday.wednesday))   # <enum 'Weekday'>
print(Weekday.wednesday.name)    # wednesday
print(Weekday.wednesday.value)   # 3

承Enum基类之后,一个枚举类中的key和value,key不能相同,但是value可以相同。
对于枚举成员,.name.value是其内置属性,此外我们还可以给枚举成员增加其他属性。实现的方式如下:

Weekday.wednesday.label = "星期三"
Weekday.wednesday.work = "完成假期作业"
Weekday.wednesday.time = 10
 
print(Weekday.wednesday.label)   # 星期三
print(Weekday.wednesday.work)    # 完成假期作业
print(Weekday.wednesday.time)    # 10

在获取枚举类型的成员时,我们可以通过类名.key的方式实现,即上面的Weekday.wednesday。此外,通过key获取枚举成员的时候,还可以使用Weekday['key']这样的方式。
也可以通过类名(value)来获取枚举成员:

obj_1 = Weekday.wednesday
print(obj_1.label)             # 星期三
 
obj_2 = Weekday['wednesday']
print(obj_1.label)             # 星期三
 
obj_3 = Weekday(3)
print(obj_3.label)             # 星期三

1.8 时间库 datetime

[使用说明]
菜鸟教程
official

1.9 切片

a[start:stop{:step}] 左闭右开

1.10 nonlocal

在Python中, nonlocal 关键字用于在嵌套函数中声明一个非局部变量。它允许您在内部函数中访问和修改外部函数的变量。
nonlocal 关键字只能在嵌套函数中使用,而不能在全局作用域中使用。它用于解决内部函数无法直接访问外部函数的变量的问题。

def outer_function():
    x = 10
     def inner_function():
        nonlocal x
        x = 20
     inner_function()
    print(x)  # 输出: 20
 outer_function()

在这个例子中, nonlocal x 语句声明了变量 x 为非局部变量,并在内部函数 inner_function 中对其进行了赋值。

1.11 int16 转 uint16

  1. &
  num & 0xFFFF   #-100 & 0xFFFF = 65436
  2. struct
  import struct
  struct.unpack('<H',struct.pack('<h',num))[0]
  3. 计算
  if num<0:
    num += 65536

二、流程控制

2.1 遍历取值

2.1.1 range

可以生成序列

#左闭右开 [),一个参数时默认初值=0
range([初值,]终值[,步长])

2.1.2 dic.items()

同时取出key与value

2.1.3 enumerate

同时取出index与value

2.1.4 zip(A,B)

按次序匹配其中元素

2.2 循环

2.2.1 for

for 参数 in 遍历条件:  

for 参数 in 遍历条件:
else:		#else子句会在循环抵达最后一次迭代后执行

2.3 条件

2.3.1 if

#1.
if 条件:
	
#2. 
if 条件:
else:

#3.		   
if 条件:
elif 条件:
else:

2.3.2 match(类似于switch)

类似其他语言中的switch,但是受限于python 3.10 以上版本

match 参数:
	case 情况1:
		操作1

语句中无需break

三、数据结构

数据类型转换

  • 不可变:Number、String、Tuple
  • 可变:List、Dictionary、Set

3.1 String(字符串):

菜鸟详解

Python 没有单独的字符类型,一个字符就是长度为 1 的字符串。
有两种索引方式,→以 0 开始,←以 -1 开始,截取左闭右开
内容不可改变

  • 字符串的截取的语法格式如下:变量[头下标:尾下标:步长]尾下标对应的(mid)会被抛弃,步长默认1
  • \可以用来转义
  • 使用 r 可以让反斜杠不发生转义。 如 r"this is a line with \n" 则 \n 会显示,并不是换行。

3.2 List(列表):[ ]

菜鸟教程-list

类似C语言的数组,多类型数组
截取、索引方式同字符串
可修改的、有顺序的、可存储任意类型

方法:

 1. append()			        末尾添加
 2. insert(index, )     	        在指定index处插入
 3. del 			        删除元素		
 4.  pop(index)			弹出元素,不写index默认为末尾
 5.  remove(‘内容’)		        根据内容删除元素
 6. sort(reverse = True)		按照首字母大小顺序排序(括号内不填默认从a---z)
 7. sorted()				不改变原表顺序排序
 8. reverse()				倒序排序
 9.  len(list)				获取长度
 10. list.count(a)                      获取a出现的次数
 11.  list(range(1,5,step))  	返回1-4范围数,转化为list,step为步长
 12.  min\max\sum( )        		最小\最大\求和
 13.  [0:3]				切片从0-3(:的两侧如果不填则是全选,用于创建副本)

 *******单单 List1 = List2 只是将 List1 关联到包含 List2 的列表中,并未生成副本*******

 14. A (not)in List			判断 A 是(否)存在List中
 15. ListA + ListB                      合并列表

3.3 Tuple(元组):()

菜鸟教程-tuple

  • 类似 list,但元素不可修改
  • 元组中只包含1个元素时,需要(元素1,) ,否则括号会被当作运算符使用
  • 按索引修改元素值非法,但是可以 tuple1 + tuple2 连接2个tuple,也可以使用 del tuple1 删除tuple

3.4 Set(集合):{}

菜鸟教程-set

(set)无序不重复,本身可变,但元素必须是不可变的

  • 可以使用大括号 { } 或者 set() 函数创建集合
  • 集合间可以进行交并差补运算(&、|、-、^)
  • 注意:创建一个空集合必须用 set() 而不是 {},因为 { } 是用来创建一个空字典
  • 因为无序,无法使用索引来获取集合元素 —— no index
group = set()             # 空集合
group = {value01,value02,...}   #创建集合
#或者
set(value)

3.5 Dictionary(字典):{}

菜鸟教程-dict

key:value,查找元素的索引从数字变成 key 近似于结构体,属性一一对应
可变数据

空字典:

  dict1 = {}     # “{}” 是空字典,set() 是空集合

操作:

	1.Dict['key']						访问元素
	2.Dict['key'] = value				添加1对key-value元素
	3.del Dict['key']					删除元素
	4.for key,value in Dict.items():	遍历字典,key和value分别承装对应值
	5.Dict.keys()						输出key值

3.6 Number(数字):

菜鸟详解
python3 支持 int、float、bool、complex(复数)。

3.7 bytes (字节串)

官方文档

不可变的二进制序列
区别于String的是:bytes 类型中的元素是int(0 到 255 之间的整数),而不是 Unicode 字符。
bytes 字面值中只允许 ASCII 字符,无论源代码声明的编码为何,任何超出 127 的二进制值必须使用相应的转义序列形式加入 bytes 字面值

3.7.1 创建bytes对象:

  1. b""
  2. bytes(字符串,encoding=编码方式)

3.7.2 转换:

编码与解码是String与bytes间的转换:

  1. 编码:(String → bytes)
bytes = str.encode(encoding='UTF-8',errors='strict')
#errors -- 设置不同错误的处理方案。默认为 'strict',意为编码错误引起一个UnicodeError。 其他可能得值有 'ignore', 'replace', 'xmlcharrefreplace', 'backslashreplace' 以及通过 codecs.register_error() 注册的任何值。
  1. 解码:(bytes → String)
str = bytes.decode(encoding="utf-8", errors="strict")
  1. hex型的String → bytes
bytes = bytes.fromhex('2Ef0 F1f2  ')
# b`.\xf0\xf1\xf2`  在ASCII中 可显示字符 正常显示,其他的由\x带着显示
  1. bytes → hex型的String
value = b'\xf0\xf1\xf2'
value.hex()
value.hex('-',[param])

四、输入输出

4.1 用户输入:

str = input("提示信息(请输入:)")	#返回输入的字符串,可以用变量来承装
input = 'I like runoob'					

4.2 用户输出:

4.2.1 basic

print 默认输出是换行的,如果要实现不换行需要在变量末尾加上 end=""
print() 函数会略去括号内标示用的引号,并打印经过转义的特殊字符

print( x, end=" " )		       #不换行
print()							#默认换行

如果不想使转义字符\ 生效,在引号前加 r

4.2.2 %占位符

从此转载,侵删,原址:https://blog.csdn.net/python1639er/article/details/112325519
有更详细的参数解读

name = "Li hua"
age = 24
print("Hello %s, you are %d years old" % (name, age))

详解:

"... %[key][flags][width][.precision][length type]conversion type ..." % values
  • %: 必须要有的符号。它标记占位符的开始。
  • key: 选填。映射的键,由带括号的字符序列组成,一般用于后面的values是字典的场景。
  • flags: 选填。转换标志(Conversion flags), 会影响某些转换类型的结果。
  • width: 选填。最小字段宽度。如果指定为“*”(星号),则实际宽度从值中元组的下一个元素读取,要转换的对象位于最小字段宽度和可选精度之后。

    HEX 补0: %02X ; 补全:0x%02Xs

  • precision: 选填。精度,写法为.precision(点+精度)。如果指定为“*”(星号),则实际宽度从值中元组的下一个元素读取,要转换的值位于精度之后。
  • length type: 选填。长度修改器。
  • Conversion type: 必须要有的符号。转换类型,也标记占位符的开始。详细介绍

4.2.3 .format

print('hello {0} i am {1}'.format('world','python')) 

详解:

"... {[field_name][!conversion][:format_spec]} ...".format(arguments)
  • field_name: 半选填,字段名。分两种情况:

      1. 为位置参数:(选填)
      "{0} {1}"
      "{} {}"
      
      1. 为关键词参数:(必填)
      "{name} {age}"
      
      该字段完整语法格式为arg_name(.attribute_name | [element_index])*,是在arg_name对应的值为对象列表字典时使用,获取其进一步的属性值或者内部值。
      >>> "{0[name]} {0[age]}, {1[0]} {1[1]}".format({"name": "Li hua", "age": 24}, ["Zhang san",24])
      'Li hua 24, Zhang san 24'
      
  • conversion:选填。变换,不常用。指定时要用!来开头,指定后会在格式化之前将arguments中对应的值进行类型变换。

  • format_spec:选填,格式化具体规范,核心内容,超常用。填写时要用:来开头,填写后,会按照其指定的规则来进行格式化。

    [[fill]align][sign][#][0][width][grouping_option][.precision][type]
    
    • fill: 填充内容,如果指定了宽度,但变量长度不够,会使用该字段值进行填充。设置了fill,后面必须显式设置align。
    • align: 对齐方式,有< > = ^,分别为左对齐、右对齐
  • arguments:分为两种

      1. 位置参数:
      "{0} {1} {1} {0}".format("Li hua", 24)
      
      1. 关键词参数:
      "{name} {age} {age} {name}".format("Li hua", 24)
      

4.2.4 f''表达式

直接将变量写入字符串中
f"{name}"
进阶
进阶2

4.3 进制转换

博客

五、函数:

def Fun(param):		函数传参
def Fun(param=''):		函数传参(参数可传可不传,函数内用if判断)
def Fun(*param): 		任意数量参数(*可以创建1个名为canshu的空元组)
def Fun(**param): 		任意数量参数(**可以创建1个名为canshu的空字典)
Fun1 as Fun2   			起别名Fun2

5.1 函数参数

5.1.1 关键字参数

调用函数时可以指定参数名称的具体参数值

5.1.2 “仅”参数

  1. /:仅位置参数:在/前的参数全部按位置提供,不许提供关键词
  2. *:仅关键字参数:在*后的参数全部需要提供关键词
def f(pos1, pos2, /, pos_or_kwd, *, kwd1, kwd2):
      -----------    ----------     ----------
        |             |                  |
        |        Positional or keyword   |
        |                                - Keyword only
         -- Positional only

5.2 回调函数(callback)

当程序跑起来时,一般情况下,应用程序(application program)会时常通过API调用库里所预先备好的函数。但是有些库函数(library function)却要求应用先传给它一个函数,好在合适的时候调用,以完成目标任务。这个被传入的、后又被调用的函数就称为回调函数(callback function)。

5.2.1 案例

even.py:

def double(x):
    return x * 2

def quadruple(x):
    return x * 4

callback.py:

from even import *

#中间函数
#接受一个生成偶数的函数作为参数
#返回一个奇数
def getOddNumber(k, getEvenNumber):
    return 1 + getEvenNumber(k)
    
#起始函数,这里是程序的主函数

def main():    
    k = 1
    #当需要生成一个2k+1形式的奇数时
    i = getOddNumber(k, double)
    print(i)
    #当需要一个4k+1形式的奇数时
    i = getOddNumber(k, quadruple)
    print(i)
    #当需要一个8k+1形式的奇数时
    i = getOddNumber(k, lambda x: x * 8)
    print(i)
    
if __name__ == "__main__":
    main()

六、类

6.1 作用域

global 全局
nonlocal 标识该变量是上一级函数中的局部变量,如果上一级函数中不存在该局部变量,nonlocal位置会发生错误

  1. 在局部函数中只能访问全局变量,不可以对其进行修改,想修改需要在局部函数内用global修饰;
  2. 在外部函数中无法访问局部变量
  3. 如果有嵌套情况,需要修改中间层(上一次)的变量需要在局部用nonlocal,global则是修改最外层的那个。

详细解释

6.1.1 类变量(类似static)

首先,Python语言并不支持静态变量。因为Python是动态语言,不存在完全静态的变量。

  • Python中,静态成员变量称为类变量(Class.A),非静态成员变量称为实例变量(object.A)

通过修改实例类变量改变类的类变量的问题(成因:类变量为可变变量)
当类变量是不可变变量时,遵循不可变变量的特性,实例中类变量的修改或赋值是将实例中的类变量指向一个新的内存地址;
当类变量是可变变量时,直接对实例变量进行赋值不会改变类变量,但是修改实例变量则会影响类变量。

class Test():
    num = 1     # 类变量
    def __init__(self,x,y):
    ...

6.1.2 实例变量

self.变量名给出
分为:

  • 构造函数中的实例变量;(类实例化了就能使用)
  • 成员函数中的实例变量;(需要调用函数后才能使用)
class Test():
    def __init__(self,x,y):
        self.x = x  # 在初始化时(构造函数)给出的实例变量
        self.y = y
    def func1(self):
        self.t1 = 1 # 成员函数中的实例变量;
        self.t2 = 2
    def func2(self):
        print(self.x+self.t1)
def main():
    t = Test(1,2)
    t.func1()   # 如果不调用func1,则使用func2会报错
    t.func2()
if __name__ == '__main__':
    main()

6.1.3 局部变量

不带self.的,只能在当前函数中使用。

6.2 构成

6.2.1 格式

class 类名:
    <语句>
    .
    .
    .

6.2.2 构造函数(__init__()

def __init__(self):
    <语句>
    .

6.2.3 self

在类中,self只能在函数中使用,表示的是实例属性;
如果不加self,表示是类的一个属性

与普通的函数相比,在类中定义的函数只有2点不同:

  1. 第一个参数永远是 self ,并且调用时不用传递该参数。
  2. 类中函数相互调用要加 self,如c = self.add()+self.square()。
class Test(object):
    val = 1

    def __init__(self):
        self.val = 2


In [18]: test = Test()

In [19]: test.val
Out[19]: 2

In [20]: Test.val
Out[20]: 1

6.3 继承

class 子类名(父类名1,父类名2):

6.3.1 super()

Python 3 和 Python 2 的另一个区别是: Python 3 可以使用直接使用 super().xxx 代替 super(Class, self).xxx,原代表返回self的MRO(继承先后序列)中Class的父类

在python中super是个特殊的类
当我们调用 super() 的时候,实际上是实例化了一个 super类 的对象

最常见的是继承父类的构造函数,并扩写

class Student(Person):
  def __init__(self, fname, lname, year):
    super().__init__(fname, lname)
    self.graduationyear = year

6.3.2 重写(覆盖)

python中没有重载,后面的同名函数会覆盖前者

类间关系
出现了同名函数就是重写


class Dog():
    def bark(self):
        print("汪汪叫")
 
 
class ZangAo(Dog):
    def bark(self):
        print("吼吼叫")


z = ZangAo()
z.bark()     # 吼吼叫
super(Dog,z).bark() # 汪汪叫

七、多线程、进程

7.1 线程(Thread)

import threading

threading.Thread([group=None,] target=func [,daemon=True][,name=None][,args=()][,kwargs=None]).start() # 传入函数名,即刻开启单独线程
# daemon为守护线程
# name 为线程名,默认为Tread-num形式的十进制数
# args 元组形式参数
# kwargs 字典形式参数
# group 为ThreadGroup类做保留

# 同样效果
t1 = threading.Thread([group=None,] target=func [,daemon=True][,name=None][,args=()][,kwargs=None])
t1.start()

7.1.1 传参

以元组形式传参(args)
sub_thread = threading.Thread(target=task, args=(5,))
以字典形式传参(kwargs0)
sub_thread = threading.Thread(target=task, kwargs={"count": 3})

7.2.2 线程操作

  1. join暂停:
    t1.join()  # 主线程暂停运行,等待子线程t1运行结束
    

7.2 进程(Process)

import multiprocessing

multiprocessing.Process(target=run, args=('anne',)).start()

# 同上:
p1 = multiprocessing.Process(target=run, args=('anne',))
p1.start()

7.2 task

八、异步

8.1 异步背景

Async编程既不是多进程也不是多线程,是并发编程。

8.2 协程(Coroutine)

是一种比线程更加轻量级的存在,协程(Coroutine) 不是被操作系统内核所管理,而完全是由程序所控制。

多线程、进程的思想是同时起多个线程,同时或者接近同时地去执行任务,各个线程本身是无序且独立的;
Async编程在同一时间只能完成一件事,但是如果这件事很耗时间,或者很长时间都没有返回结果,此时会陷入阻塞状态,为了充分利用cpu的时间,会先处理其他可以处理的事情,等之前那件事阻塞解除了再重新回来继续处理。

async 关键词:
下文所有的用到的异步函数都需要用await asyncfun()或者asyncio.run(asyncfun())来修饰;
可以使下文提到的所有await均视为异步关键词;

如果一个对象可以在 await 语句中使用,那么它就是 可等待 对象
可等待 对象有三种主要类型: 协程, 任务 和 Future.

一般异步协程不直接写在主线程里,会导致任务非常多,如何修改?
写一个任务的主函数,在外部调用直接调用主函数

import asyncio

async def main():
  print('A')
  await asyncio.sleep(1)
  print('B')

async def func():
  print('1')
  await asyncio.sleep(2)
  print('2')

asyncio.run(main())
task = asyncio.create_task(func())  # 将函数放入task日程表,主线程空闲时可以执行task日程表中的内容

九、异常处理

分为 异常处理断言
捕捉异常可以使用try/except语句,如果你不想在 ,只需在try里捕获它。

9.1 Ctrl + C

py特有:

except KeyboardInterrupt:  
    pass  
posted @ 2023-07-25 09:02  LASER_06  阅读(34)  评论(0)    收藏  举报