高级版 - 全面覆盖Python开发核心知识点
TCP(传输控制协议)、UDP(用户数据报协议)和HTTP(超文本传输协议)是网络通信中常用的三种协议。
总的来说:TCP和UDP是传输层协议,负责数据在网络中的传输;而HTTP是应用层协议,基于TCP协议,用于规定浏览器和服务器之间的通信规则。
import smtplib
from email.mime.text import MIMEText
from email.header import Header
# 设置邮箱服务器信息
smtp_server = 'smtp.163.com'
smtp_port = 465 # 网易邮箱SMTP服务器的SSL端口
# 发送者邮箱账号和授权码
sender_email = 'your_email@163.com' # 替换为您的网易邮箱地址
sender_password = 'your_authorization_code' # 替换为您的授权码
# 接收者邮箱地址
receiver_email = '13655699934@163.com' # 指定的接收邮箱地址
# 创建MIMEText对象,设置邮件内容
msg = MIMEText('这是一封来自Python脚本的测试邮件。', 'plain', 'utf-8')
msg['From'] = Header("您的名字", 'utf-8') # 发件人名称
msg['To'] = Header("收件人名称", 'utf-8') # 收件人名称
msg['Subject'] = Header('Python脚本测试邮件', 'utf-8') # 邮件主题
# 发送邮件
try:
# 创建SMTP对象
server = smtplib.SMTP_SSL(smtp_server, smtp_port)
# 登录邮箱
server.login(sender_email, sender_password)
# 发送邮件
server.sendmail(sender_email, [receiver_email], msg.as_string())
print("邮件发送成功")
except smtplib.SMTPException as e:
print(f"邮件发送失败: {e}")
finally:
# 关闭服务器连接
server.quit()
深拷贝(deep copy)和浅拷贝(shallow copy)是两种不同的复制对象的方式。
浅拷贝指的是复制一个对象,但是并不复制该对象内部的引用指向的对象。也就是说,浅拷贝会创建一个新的容器,然后在这个容器中填充原始对象元素的引用。
import copy
# 使用copy()函数
list1 = [1, 2, [3, 4]]
list2 = copy.copy(list1)
深拷贝指的是复制一个对象以及该对象内部的引用指向的所有对象。深拷贝会创建一个完全独立的副本,包括所有子对象。
import copy
# 使用deepcopy()函数
list1 = [1, 2, [3, 4]]
list4 = copy.deepcopy(list1)
使用方式:如果你需要复制一个对象但是保持其内部引用指向的对象不变,你应该使用浅拷贝。如果你需要复制一个对象及其所有子对象,你应该使用深拷贝。
前端请求的处理流程通常涉及多个组件,下面是使用 uWSGI、Nginx 和 Django 处理一个前端请求的大致流程:
在整个流程中,Nginx和uWSGI通常配置为守护进程运行,并且可以处理并发请求,以提供高效和可靠的服务。Django作为应用服务器,专注于实现业务逻辑和生成动态内容。
Redis是一种高性能的键值数据库,它支持多种数据结构来适应不同的使用场景。以下是Redis支持的主要数据结构及其保存方式:
保存方式:Redis的字符串是二进制安全的,可以包含任何数据,如JPEG图片或序列化的对象。字符串的大小最多可以达到512MB。
# 设置一个键值对
SET mykey "Hello World"
# 获取键的值
GET mykey
保存方式:列表是一种简单的字符串列表,按照插入顺序排序。可以添加一个元素到列表的头部(左边)或尾部(右边)。列表的底层实现为一个双向链表。
# 从列表左侧插入元素
LPUSH mylist "First item"
# 从列表右侧插入元素
RPUSH mylist "Second item"
# 获取列表中的所有元素
LRANGE mylist 0 -1
保存方式:集合是无序集合,元素具有唯一性,即集合中不能有重复的元素。集合的底层实现是一个值为null的哈希表。
# 向集合中添加元素
SADD myset "item1"
# 检查元素是否在集合中
SISMEMBER myset "item1"
# 获取集合中的所有元素
SMEMBERS myset
保存方式:哈希是一个键值对的集合,适合用于表示对象。哈希表的结构使得数据访问非常快,适合存储对象及其属性。
# 向哈希中添加键值对
HSET myhash field1 "value1"
# 获取哈希中的指定字段值
HGET myhash field1
# 获取哈希中的所有字段和值
HGETALL myhash
保存方式:有序集合类似于集合,但是每个成员都会关联一个分数(score),可以根据分数对成员进行排序。有序集合的底层实现是一个跳表(Skip List)和哈希表的组合。
# 向有序集合中添加元素,并指定分数
ZADD myzset 1 "one"
# 向有序集合中添加另一个元素,并指定不同的分数
ZADD myzset 2 "two"
# 获取有序集合中的所有元素及其分数
ZRANGE myzset 0 -1 WITHSCORES
保存方式:位图不是一种实际的数据结构,而是通过在字符串类型上使用位操作来模拟的。位图适合用于存储布尔值信息,如用户是否在线。
# 设置位图中特定位置的位
SETBIT mybitmap 0 1
# 获取位图中特定位置的位
GETBIT mybitmap 0
# 计算位图中设置为1的位的数量
BITCOUNT mybitmap
保存方式:HyperLogLog是一种用于估计集合基数的概率数据结构,它使用极小的内存来存储大量的唯一值。
# 向HyperLogLog添加元素
PFADD hll "element1"
# 向HyperLogLog添加更多元素
PFADD hll "element2" "element3"
# 计算HyperLogLog的近似基数
PFCOUNT hll
保存方式:流是Redis 5.0引入的一种数据结构,用于存储记录序列,类似于日志。每个记录由一个ID和一组字段组成,这些记录按ID排序。
# 向流中添加记录
XADD mystream * key1 value1 key2 value2
# 读取流中的记录
XRANGE mystream - +
每种数据结构都有其特定的使用场景,Redis会根据数据结构的特性和使用模式来优化存储和访问效率。例如,列表可能用于消息队列,而有序集合可能用于排行榜或优先级队列。Redis的数据结构设计使其非常适合于缓存、实时分析、排行榜等多种应用场景。
Celery 是一个基于异步任务队列/消息队列的分布式任务队列/作业队列,用于在多个线程、进程或机器上执行任务。Celery 通常与消息代理(也称为消息中间件)一起使用,如 RabbitMQ 或 Redis,以在多个工作进程之间传递任务。
在实际应用中,开发者会根据项目的具体需求和团队的技能偏好来选择合适的开发模式。有些ORM框架,如Entity Framework,同时支持这两种模式,使得开发者可以根据实际情况灵活选择。
Tornado 是一个 Python Web 框架和异步网络库,最初由 FriendFeed 开发,并在 2009 年由 Facebook 开源。它以其高性能和可扩展性而闻名,特别适合处理长连接、WebSockets 和需要非阻塞网络处理的场景。
Tornado 适用于需要高并发和持续连接的 Web 应用,例如:
由于其高性能的特性,Tornado 在需要处理大量用户连接的场合特别有用,例如社交网络、游戏后端或实时通信服务。
# -*- coding: utf-8 -*-
import tornado.ioloop
import tornado.httpserver
import tornado.options
import os
import json
import threading
from tornado.options import define, options
from tornado.websocket import WebSocketHandler
import tornado.web
from tornado.web import RequestHandler
import datetime
# 全局参数定义
define("port", default=8202, type=int)
from tornado_sqlalchemy import SessionMixin
class IndexHandler(RequestHandler, SessionMixin): # 继承RequestHandler类
"""只允许 GET 请求"""
# SUPPORTED_METHODS = ["GET"]
def prepare(self):
self.form_data = {
key: [val.decode('utf8') for val in val_list]
for key, val_list in self.request.arguments.items()
}
def set_default_headers(self):
"""设置默认响应头为 json 格式的"""
self.set_header("Content-Type", 'application/json; charset="utf-8"')
def send_response(self, data, status=200):
"""Construct and send a JSON response with appropriate status code."""
self.set_status(status)
self.write(json.dumps(data))
def get(self, **kwargs):
self.render("index.html")
msg = self.get_argument("msg") # 得到post请求中的msg的值
ip = self.get_argument('ip') # 得到要发送的ip
def post(self):
msg = self.get_argument("msg") # 得到post请求中的msg的值
ip = self.get_argument('ip') # 得到要发送的ip
class ChatHandler(WebSocketHandler):
# 定义一个集合,用来保存在线的所有用户
cli = set()
def initialize(self, IotCode):
self.IotCode = IotCode
# 有新的连接时open()函数将会被调用,将客户端的连接统一放到clients
def open(self, **kw):
self.set_nodelay(True) # 设置此流的无延迟标志
# 当有新的用户上线,将该用户加入集合中
self.cli.add(self)
for c in self.cli: # 向已在线用户发送消息
c.write_message(
u"Tips [%s]-[%s]-进入系统" % (
self.request.remote_ip, datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")))
# 客户收到消息将被调用
def on_message(self, message):
for c in self.cli: # 向在线用户广播消息
c.write_message(message)
# 关闭连接时被调用
def on_close(self):
self.cli.remove(self) # 用户关闭连接后从容器中移除用户
for c in self.cli:
c.write_message(
u"Tips [%s]-[%s]-离开系统" % (
self.request.remote_ip, datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")))
def check_origin(self, origin):
# 允许WebSocket的跨域请求
return True
@classmethod
def send_message(cls, message):
removable = set()
for ws in cls.cli:
if not ws.ws_connection or not ws.ws_connection.stream.socket:
removable.add(ws)
else:
ws.write_message(message)
for ws in removable:
cls.cli.remove(ws)
class Application(tornado.web.Application):
def __init__(self):
handlers = [
(r"/", IndexHandler),
(r"/chat", ChatHandler, {"IotCode": "1236548512254555"}),
]
SETTINGS = {
'debug': False,
"static_path": os.path.join(os.path.dirname(__file__), 'static'), # 静态目录
'template_path': os.path.join(os.path.dirname(__file__), 'templates/html1/zh_CN'),
'cookie_secret': 'IOT_Message',
}
tornado.web.Application.__init__(self, handlers, **SETTINGS)
if __name__ == '__main__':
# 自动设置logging的级别
tornado.options.parse_command_line()
app = Application()
http_server = tornado.httpserver.HTTPServer(app)
http_server.listen(options.port)
# 创建线程
t1 = threading.Thread(target=tornado.ioloop.IOLoop.current().start())
向量化(Vectorization)是机器学习中一个重要的预处理步骤,它涉及将原始数据转换成更适合机器学习算法处理的格式。下面我将分别解释 one-hot 编码和数据分箱(也称为分位数分箱或分箱)。
One-Hot 编码是一种将分类数据转换为数值数据的方法,常用于机器学习预处理。每个类别值都被转换成一个只含一个"1"和一个或多个"0"的二进制向量。
步骤:
例子:
假设有一个特征"颜色",有三个类别:红色、绿色、蓝色。
颜色: 红色 → 编码: [1, 0, 0]
颜色: 绿色 → 编码: [0, 1, 0]
颜色: 蓝色 → 编码: [0, 0, 1]
import pandas as pd
# 假设 df 是一个包含颜色列的 DataFrame
df = pd.DataFrame({'颜色': ['红色', '绿色', '蓝色', '红色']})
# 使用 pandas 的 get_dummies 函数进行 one-hot 编码
df_encoded = pd.get_dummies(df, columns=['颜色'])
数据分箱是将连续数据离散化为一系列区间(或"箱子")的过程。这个过程可以有助于提高模型的性能,尤其是当某些特征具有非线性关系时。
步骤:
例子:
假设有一个特征"年龄",我们希望将其分为三个箱子。
年龄: 20 21 22 23 24 25 26 27 28 29 30
分箱: 1 1 1 2 2 2 3 3 3 3 3
import pandas as pd
# 假设 df 是一个包含年龄列的 DataFrame
df = pd.DataFrame({'年龄': [20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30]})
# 使用 pandas 的 qcut 函数进行分位数分箱
df['年龄分箱'] = pd.qcut(df['年龄'], q=3, labels=["青年", "中年", "老年"])
在机器学习中,one-hot 编码和分箱都是将非数值数据转换为数值数据的有效方法,这有助于模型更好地理解和处理数据。这两种技术通常结合使用,以准备适合训练的数据集。
在计算机科学中,栈(Stack)和堆(Heap)是两种基本的数据结构,它们在内存管理中扮演着重要角色,尤其是在程序运行时的内存分配方面。
栈是一种后进先出(Last In, First Out, LIFO)的数据结构。在栈中,数据的插入和删除操作都发生在同一端,称为栈顶。
特点:
用途:
限制:
堆是一种更加灵活的内存分配方式,它通常用于动态内存分配。
特点:
用途:
限制:
在编写程序时,合理地使用栈和堆对于优化内存使用和提高程序性能是非常重要的。
def quick_sort(arr):
# 基本情况:如果数组为空或只有一个元素,则无需排序
if len(arr) <= 1:
return arr
# 选择一个中间元素作为基准值
pivot = arr[len(arr) // 2]
# 将数组分为三个部分:小于基准值的,等于基准值的,大于基准值的
left = [x for x in arr if x < pivot]
middle = [x for x in arr if x == pivot]
right = [x for x in arr if x > pivot]
# 递归地对小于和大于基准值的部分进行快速排序,然后将结果拼接起来
return quick_sort(left) + middle + quick_sort(right)
# 示例
arr = [3, 6, 8, 10, 1, 2, 1]
print("Quick Sort:", quick_sort(arr))
def merge_sort(arr):
# 基本情况:如果数组为空或只有一个元素,则无需排序
if len(arr) <= 1:
return arr
# 找到中间位置,分割数组
mid = len(arr) // 2
left = merge_sort(arr[:mid])
right = merge_sort(arr[mid:])
# 合并两个已排序的数组
return merge(left, right)
def merge(left, right):
# 初始化结果数组
result = []
i = j = 0
# 从两个数组中按顺序取出最小的元素,直到一个数组为空
while i < len(left) and j < len(right):
if left[i] < right[j]:
result.append(left[i])
i += 1
else:
result.append(right[j])
j += 1
# 将剩余的元素添加到结果数组中
result.extend(left[i:])
result.extend(right[j:])
return result
# 示例
arr = [3, 6, 8, 10, 1, 2, 1]
print("Merge Sort:", merge_sort(arr))
def insertion_sort(arr):
# 从第二个元素开始遍历数组
for i in range(1, len(arr)):
key = arr[i] # 当前要插入的元素
j = i - 1 # 从当前元素的前一个开始比较
# 将当前元素与已排序的元素比较,如果当前元素小,则交换位置
while j >= 0 and key < arr[j]:
arr[j + 1] = arr[j]
j -= 1
# 将当前元素插入到正确的位置
arr[j + 1] = key
return arr
# 示例
arr = [3, 6, 8, 10, 1, 2, 1]
print("Insertion Sort:", insertion_sort(arr))
def bubble_sort(arr):
n = len(arr)
# 遍历数组中的所有元素
for i in range(n):
# 最后i个元素已经排好序,无需比较
for j in range(0, n-i-1):
# 如果当前元素比下一个元素大,则交换它们的位置
if arr[j] > arr[j+1]:
arr[j], arr[j+1] = arr[j+1], arr[j]
return arr
# 示例
arr = [3, 6, 8, 10, 1, 2, 1]
print("Bubble Sort:", bubble_sort(arr))
def selection_sort(arr):
# 遍历数组中的所有元素
for i in range(len(arr)):
min_idx = i # 假设当前位置的元素是最小的
# 从当前位置的下一个元素开始遍历,找到最小元素的索引
for j in range(i+1, len(arr)):
if arr[min_idx] > arr[j]:
min_idx = j
# 将找到的最小元素与当前位置的元素交换
arr[i], arr[min_idx] = arr[min_idx], arr[i]
return arr
# 示例
arr = [3, 6, 8, 10, 1, 2, 1]
print("Selection Sort:", selection_sort(arr))
在工程实践中,通常会根据具体的需求和数据特性来选择排序算法。例如,对于大多数通用场景,快速排序是一个很好的选择。然而,如果数据量非常大,可能会考虑使用归并排序或堆排序,因为它们在最坏情况下的性能更稳定。对于小数据集,简单的插入排序或冒泡排序可能就足够了。对于特定类型的数据,如整数,计数排序、基数排序和桶排序可以提供非常高的效率。
MySQL优化通常涉及以下几个方面:
多表查询通常使用JOIN操作来组合多个表中的数据。以下是几种常见的多表查询类型:
在进行多表查询时,以下是一些优化技巧:
记住,优化是一个持续的过程,需要根据实际的使用情况不断调整。多表查询的性能也受数据库设计、索引和查询本身的影响。
在Linux下查找文件,可以使用多种命令行工具。以下是一些常用的命令及其使用方法:
find 命令是Linux中最强大的查找文件的工具之一。它可以根据文件名、文件类型、文件大小、修改时间等多种标准进行搜索。
find /path/to/search -name "filename.txt"
find /path/to/search -type d
find /path/to/search -size +100M
find /path/to/search -mtime -1
locate 命令通过查询一个数据库来快速找到文件,这个数据库通常每天更新一次(通过updatedb命令)。它不如find灵活,但速度更快。
locate filename.txt
grep 命令用于搜索文件内容。结合-r(递归)和-l(只列出文件名)选项,可以用来查找包含特定文本的文件。
grep -rl "特定文本" /path/to/search
which 命令用于查找可执行文件的位置。
which executable_name
mlocate 是locate的一个改进版本,具有实时更新的能力。
mlocate filename.txt
闭包(Closure)在计算机科学中是一个比较抽象的概念,尤其在函数式编程语言中非常重要。简单来说,闭包是指那些能够访问自由变量的函数。"自由变量"是指在函数定义时处于环境中的变量,而不是函数的参数或局部变量。
在JavaScript、Python等支持闭包的编程语言中,闭包具有以下特性:
在Python中,闭包的工作方式与JavaScript类似,但有一些细微差别,比如在处理不可变变量时的表现。以下是一个Python中的闭包示例:
def outer():
outer_var = 'I am from outer function'
def inner():
print(outer_var) # 输出:I am from outer function
return inner
my_closure = outer()
my_closure()
在Django中,模型类继承与其他面向对象编程语言中的类继承非常相似,但有一些特定的规则和限制。Django支持几种不同的模型继承方式,每种方式都有其用途和特点。
抽象基类继承允许你创建一个包含共同字段和方法的基类,但不创建实际的数据库表。子模型将继承这些共同字段和方法,并为每个子模型创建单独的数据库表。
from django.db import models
class CommonInfo(models.Model):
name = models.CharField(max_length=100)
age = models.PositiveIntegerField()
class Meta:
abstract = True # 表明这是一个抽象基类
class Student(CommonInfo):
school = models.CharField(max_length=100)
在这个例子中,CommonInfo是一个抽象基类,它不会创建数据库表。Student模型继承了CommonInfo的字段,并为Student创建了一个包含name、age和school字段的数据库表。
多表继承允许子模型从父模型继承字段,并且每个模型都有自己的数据库表。子模型会自动获得一个指向父模型的一对一关系。
class Person(models.Model):
name = models.CharField(max_length=100)
age = models.PositiveIntegerField()
class Student(Person):
school = models.CharField(max_length=100)
在这个例子中,Person和Student都有自己的数据库表。Student表有一个外键指向Person表。
代理模型继承允许你创建一个与现有模型具有相同字段的新模型,但不创建新的数据库表。这通常用于改变模型的默认管理器或默认排序等行为。
class MyPerson(Person):
class Meta:
proxy = True
ordering = ['name'] # 更改默认排序
在这个例子中,MyPerson是Person的一个代理模型,它使用相同的数据库表,但可以有自己的管理器或排序规则。
虽然不常见,但Django也支持多重继承,其中子模型可以继承多个父模型。在这种情况下,Django会将所有父模型的字段合并到子模型中。
class CommonInfo(models.Model):
name = models.CharField(max_length=100)
class ExtraInfo(models.Model):
age = models.PositiveIntegerField()
class Student(CommonInfo, ExtraInfo):
school = models.CharField(max_length=100)
在这个例子中,Student模型继承了CommonInfo和ExtraInfo的字段。
每种继承方式都有其特定的使用场景,选择哪种方式取决于你的具体需求。通常,抽象基类用于共享字段和方法,而多表继承用于当子模型需要扩展父模型的功能时。代理模型用于改变模型的行为,而多重继承则较少使用,因为它可能导致复杂的模型关系。
跨域问题是Web开发中常见的问题,它发生在当从一个域下的文档或脚本尝试去请求另一个域下的资源时,由于浏览器的同源策略限制而无法直接进行。以下是一些解决跨域问题的方法:
CORS是解决跨域问题的标准方法。服务器设置Access-Control-Allow-Origin头部,浏览器将根据这个头部决定是否允许跨源请求。
1、服务器端设置:
在服务器端,你可以在响应中添加以下HTTP头部:
Access-Control-Allow-Origin: *
# 或者指定特定的域名
Access-Control-Allow-Origin: http://example.com
如果需要带Cookie请求,还需要设置:
Access-Control-Allow-Credentials: true
并且Access-Control-Allow-Origin不能设置为*,必须指定具体的域名。
在客户端的同源域下设置一个代理服务器,由代理服务器转发请求到目标服务器,并将响应返回给客户端。
代理服务器配置(以Node.js为例):
const express = require('express');
const request = require('request');
const app = express();
app.use('/proxy', (req, res) => {
const url = 'http://example.com' + req.url;
req.pipe(request(url)).pipe(res);
});
app.listen(3000);
某些Web服务器(如Nginx)可以配置反向代理来处理跨域请求。
Nginx配置示例:
location /api {
proxy_pass http://example.com;
add_header Access-Control-Allow-Origin *;
}
在软件开发中,"Settings"通常指的是一个配置文件或者配置类,用于存储和管理应用程序的设置。这些设置可以是数据库连接字符串、API密钥、应用运行模式、日志级别等。
在Python中,我们通常创建一个settings.py文件,并在其中定义一个配置类。
# settings.py
class Settings:
DEBUG = True
TESTING = False
DATABASE_URI = 'sqlite:///mydatabase.db'
SECRET_KEY = 'a-very-secret-key'
# 使用配置
settings = Settings()
print(settings.DEBUG)
CSRF(跨站请求伪造)是一种攻击手段,攻击者利用受害者的身份在受害者已经认证的网站上执行非授权的操作。为了防止这种情况,许多Web应用都会在表单或者AJAX请求中添加CSRF令牌(token)。
大多数Web框架都会在每个页面的表单中或者作为HTTP头部包含一个CSRF Token。在AJAX请求中,你需要确保这个Token被发送到服务器。
function getCookie(name) {
var cookieValue = null;
if (document.cookie && document.cookie !== '') {
var cookies = document.cookie.split(';');
for (var i = 0; i < cookies.length; i++) {
var cookie = jQuery.trim(cookies[i]);
if (cookie.substring(0, name.length + 1) === (name + '=')) {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
}
return cookieValue;
}
var csrftoken = getCookie('csrftoken');
$.ajax({
url: "/my-url/",
type: "POST",
data: {
csrfmiddlewaretoken: csrftoken,
// ...其他数据
},
success: function(data) {
// 处理成功响应
}
});
另一种方法是将CSRF Token添加到AJAX请求的HTTP头部中。
$.ajaxSetup({
beforeSend: function(xhr, settings) {
if (!this.crossDomain) {
xhr.setRequestHeader("X-CSRFToken", csrftoken);
}
}
});
// 现在,所有的AJAX请求都会自动包含X-CSRFToken头部
机器数据分析/建模是人工智能和大数据领域的核心内容,通过这一过程,我们可以从看似杂乱无章的数据中提取有价值的信息,进而支撑决策和预测。以下是一些在进行机器数据分析/建模时的感悟:
通过这些感悟,我们能够更加审慎和有效地进行机器数据分析/建模工作,更好地服务于社会和经济发展。
网络爬虫(Web Crawler)是一种自动获取网页内容的程序,它主要用于搜索引擎,以索引网页内容,帮助用户更快速地找到信息。以下是网络爬虫的基本原理:
网络爬虫的设计和实现需要综合考虑网络协议、数据解析、存储管理、并发处理等多个技术方面。同时,它还要遵守相关的法律法规,尊重网站的版权和用户隐私。
Redis之所以快速,除了它是基于内存的数据库之外,还有以下几个原因:
这些因素综合起来,使得Redis在提供快速数据访问的同时,还能保持良好的可扩展性和可靠性。
Python 2和Python 3之间有很多重要的区别,这些区别导致了两者在语法、库支持、性能和默认行为上的不同。以下是一些主要的区别:
print "Hello, World"print("Hello, World")except Exception, e:。except Exception as e:。Python 3 在某些方面(如整数运算)比 Python 2 快,但由于其更严格的内存管理和Unicode支持,某些操作可能会稍慢。
Python 3 不是 Python 2 的直接升级,两者不完全兼容。很多在 Python 2 下可以正常运行的代码,在 Python 3 下可能需要修改。
Python 2 的官方支持已于2020年1月1日结束。这意味着不再有安全更新或改进。因此,推荐使用 Python 3。
这些只是一些主要区别的概览。实际上,两者之间的差异要多得多,而且涉及到语言的各个方面。对于开发者来说,理解这些差异对于编写兼容 Python 2 和 Python 3 的代码至关重要。
将Python 2项目迁移到Python 3可能会遇到多种挑战,以下是一些可能的困难:
except Exception, e: 改为 except Exception as e:。总的来说,迁移工作可能既复杂又耗时,但对于确保软件项目的长期健康和维护来说,这是必要的。
Docker 是一个"容器化"平台,用来打包、发布和运行应用程序。你可以把它想象成一个「轻量虚拟机」,但比虚拟机更快、更轻便。
🧱 举个例子:假设你有一个 Python 项目,它需要特定版本的 Python、某些依赖库、数据库等等。如果你用 Docker,可以把这一整套运行环境 + 你的代码打包成一个「Docker 容器」。其他人只需要安装 Docker,就能用一条命令运行这个项目,不用担心环境配置问题。
Docker 镜像(Image) 就像是一个「模版快照」:
从这个镜像启动时,就会生成一个正在运行的 容器(container)。
Docker 最大的好处是:环境统一、部署简单、运行一致性高。
docker-compose 是 Docker 提供的一个工具,用来统一管理多个容器服务,比如:Web 服务、数据库、Redis 等。你可以通过一个 docker-compose.yml 配置文件,用一条命令启动整个系统。
🧱 举个例子:假设你有一个系统包括:一个前端 Vue 服务、一个后端 Python/Flask 服务、一个数据库 PostgreSQL。用 docker-compose.yml 可以把它们定义在一个文件中:
version: '3.8'
services:
db:
image: postgres:15
container_name: odoo-db
environment:
- POSTGRES_DB=postgres
- POSTGRES_USER=odoo
- POSTGRES_PASSWORD=odoo
volumes:
- odoo_db_data:/var/lib/postgresql/data
odoo:
image: odoo:18.0
container_name: odoo-app
depends_on:
- db
ports:
- "8069:8069"
environment:
- HOST=db
- USER=odoo
- PASSWORD=odoo
volumes:
- ./addons:/mnt/extra-addons
- ./odoo.conf:/etc/odoo/odoo.conf
volumes:
odoo_db_data:
Python 虚拟环境(virtual environment) 是一个隔离的 Python 运行环境,用来:📌 "为每个项目单独安装依赖包,不相互干扰。"
假设你有两个 Python 项目:
如果你把它们都装在全局环境里,就会冲突。但如果每个项目都有独立的「虚拟环境」,就不会互相干扰。
🔒 它隔离了:
推荐使用 Python 自带的 venv 模块(从 Python 3.3 开始支持)
python3 -m venv new_app_venv
或者使用 virtualenv(更兼容版的 venv)
pip install virtualenv
virtualenv new_app_venv
source venv/bin/activate
new_app_venv 是虚拟环境的目录名,会在当前目录下生成一个 new_app_venv/ 文件夹
venv\Scripts\activatesource venv/bin/activate(venv) $ 说明你已经进入了虚拟环境。
总结一句话:Python 虚拟环境是为项目隔离依赖的独立空间,避免不同项目间产生冲突,是专业开发必备工具。
conda 是在数据科学和机器学习领域最受欢迎的环境和包管理工具之一,特别适合涉及大量科学计算库(如 numpy、pandas、scipy、tensorflow、pytorch)的项目。
conda 是一个跨平台的环境和包管理器,由 Anaconda 公司开发,支持:
推荐使用 Miniconda,精简干净,安装快。
✅ 创建虚拟环境
conda create -n myenv python=3.11
myenv 是环境名,可指定 Python 版本
✅ 激活虚拟环境
conda activate myenv
✅ 安装常用库(以 pandas 为例)
conda install pandas
# 也可以一次性安装多个包:
conda install numpy scipy matplotlib seaborn
# 或者安装深度学习框架:
conda install pytorch torchvision torchaudio cpuonly -c pytorch
conda config --add channels conda-forge
conda config --set channel_priority strict
conda-forge 提供了更全更及时的社区包,覆盖很多 pip 上才有的工具。
name: ds-env
channels:
conda-forge
dependencies:
python=3.11
numpy
pandas
matplotlib
jupyterlab
scikit-learn
seaborn
用这个文件一键部署环境:
conda env create -f environment.yml
总结一句话:conda 是数据科学的"环境神器",不仅能管理 Python 环境和依赖,还能解决大型项目的依赖地狱,是 Jupyter、Numpy、Pandas、TensorFlow 等库的理想搭档。
可以分为"六大步骤",无论文档类型(PDF、Word、图片、HTML 等)如何,整体流程都大致相同。
1️⃣ 加载 PDF 文档
import fitz # PyMuPDF
doc = fitz.open("sample.pdf")
2️⃣ 获取每一页内容
for page in doc:
text = page.get_text()
print(text)
3️⃣ 可选:使用 pdfplumber 提取表格
import pdfplumber
with pdfplumber.open("sample.pdf") as pdf:
for page in pdf.pages:
tables = page.extract_tables()
for row in tables[0]:
print(row)
4️⃣ 文本清洗
def clean_text(text):
return text.replace('\xa0', ' ').strip()
cleaned = clean_text(text)
5️⃣ 结构化内容(例如使用正则或标题识别)
import re
headings = re.findall(r'(第[一二三四五六七八九十]+章.*?)\n', cleaned)
print(headings)
6️⃣ 应用:存入数据库、问答、摘要等
例如,将结构化内容作为输入,喂入大模型做问答:
from openai import OpenAI
prompt = "请总结下列 PDF 文档的要点:\n" + cleaned
response = openai.ChatCompletion.create(...)
✅ 总结:一句话描述文档解析的本质是:提取有用信息 + 保留语义结构 + 为后续分析做好准备。不同文档类型工具不同,但流程类似。
微服务(Microservices)是一种软件架构风格,它把一个复杂的应用程序拆分成一组小的、自治的服务,每个服务都围绕特定的业务功能构建,可以独立开发、部署和扩展。
30道Python相关的面试题,涵盖基础语法、数据结构、函数、类和对象、模块和包、高级特性等多个方面,适合不同层次的Python开发者:
答案:直接赋值即可,例如 x = 10。
答案:可以直接使用 a, b = b, a。
答案:使用print()函数,例如 print("Hello, World!")。
答案:使用input()函数,例如 name = input("Enter your name: ")。
答案:使用三引号"""或''',例如:
"""
This is a multi-line comment.
It can span multiple lines.
"""
答案:列表是可变的,可以修改其内容;元组是不可变的,一旦创建不能修改。
答案:使用{}或dict(),例如 my_dict = {} 或 my_dict = dict()。
答案:使用for循环,例如:
my_list = [1, 2, 3]
for item in my_list:
print(item)
答案:使用sort()方法或sorted()函数,例如:
my_list = [3, 1, 2]
my_list.sort() # 修改原列表
sorted_list = sorted(my_list) # 返回新列表
答案:使用del关键字或pop()方法,例如:
my_dict = {'a': 1, 'b': 2}
del my_dict['a']
value = my_dict.pop('b')
答案:使用def关键字,例如:
def my_function():
print("Hello from a function")
答案:在函数定义中指定参数,例如:
def my_function(name):
print(f"Hello, {name}")
答案:在函数定义中为参数指定默认值,例如:
def my_function(name="World"):
print(f"Hello, {name}")
答案:函数可以返回一个元组,调用时可以解包,例如:
def my_function():
return 1, 2, 3
a, b, c = my_function()
答案:使用lambda关键字,例如:
my_function = lambda x: x * 2
答案:使用class关键字,例如:
class MyClass:
def __init__(self, name):
self.name = name
答案:通过类名调用,例如:
my_object = MyClass("Kimi")
答案:在类中定义函数,使用self作为第一个参数,例如:
class MyClass:
def my_method(self):
print("Hello from a method")
答案:在类定义中指定父类,例如:
class MySubClass(MyClass):
def my_sub_method(self):
print("Hello from a subclass method")
答案:使用super()函数,例如:
class MySubClass(MyClass):
def my_method(self):
super().my_method()
print("Hello from a subclass method")
答案:使用import关键字,例如:
import math
答案:使用from ... import ...语法,例如:
from math import sqrt
答案:创建一个.py文件,例如my_module.py,在其中定义函数、类等。
答案:创建一个文件夹,并在其中创建一个__init__.py文件,然后在文件夹中添加模块文件。
答案:使用点号表示路径,例如:
from my_package import my_module
答案:使用[expression for item in iterable]语法,例如:
squares = [x * x for x in range(10)]
答案:使用expression for item in iterable语法,例如:
squares = (x * x for x in range(10))
答案:使用@decorator语法,例如:
def my_decorator(func):
def wrapper():
print("Something is happening before the function is called.")
func()
print("Something is happening after the function is called.")
return wrapper
@my_decorator
def say_hello():
print("Hello!")
答案:使用with语句,例如:
with open('file.txt', 'r') as file:
content = file.read()
答案:使用threading模块实现多线程,使用multiprocessing模块实现多进程,例如:
import threading
import multiprocessing
def my_function():
print("Hello from a thread/process")
thread = threading.Thread(target=my_function)
thread.start()
thread.join()
process = multiprocessing.Process(target=my_function)
process.start()
process.join()
这些面试题涵盖了Python的基础语法、数据结构、函数、类和对象、模块和包以及高级特性,适合不同层次的Python开发者。