Skip to content

Python入门

安装python环境

https://www.python.org/downloads/release/python-3133/

  • 自定义安装, 勾选Path, 自动配置环境变量
  • 验证 py --version

1745233857352

常用数据类型

数值

  • 数值分整数, 浮点数, 复数(int, float, complex)

序列

  • 序列分字符串(str), 可变有序列表(list), 不可变有序元组(tuple)

  • list和tuple可放多个类型, 如[0,'a'], (1, 'b')

    # list常用操作
    list.insert(index,val)
    list.append(val)
    list.extend(可迭代对象)
    
    list.remove(val)
    lit.reverse()
    list.pop(index), 不指定索引则移除最后一个元素
    list.copy()
    list.clear()
    
    len(list)
    len(list[0])得到list[0]元素的长度
    list.count(val)得到val在列表中出现的次数
    
    list.sort()
    sort(list) 返回新的排序后的列表
    # 元组支持不可变序列的全部内置操作
  • 字符串常用函数

  # 可以使用单引号, 双引号, 三引号, 主要用于规避转义
  print('"哈哈"')

  # 字符串中嵌入变量, f"{变量}"
  x=123
  print(f"x={x}")

  # 判断包含与否
  # True
  print("x" in "123x456")
  # False
  print("xy" not in "123xy456")

  # 字符串拼接
  # xy
  print("x"+"y")
  # xyxyxy
  print("xy"*3)

  # 切片取最后一个字符
  print("xyz"[-1])# z
  print("xyz"[0,1])# 取0到1的切

  print("xyzxyvsad".count("x"))#2
  print("xyzxyvsad".isalnum())#True, 判断字符串中全为字符或数字, 且至少有一个字符
  print("xyzxyvsad".isalpha())#True, 判断字符串中全为字符, 且至少有一个字符
  print(",".join("xyzxyvsad"))#x,y,z,x,y,v,s,a,d
  print("x.y.z".split("."))#['x', 'y', 'z']
  print("xyz".startswith("x"))#True

映射类型

  • dict, 键值对字典, 如
  • 键不能重复, 值可以为空
  • 整数1和浮点数1.0会被当做相同的键
# 常用操作
# 定义新字典
1. 使用花括号定义: {"name":1,"age":2}
2. 使用类型构造器: dict(one=1,two=2)
3. 使用字典推导式: {x: x**2 for x in range(10)}

del dict_name[index]

# 常用函数
dict.items() #查看所有元素
dict.keys()
dict.values()
dict.get(key) #或dict[key]

# 遍历
for k,v in dict.items()

# 新增
dict[key]=value

len(dict)
key in dict
pop("key")
popitem() # 移除最后一个元素

dict.setdefault(k,v) # 就是java的computeIfAbsent

dict|=new_dict # 3.9及以上版本才支持, 将new_dict的键和值更新dict

dict=dict(zip(list1,list2)) #zip()将2个列表合并成字典

集合类型

  • set, 无序不重复集合
  • frozenset, 不可变集合
# 集合常见操作
len(s) 返回集合s的元素数量
x in s
set <= other
set < other

add()
remove()
pop()
clear()

示例: 元组去重
color=("a","b","z","a")
new_color=set(color)
new_color2=tuple(new_color)

布尔类型

  • bool, True或False

二进制类型

  • bytes, 不可变字节序列, 如b'hello'
  • bytearray, 可变字节序列, 如bytearray(b"abc")

None

  • NoneType表示空值或无意义, 如None

Class

  • 自定义类型

python语法

https://docs.python.org/zh-cn/3.13/tutorial/index.html

变量

# 变量输入输出
var1=input("请输入: \n")
print("hello world")
print(var1)

# 连续赋值
z=y=var1
# 多个变量赋值
a,b=1,2

分支判断

if

num=10
if num %2==1:
    print("num是奇数")
elif num %2==0:
    print("num是偶数")
else:
    print(f"num的值是{num}")

match

# 类似switch, 3.10以上版本才支持, _为通配符
match http_response_status:
    case 400|403:
        print("Bad request")
    case 404:
        print("Not Found")
    case _:
        print("Something's wrong with the internet")

while

num=1
while num <=10:
    print(f"num --> {num}") 
    num+=1
    if num==3:
        continue;
    if num==5:
        break;

# 遍历列表
list1=[1,2,3]
while list1:
    print(list1.pop())

for

for i in range(1,5):
    print(i);
  
for k,v in {"name":"sa","age":"12"}.items():
    print(f"{k}-{v}");


for e in enumerate({"name":"sa","age":"12"}.items()):
    print(f"{e[0]}-->{e[1][0]}-{e[1][1]}");
#0-->name-sa
#1-->age-12

list=[i*i for i in range(1,5) if i >2]
print(list)# [9,16] 这种推导的集合也行, 但注意range是左闭右开

输入输出

input函数

x=input("请输入: ");
print(x)

命令行参数

#argparse-用户友好的命令行选项解析器, 需要py3.2以上版本支持
import argparse
parser=argparse.ArgumentParser(description="演示")
parser.add_argument("-n",type=int, default=10,help="随便输一个, 带-为可选参数")
args=parser.parse_args()
print(f"你输入的参数是 {args.n}")
-------------------------------------
PS C:\xz\code2\python-demo> & C:/python/python.exe c:/xz/code2/python-demo/1.py
你输入的参数是 10
PS C:\xz\code2\python-demo> & C:/python/python.exe c:/xz/code2/python-demo/1.py 1
usage: 1.py [-h] [-n N]
1.py: error: unrecognized arguments: 1
PS C:\xz\code2\python-demo> & C:/python/python.exe c:/xz/code2/python-demo/1.py -number=123
你输入的参数是 umber=123
PS C:\xz\code2\python-demo> & C:/python/python.exe c:/xz/code2/python-demo/1.py -n=111   
你输入的参数是 111
PS C:\xz\code2\python-demo> & C:/python/python.exe c:/xz/code2/python-demo/1.py --help
usage: 1.py [-h] [-n N]

演示

options:
  -h, --help  show this help message and exit
  -n N        随便输一个, 带-为可选参数4
----------------------------------
# getopt-c风格命令行选项解析器, 略

F-string函数

# 字符串输出还有%s, 以及format函数, 因为py3.6新增的f-string更方便, 因此前两种略

# F-string中的{}可以实现数学计算, 子字符串连接, 函数执行等计算任务, 类似于js
f"{print(1)}"

# F-strings可以调整输出的宽度和精度, 格式为f"{对象:宽度.精度类型}"

number=123.4567
# 宽度
print(f"{number:10}")#指定10个宽度, 默认向右对齐
print(f"{number:-10}")#-10, 可向左对齐
print(f"{number:010}")#以0补位
print(f"{number:4f}")#指定为浮点数, 默认保存小数点后6位
# 精度
print(f"{number:.3f}")#指定为浮点数, 默认保存小数点后3位, 会自动四舍五入
--------------------
PS C:\xz\code2\python-demo> & C:/python/python.exe c:/xz/code2/python-demo/1.py
  123.4567
  123.4567
00123.4567
123.456700
123.457

文件处理

file_handler=open("/temp/xxx.txt", mode="r", encoding="utf-8")
file_handler.write("123")
file_handler.close(3)

mode: 默认读取r, 写入并覆盖w, 写入追加a, 二进制模式b, 支持读取和写入+
注意: 需要写入并支持读取, 则使用w+或是a+

# 关于编码问题
win默认使用GBR编码, Linux和macOS使用UTF-8编码

# 文件读取
read(size) # 返回指定size
readline()
readlines(size) # 返回指定size行数
for line in file # 迭代

# 使用with函数自动close文件如下示例
with open("C:\\Users\\xinzhang0618\\Desktop\\xinzhang-note.conf") as file:
    print(file.readlines())

函数

# py3.5以上版本能够支持类型提示, 但类型提示仅能提示, 不能用于类型检查
def func(x:int, y:int)->int:
    return x+y;
print(func(1,1))

# 可以使用关键字参数改变参数位置, 以及赋予默认值, 关键字参数和形式参数可以混用
file_handler=open("/temp/xxx.txt", mode="r", encoding="utf-8")

# 可变长度参数
# *接收位置参数-以元组方式存储, **接收关键字参数-以字典形式存储
def address_book(name, *tel, aname=None, **custom):
    """这是个可变参数的接口示例"""
    print(f"name: {name}, tel: {tel}, aname: {aname}, custom: {custom}")


address_book(
    "张三", 123, 456, 789
)  # name: 张三, tel: (123, 456, 789), aname: None, custom: {}

address_book(
    "张三", 123, 456, 789, custom={"home": "guangzhou"}
)  # name: 张三, tel: (123, 456, 789), aname: None, custom: {'custom': {'home': 'guangzhou'}}

address_book(
    "张三", 123, 456, 789, aname="小张", custom={"home": "guangzhou"}
)  # name: 张三, tel: (123, 456, 789), aname: 小张, custom: {'custom': {'home': 'guangzhou'}}


# 特殊情况
def address_book2(name, *, age):
    print("这里只处理第一个和最后一个参数, 第二个参数忽略")

# 查看函数文档
print(address_book.__doc__)  # 这是个可变参数的接口示例
# 查看函数的内省
print(dir(address_book))

# 高阶函数
# map()将可迭代对象的每个元素作为函数参数执行
print(list(map(lambda x: x + x, range(5))))  # [0, 2, 4, 6, 8]

# filter(), 过滤到可迭代对象中返回值不为True的元素
print(list(filter(lambda x: x > 0, (-2, -1, 2, 3))))  # [2, 3]

# reduce(函数, 可迭代对象), 对可迭代对象进行累计
from functools import reduce

print(
    reduce(lambda x, y: x + y, [1, 2, 3, 4, 5])
)  # 15, 1+2, 再将结果3+3, 再将结果6+4...

# 偏函数, 固定某个参数,形成新的函数, 其实就是方法重载, 固定一个参数
from functools import partial

int_16 = partial(int, base=16)  # 将int()函数固定16进制的参数
print(int_16("0f"))

wopen = partial(open, mode="w", encoding="UTF-8")
f = wopen("a.txt")
f.write("123")
f.close

 # 变量作用域: LEGB规则
# Local 本地变量->方法内部的局部变量
# Enclosed 闭包变量->函数内的再次定义的内部函数形成闭包(就是嵌套的方法), 闭包作用域之内, 内部函数可以访问外部函数的变量
# Global 全局变量
# Builtin 内置变量->导的包内部的变量

def out():
    n=100
    def bar():
        return n;
    return bar;
f=out()
print(f())# 或是out()(``)

装饰器模式

# 未用装饰器语法
import time


def func():
    print("func方法执行---")
    time.sleep(1)


def funcCounter(func: func):
    start = time.time()
    func()
    end = time.time()
    print(f"func方法执行耗时: {end-start:.2f}s")


funcCounter(func)
  • 使用装饰器语法+@wraps
# 使用装饰器语法
from functools import wraps 
import time

def my_decorator(func2):
    @wraps(func2)
    def wrapper(*args,**kvargs):
        """wrapper docstring"""
        start = time.time()
        func2()
        end = time.time()
        print(f"{func2.__name__}方法执行耗时: {end-start:.2f}s")
        print(f"{func2.__name__}方法的doc: {func2.__doc__}")
        return func2
    return wrapper


@my_decorator
def func2():
    """original docstring"""
    print("func2方法执行---")
    time.sleep(2)

func2(123);

--------------------
func2方法执行---
func2方法执行耗时: 2.00s
func2方法的doc: original docstring

面向对象

类定义

# 类的基本定义
class Man:
    age=0;
    name="zhangsan";
  
    def getNickName(self):
        self.nickName="小张" # 定义方法内部属性

# 类的构造方法
class Man:
    def __init__(self,name,age):
        self.name=name;
        self.age=age;
  
    def getInformation(self):
        print(self.name)
        print(self.age)

man=Man("张三",18)
man.getInformation();

类的继承与混入

# 父子类继承, 类可以多继承, 通过有向无环图按顺序遍历继承图
class Father:
    def run(self):
        pass

class Son(Father):
    def run(self):
        super().run();
        print("run")

f=Son()
f.run()  # run

print(f._mro_) #查看继承顺序


# 混入, Mix-In, 借用多继承的语法,为现有类增加新的方法, 类似于抽象类, 但是又是前端的叫法
# 混入不定义新的属性, 只包含方法
# 混入便于重用, 但决不能实例化
# 混入类一般在类名称后增加Mixin
# 定义一个日志记录的 Mixin
class LoggableMixin:
    def log(self, message):
        print(f"[LOG] {self.__class__.__name__}: {message}")


# 定义一个可序列化的 Mixin
class SerializableMixin:
    def to_dict(self):
        return {
            key: value
            for key, value in self.__dict__.items()
            if not key.startswith("_")
        }


# 创建一个使用多个 Mixin 的主类
class User(LoggableMixin, SerializableMixin):
    def __init__(self, name, email):
        self.name = name
        self.email = email
        self.log(f"User {name} created")  # 使用 LoggableMixin 的方法


# 使用示例
if __name__ == "__main__":
    user = User("Alice", "alice@example.com")

    # 使用 SerializableMixin 的方法
    user_data = user.to_dict()
    print("Serialized user data:", user_data)

    # 使用 LoggableMixin 的方法
    user.log("This is a test log message")

----------------------
[LOG] User: User Alice created
Serialized user data: {'name': 'Alice', 'email': 'alice@example.com'}
[LOG] User: This is a test log message

类装饰器

# 类装饰器

# classmethod装饰器, 将实例的方法定义为类的方法, 类似于java的静态方法

# staticmethod装饰器, 不需要类的任何信息但又和类相关的一些方法, 为了方便维护代码并保持代码工整, 可以将该函数定义到类中并使用staticmethod修饰
# staticmethod修饰的方法不需要使用self或cls

# property装饰器, 将方法装饰为属性, 对应的是xx.setter, 有点类似于java的getter/setter
class Man:
    @classmethod
    def say(cls):
        print("man bron can say")

    def run():
        print("run")

    @property
    def age(self):
        return self.__age

    @age.setter
    def age(self, val):
        self.__age = val


Man.say()  # man bron can say
Man.run()  # run

m = Man()
m.age = 18  # 18
print(m.age)

模块

# from包import模块as别名
from os import getcwd
print(getcwd())  # C:\xz\code2\python-demo

# 标准库中的常见组件
#内置函数, 类型, 异常, 数字, 文件和目录, 通用操作系统
#并发执行, 网络和进程间通信, 互联网协议

# 编写自定义模块时调试用
if __name__=="__main__":
    print("模块直接被执行时, name为main, 这个if, 可用作调试的场景")
elif __name__=="1":
    print("模块被导入时, name为模块的名称")
else:
    pass

安装使用第三方模块, 虚拟环境

# 使用pip安装第三方模块
pip install xxx
# 使用venv建立虚拟环境
python -m venv xxx
# 将当前安装的包及其版本保存到文件中
pip freeze > requirements.txt
# 查看当前有哪些安装的包
pip freeze
# 激活虚拟环境
source xxx/bin/activate
# 在虚拟环境中导入指定的包
pip install -r requirements.txt
# 离开虚拟环境
deactivate

# 加速第三方模块安装
- 临时加速
pip install -i https//xxx package_name
- 永久加速
cat ~/pip.conf

[global]
index-url=http://mirrors.aliyun.com/pypi/simple/
[install]
trusted-host=mirrors.aliyun.com

异常

# BaseException 所有内置异常的基类
# Exception 所有内置的非系统退出类异常都派生自此类, 所有用户自定义异常也应当派生自此类
# ArithmeticError, 用于派生针对各种算数类错误而引发的内置异常
# BufferError, 当与缓冲区相关的操作无法执行时此基类将被引发
# LookupError, 用于派生当映射或序列所使用的键或索引无效时引发的异常

try:
    file = open("a.txt", encoding="UTF-8")
except FileNotFoundError as e:
    print("文件不存在")
except Exception as e:
    print(f"未知异常: {e}")
else:
    file.write("123")
finally:
    file.close()

# 自定义异常
class BizError(Exception):
    def __init__(self, msg):
        self.msg = msg

    @property
    def message(self):
        return f"发生业务异常: {self.msg}"


try:
    raise BizError("模拟业务异常")
except BizError as e:
    print(e.message)

扩展数据类型

命名元组

# 命名元组, namedtuple()是命名元组的工厂函数
from collections import namedtuple

# 使用命名元组可以快捷的定义一个坐标
Point = namedtuple("Point", ["x", "y"])
p1 = Point(11, 22)
p2 = Point(33, 44)
print(p1 + p2)  # (11, 22, 33, 44)

# 覆盖默认的加减方法, 可以实现坐标的加减
class Point_2D(namedtuple("Point", ["x", "y"])):
    def __add__(self, other):
        self.other_x, self.other_y = other
        return self.x + self.other_x, self.y + self.other_y

    def __sub__(self, other):
        self.other_x, self.other_y = other
        return self.x - self.other_x, self.y - self.other_y


p3 = Point_2D(11, 22)
p4 = Point_2D(33, 44)
print(p3 + p4)  # (44, 66)
print(p3 - p4)  # (-22, -22)

双端队列

from collections import deque
# 列表在两端操作效率低
lst = [1, 2, 3, 4]

# 在列表左侧添加元素 (O(n) 操作)
lst.insert(0, 0)  # 不推荐频繁使用

# 在列表左侧删除元素 (O(n) 操作)
del lst[0]  # 不推荐频繁使用

# deque 更适合这种操作
d = deque([1, 2, 3, 4])
d.appendleft(0)  # O(1) 操作
d.popleft()  # O(1) 操作

计数器

from collections import Counter

# 统计单词频率
text = "to be or not to be that is the question"
words = text.split()
word_counts = Counter(words)
print(word_counts)  # 输出: Counter({'to': 2, 'be': 2, 'or': 1, 'not': 1, 'that': 1, 'is': 1, 'the': 1, 'question': 1})

# 找出最常见的单词
common_words = word_counts.most_common(3)
print("最常见的单词:", common_words)  # 输出: [('to', 2), ('be', 2), ('or', 1)]

# 统计字符频率
char_counts = Counter("hello world")
print("字符频率:", char_counts)  # 输出: Counter({'l': 3, 'o': 2, 'h': 1, 'e': 1, ' ': 1, 'w': 1, 'r': 1, 'd': 1})

# 统计列表中重复项
data = [1, 2, 2, 3, 3, 3, 4, 4, 4, 4]
value_counts = Counter(data)
print("值出现次数:", value_counts)  # 输出: Counter({4: 4, 3: 3, 2: 2, 1: 1})

字典和列表子类化

#UserDict, 适用于需要自定义字典的场景, 数据实际存储在data属性中

感觉用的不多, 示例略

魔术方法

魔术方法是Python预先定义好有特定功能的一类方法, 可以理解为数据类型的接口, 改变数据类型, 通常通过重写魔术方法来实现

魔术方法是以双下划线(__)开头和结尾的方法,也称为"dunder methods"(double underscore的缩写)。

1746281970629

线/进程池

# ThreadPoolExecutor线程池, ProcessPoolExecutor进程池
from concurrent.futures import ThreadPoolExecutor

import concurrent.futures
import urllib.request

URLS = [
    "http://www.baidu.com",
    "http://www.baidu.com",
    "http://www.baidu.com",
    "http://www.baidu.com",
    "http://www.baidu.com",
    "http://www.baidu.com",
]


def load_url(url, timeout):
    with urllib.request.urlopen(url, timeout=timeout) as conn:
        return conn.read()


with concurrent.futures.ThreadPoolExecutor(max_workers=2) as executor:
    # Future = Executor.submit(fn, *args, **kwargs), *args: 传递给函数的位置参数
    # 返回一个key是future对象, value是url的字典
    future_to_url = {executor.submit(load_url, url, 60): url for url in URLS}
    # as_completed()方法传入一个可迭代对象, 这里传入是ok的, 因为字典默认迭代的是键
    for future in concurrent.futures.as_completed(future_to_url):
        url=future_to_url[future]
        try:
            data=future.result()
        except Exception as e:
            print(f"{url} generated an exception: {e}")
        else:
            print(f"{url} page is {len(data)} bytes")

多进程通信

# 队列
from multiprocessing imiport Queue

q=Queue(3) #限制容量为3
q.put("1")
q.get()
q.full()
q.empty()

# 管道
from multiprocessing import Pipe
a, b=Pipe() #双工的, 可互相发送接收信息
a.send("123")
b.recv()

# 共享内存, 用的更少
from multiprocessing import shard_memory
shm=shared_memory.SharedMemort(created=True,size=10)

补充

  • 使用numpy, matplotlib可以绘制2维甚至3维图表
pip install numpy,matplotlib -i https://mirrors.aliyun.com/pypi/simple/
  • http服务端
 py -m http.server -b 127.0.0.1 8080