Python 基础

Dec 26, 2024

Python 编程概述

Python 是一种多功能的编程语言,它同时支持面向对象编程 (OOP) 和函数式编程。

Python 正在推动人工智能领域的最新进展,包括:

  • 文本到图像的生成
  • 大型语言模型 (LLMs)
  • 深度学习

被众多领先公司采用:

  • 特斯拉:利用 OpenCV
  • Instagram:采用 Django

应用场景

  • 人工智能与机器学习
  • 计算机视觉
  • Web 应用程序(例如 Flask、Django)
  • 数据分析与可视化

变量

Python 中的变量充当存储数据值的容器。

数据类型

  • 整型a = 1
  • 布尔型b = False
  • 字符串型c = "Aryan"
  • 空类型d = None

数字数据类型

  1. 数值:整数、浮点数、复数

    • int3, -8, 0
    • float3.8, 0.001, -9.0
    • complex2 + 3j,语法:a = complex(123, 2) -> 123 + 2j
  2. 文本数据str

    • 示例:"你好,大神级工程师"
  3. 布尔数据TrueFalse

  4. 序列数据list, tuple

    • 列表 (List):有序的数据集合,元素用逗号分隔,并用方括号括起来。

      • 列表是可变的,可以被修改。
      • 示例:list1 = [B, 2.3, [-4, 5], ['苹果']]
    • 元组 (Tuple)不可变的有序数据集合,元素用逗号分隔,并用圆括号括起来。

      • 元组是不可变的,不能被修改。
      • 示例:tuple1 = (("aryan", "myron"), ("pradyumnaa", "sharvin"))
    • 可变 vs 不可变

      • 变异指的是变化(例如,人类的尾巴消失)。

    注意:列表是可变的,而元组是不可变的。

  5. 映射数据dictionary(或 dict

    • 键值对的集合。

    • 示例:dict1 = { "name": "aryan", "age": 20, "girlfriends": 0, "canCode": True }

    注意:在 Python 中,一切皆为对象!这包括字典、整数和布尔值。

运算符

运算符运算符名称示例+加法5 + 7-减法5 - 7*乘法5 * 7/除法5 / 7%取模5 % 7//地板除法5 // 7**指数运算5 ** 2

类型转换

类型转换是指将一种数据类型转换为另一种数据类型。在 Python 中,这被称为类型转换。

函数

  • int(), float(), str(), ord(), hex(), oct(), tuple(), list(), set(), dict()

类型转换的种类

  • 显式转换:由开发者手动完成。
  • 隐式转换:由 Python 自动执行。
a = "1"  # 字符串
b = "2"
print(int(a) + int(b))  # 字符串转数字
c = 1.9  # 浮点数
d = 8    # 整数
# d 被转换为浮点数,因为它的数据类型优先级更高
print(c + d)

获取用户输入

使用 input() 函数,它返回一个字符串值。

x = input("输入第一个数字:")
y = input("输入第二个数字:")
print(x + y)

输出12100(因为字符串被拼接在一起)

要执行加法,需要将类型转换为整数格式:

print(int(x) + int(y))  # 类型转换

字符串处理

字符串是用单引号或双引号括起来的文本数据序列。

访问字符

  • 示例:name = "aryan"

    print(name[0])  # 输出:'a'
    print(name[1])  # 输出:'r'
    

字符串可以像数组一样通过从 0 开始的索引访问。

字符串切片

切片是指使用索引提取字符串的部分内容。

fruit = "芒果"
len1 = len(fruit)
print("芒果是一个", len1, "个字的词")

字符串作为数组

  • 字符串是字符序列。
pie = "苹果派"
print(pie[:2])  # 输出:'苹果'
print(pie[2])   # 输出:'派'
conditions = [
(3, "fizz"),
(5, "buzz"),
(7, "bizz"),
(9, "bazz")]

for i in range(1, 100):
    output = "".join(word for divisor, word in conditions if i % divisor == 0)
    if not output:
        output = str(i)
    print(output, i)

字符串方法

  • upper():将字符串转换为大写。

    str = "AbcdEfghIJ"
    print(str.upper())  # 输出:'ABCDEFGHIJ'
    
  • lower():将字符串转换为小写。

  • strip():移除字符串开头和结尾的空白字符。

    str = "银   勺  "
    print(str.strip())  # 输出:'银   勺'
    
  • rstrip():移除尾随字符。

    str = "你好!!!"
    print(str.rstrip("!"))  # 输出:'你好'
    
  • replace():将字符串中所有出现的子字符串替换为另一个字符串。

    str = "银勺"
    print(str.replace("勺", "叉"))  # 输出:'银叉'
    
  • split():在指定实例处分割字符串,并返回一个列表。

    str2 = "银 勺"
    print(str2.split(" "))  # 输出:['银', '勺']
    
  • capitalize():将字符串的第一个字符大写。

  • center():将字符串居中对齐。

  • count():返回字符串中某个值出现的次数。

    str = "abracadabra"
    countStr = str.count("a")
    print(countStr)  # 输出:5
    
  • endswith():检查字符串是否以给定的值结尾。

  • find():查找某个值第一次出现的位置,并返回其索引。如果未找到,则返回 -1

    str = "他的名字是aryan,他很棒"
    print(str.find("是"))  # 输出:6
    print(str.find("丹尼尔"))  # 输出:-1
    

    注意index() 在值不存在时会引发异常,而 find() 返回 -1

  • isalnum():如果字符串仅包含字母数字字符(A-Z、a-z、0-9),则返回 True

  • islower():如果字符串中的所有字符均为小写,则返回 True

  • isprintable():如果字符串中的所有字符均为可打印字符,则返回 True

  • isspace():如果字符串由空白字符组成,则返回 True

  • istitle():如果字符串采用标题格式(每个单词的首字母大写),则返回 True

  • isupper():如果字符串中的所有字符均为大写,则返回 True

条件语句

  • if:基本条件语句。
  • if-else:带有备选执行的条件语句。
  • if-else-elif:多个条件语句。
  • 嵌套 if-else-elif:条件中的条件。

示例

iphonePrice = 60000
budget = 20000
if budget < iphonePrice:
    print("努力赚钱吧!")
else:
    print("买吧,兄弟!")

elif 语句

num = 0
if num < 0:
    print("数字是负数")
elif num == 0:
    print("数字是零")
else:
    print("数字是正数")

嵌套 if

num = 18
if num < 0:
    print("数字是负数")
elif num > 0:
    if num <= 10:
        print("数字在 1-10 之间")
    elif num > 10 and num <= 20:
        print("数字在 11-20 之间")
    else:
        print("数字大于 20")
else:
    print("数字是零")

输出数字在 11-20 之间

条件运算符

条件运算符用于比较值。以下是一些示例:

  • 运算符>, <, >=, <=, ==

    a = 18
    print(a > 18)   # 输出:False
    print(a <= 18)  # 输出:True
    print(a == 18)  # 输出:True
    print(a != 18)  # 输出:False
    

For 循环

Python 中的 for 循环遍历可迭代对象序列,例如字符串、列表、元组、集合和字典。

  • 字符串示例

    name = "马丁"
    for i in name:
        print(i, end=", ")
    # 输出:马, 丁,
    
  • 列表示例

    colors = ["红色", "绿色", "蓝色"]
    for i in colors:
        print(i)
        for b in i:
            print(b)
    
  • 范围示例

    for k in range(1, 200):
        print(k)  # 输出:从 1 到 199 的数字
    
    for k in range(2, 12, 2):
        print(k)  # 输出:2, 4, 6, 8, 10
    

While 循环

while 循环只要条件为 True 就会重复执行代码块。

count = 5
while count > 0:
    print(count)
    count -= 1
else:
    print("我在 else 内部")

Do-While 循环

Python 没有内置的 do-while 循环,但可以使用 while 循环来模拟它。

# 这是一个伪代码表示,因为 Python 不支持 do-while 语法
do:
{
    # 循环体
}
while (condition)

Break & Continue

  • break:立即退出循环。

  • continue:跳过循环当前迭代中剩余的代码。

  • break 示例:

    for i in range(1, 101):
        print(i, end=" ")
        if i == 50:
            break
        else:
            print("aryan")
    # 输出:1 aryan 2 aryan ... 48 aryan 49 aryan 50
    
  • continue 示例:

    for i in range(12):
        if i == 10:
            print("跳过本次迭代")
            continue
        print("5 x", i, "=", 5 * i)
    # 输出:5 x 0 = 0 ... 5 x 9 = 45 跳过本次迭代 5 x 11 = 55
    

Python 函数

函数是一个代码块,用于在调用时执行特定任务。函数有助于使代码更简洁且更具可重用性。

  • 内置函数min(), max(), len(), sum(), type(), tuple(), list(), set(), print(), range(), dict()

  • 用户定义函数:根据用户的需要创建的函数来执行特定任务。

    示例

    def greet(fname, lname):
        print("你好", fname, lname)
    
    greet("aryan", "kyatham")
    

函数参数

  • 默认参数:为函数参数提供默认值。

    def greet(fname, mname="ajay", lname="sharma"):
        print("你好", fname, mname, lname)
    
    greet("disha")  # 输出:你好 disha ajay sharma
    
  • 关键字参数:以键值格式提供值,允许你跳过参数的顺序。

    def greet(fname, mname, lname):
        print("你好", fname, mname, lname)
    
    greet(mname="Peter", lname="wesker", fname="Jaden")
    # 输出:你好 Jaden Peter Wesker
    
  • 必需参数:必须提供所有必需的参数。

    # 这会引发错误,因为缺少 'lname'
    greet("aryan", "bhai")
    # 输出:TypeError: greet() 缺少 1 个必需的位置参数:'lname'
    
  • 可变长度参数:允许传递比定义的参数更多的参数。

    • 任意参数

      def greet(*names):
          print("你好", names[0], names[1], names[2])
      
      greet("aryan", "zayn", "khalid")
      
    • 关键字参数

      def greet(**names):
          print(names["fname"], names["mname"], names["lname"])
      
      greet(fname="Aryan", mname="Zayn", lname="Khalid")
      
  • return 语句:将表达式的值返回给调用函数。

    def add(a, b):
        return a + b
    
    result = add(5, 3)
    print(result)  # 输出:8
    

列表 (List)

Python 中的列表是数据项的有序集合。它允许你在单个变量中存储多个项目。列表用方括号 ([]) 括起来,项目之间用逗号分隔。列表是可变的,这意味着你可以在创建后更改它们。

  • 示例

    lst1 = [1, 2, 3, 4, 5, 6]
    lst2 = ["红色", "绿色", "蓝色"]
    details = ["Aryan", 20, "BTech"]
    

检查列表项是否存在: 你可以使用 in 关键字。

colors = ["红色", "绿色", "蓝色", "黄色"]

if "黄色" in colors:
    print("黄色存在")

索引范围

你可以使用索引来访问列表的不同部分:

  • 打印从给定索引到末尾的所有元素

    animals = ["猫", "狗", "蝙蝠", "狮子", "老虎", "山羊", "牛"]
    print(animals[4:])
    
  • 打印从开始到给定索引的所有元素

    print(animals[:6])
    
  • 打印交替值

    print(animals[::2])
    
  • 打印给定范围内每第 3 个元素

    print(animals[1:8:3])
    

列表推导式

列表推导式用于从其他可迭代对象(如列表、元组、字典、集合甚至字符串)创建新列表。

  • 示例 1:接受带有字母 "o" 的项目:

    names = ["Milo", "Sarah", "Bruno", "Anastasia", "Rose"]
    names_with_o = [item for item in names if "o" in item]
    print(names_with_o)
    # 输出:['Milo', 'Bruno', 'Rose']
    
  • 示例 2:接受超过 4 个字母的项目:

    names_with_4 = [item for item in names if len(item) > 4]
    

列表方法

以下是一些常用的列表操作方法:

  1. list.sort():按升序对列表进行排序。

    colors = ["紫色", "靛蓝", "蓝色", "绿色"]
    colors.sort()  # 输出:['蓝色', '绿色', '靛蓝', '紫色']
    

    降序排序

    nums = [4, 5, 1, 2, 3, 6, 7, 9, 8]
    nums.sort(reverse=True)
    # 输出:[9, 8, 7, 6, 5, 4, 3, 2, 1]
    
  2. list.reverse():反转列表。

    colors.reverse()
    
  3. list.index():返回指定项第一次出现的索引。

    colors.index("绿色")
    
  4. list.count():返回具有指定值的项的计数。

    colors.count("绿色")
    
  5. list.copy():返回列表的浅拷贝。

    • 用于对副本执行操作而不修改原始列表。
    copy_colors = colors.copy()
    
  6. list.append():将一个项追加到列表的末尾。

    colors = ["紫色", "靛蓝"]
    colors.append("蓝色")
    # 输出:['紫色', '靛蓝', '蓝色']
    
  7. list.insert():在指定索引处插入一个项。

    colors = ["紫色", "靛蓝"]
    colors.insert(1, "绿色")
    # 输出:['紫色', '绿色', '靛蓝']
    
  8. list.extend():将另一个列表或集合中的元素添加到列表的末尾。

    colors = ["紫", "靛", "蓝"]
    rainbow = ["绿", "黄", "橙", "红"]
    colors.extend(rainbow)
    # 输出:['紫', '靛', '蓝', '绿', '黄', '橙', '红']
    
  9. 连接两个列表

    combined_list = color1 + color2
    

元组 (Tuples)

  • 数据项的有序集合。

  • 在单个变量中存储多个项目。

  • 不可更改 - 不可变:不能更改它们。

    tuple1 = (1, 2, 2, 3, 4, 5, 6)
    tuple2 = ("红色", "绿色", "蓝色")
    details = ("abhijeet", 19, "Btech", 9.7)
    
    • 元组索引:

      • 元组中的每个项目/元素都有其唯一的索引。
      • country = ("印度", "意大利", "西班牙")
      • [0] [1] [2]
      • country[0] -> 印度
    • 使用 in 关键字检查元组中的项目:

country = ("印度", "意大利", "西班牙")
if "印度" in country:
   print("印度存在")

操作元组

  • 元组是不可变的,因此如果你想在元组中添加、删除或更改项目,你必须先将其转换为列表

  • 元组到列表的转换

    countries = ["意大利", "印度", "英国"]
    temp = list(countries)
    temp.append("德国")
    temp.pop(1)
    temp[2] = "芬兰"
    countries = tuple(temp)
    print(countries)
    

注意:你可以直接连接两个元组,而无需将它们转换为列表。

countries1 = ["印度"]
countries2 = ["英国"]
print(countries1 + countries2)

元组方法

  1. count():返回指定值出现的次数。

    tup1 = (1, 2, 3, 3, 3)
    print(tup1.count(3))  # 输出:3
    
  2. index():返回指定值第一次出现的索引。

    tup1 = (1, 2, 3, 4)
    print(tup1.index(3))  # 输出:2
    

    注意

    • tup1 = (1) 创建的是一个整数元组,而不是一个元组。要创建一个单项元组,请使用 tup2 = (1,)

      tup1 = (1)
      print(type(tup1))  # 输出:<class 'int'>
      
      tup2 = (1,)
      print(type(tup2))  # 输出:<class 'tuple'>
      

注意:当值应保持不变且不可更改时,使用元组。

F 字符串

F 字符串提供了一种使用花括号 {} 将表达式嵌入字符串文字的方式。

name = "Aryan"
print(f"嘿,{name}")

Python 文档字符串

  • 文档字符串是出现在函数、方法、类或模块定义之后的字符串文字。
  • 它们用作代码的文档。
def square(n):
    '''接受一个数字 n 并返回 n 的平方。'''
    print(n**2)

square(5)

Python 注释与文档字符串

  • 注释:用于向人类解释代码的描述。它们会被 Python 解释器忽略,就像你的暗恋对象可能会忽略你一样!

  • 文档字符串:紧接在函数、方法或类的定义之后使用的文档字符串。可以使用 __doc__ 属性访问它们。

    print(square.__doc__)
    

PEP 8

  • PEP 8 是一份提供关于如何编写 Python 代码的指南和最佳实践的文档。
  • 它的目的是提高 Python 代码的可读性和一致性。
  • PEP:Python 增强提案

递归:它是用自身定义事物的过程

  • 我们知道一个函数可以调用其他函数,函数甚至可以调用自身。
def factorial(num):
   if (num == 1 or num == 0):
      return 1
   else:
      return (num * factorial(num-1))

实现:

5 x factorial(4)
5 x 4 x factorial(3)
5 x 4 x 3 x factorial(2)
5 x 4 x 3 x 2 x factorial(1)
factorial(1) 返回 1

集合 (Sets):数据项的无序集合

  • 它们在单个变量中存储多个项目。集合项目用逗号分隔,并用 {} 括起来。
  • 集合是不可更改的,这意味着你一旦创建就不能更改集合的项目。
  • 集合不包含重复项。
info = {"aryan", 20, False, 5.9}
print(info) # 顺序可能会改变
  • 在这里我们看到集合的项目以随机顺序出现,因此不能使用索引号访问它们。
  • 示例:在办公室检查哪些员工没有收到礼物,获取不重复的人员姓名。

操作adduniondifferenceintersectionupdateintersection_updatesymmetric_differencediscard(无错误)、remove(有错误)

集合中的连接操作:

  1. union()update()

    • 打印两个集合中存在的所有项目。
    • update 将另一个集合的项目添加到现有集合中。
    cities1 = {"东京", "马德里", "柏林", "德里"}
    cities2 = {"东京", "首尔", "喀布尔", "马德里"}
    cities3 = cities1.union(cities2)
    print(cities3) # {'东京', '马德里', '柏林', '德里', '首尔', '喀布尔'}
    cities1.update(cities2)
    print(cities1) # {'东京', '马德里', '柏林', '德里', '首尔', '喀布尔'}
    
  2. intersection()intersection_update()

    • 打印两个集合中相似的所有项目。
    cities3 = cities1.intersection(cities2)
    print(cities3) # {"马德里", "东京"}
    cities1.intersection_update(cities2)
    print(cities1) # {"马德里", "东京"}
    
  3. symmetric_difference()symmetric_difference_update()

    • 打印集合中不相似的项目。
    print(cities1.symmetric_difference(cities2)) # {"首尔", "喀布尔", "柏林", "德里"}
    
  4. difference()difference_update()

集合方法

  1. isdisjoint()

    • 检查给定集合的项目是否在另一个集合中存在。
    • 如果项目不存在,则返回 True;如果项目存在,则返回 False
    cities1.isdisjoint(cities2)
    
  2. issuperset()

    • 检查特定集合的所有项目是否在原始集合中存在。
    • 如果项目存在,则返回 True;否则返回 False
    cities1.issuperset(cities2)
    
  3. issubset()

  4. add()

    cities1.add("赫尔辛基")
    
  5. update()

    cities1.update(cities2)
    
  6. remove()/discard()

    • remove

      cities1.remove("东京") # 如果未找到“东京”,则会引发错误
      
    • discard

      cities2.discard("东京") # 如果未找到“东京”,则不会引发错误
      
  7. pop():随机删除。

  8. del:删除集合。

  9. clear()

Python 字典 (Dictionaries):

  • 数据项的有序集合。
  • 在单个变量中存储多个项目。
  • 字典是键值对,用逗号分隔,并用 {} 括起来。
info = {"name": "aryan", "age": 19, "language": "python"}
  1. 访问单个值:

    info['name'] # 'aryan'
    info.get('language') # 'python'
    
  2. 访问多个值和键:

    info.values() # dict_values(['aryan', 19, 'python'])
    info.keys() # dict_keys(['name', 'age', 'language'])
    
  3. 访问键值对:items() 方法

    for key, value in info.items():
        print(f"{key}: {value}")
    

字典方法

ep1 = {122: 45, 123: 89, 567: 69, 670: 69}
ep2 = {222: 67, 566: 90}
ep1.update(ep2) # {122: 45, 123: 89, 567: 69, 670: 69, 222: 67, 566: 90}
ep1.clear() # {}
ep1.pop(122) # 删除键 122
ep1.popitem() # 删除最后一个键值对
del ep1[122] # 删除键 122
  1. update():如果项目已存在,则更新提供的键的值,否则添加新的键值对。

    info = {'age': 19}
    info.update({'age': 20}) # 19 -> 20
    info.update({'DOB': 2003}) # 在字典中添加 'DOB'
    
  2. clear():删除所有项目。

  3. pop(x):删除键值对。

  4. popitem():删除最后一个键值对。

  5. del:删除项目或整个字典。

    注意delpoppop(x) 返回一个值!

带有 else 的 For 循环:

for x in range(5):
   print(f"{x} 数字")
else:
   print("循环中的 else 块")

x = 0
while x < 7:
   print(x)
   x += 1
else:
   print("抱歉,没有 x")
  • else 出现在循环体之后。
  • 在循环中所有迭代完成后执行。
  • 只有在 else 块之后,程序才会退出循环。

异常处理:

try:
   num = int(input("输入一个整数"))
   a = [6, 3]
   print(a[num])
except IndexError:
   print("索引错误")
a = input("输入数字")
print(f"{a} 的乘法是:")
try:
   for i in range(1, 11):
       print(f"{int(a)} x {i} = {int(a) * i}")
except:
   print("输入无效")
  • 响应不需要的错误的过程。
  • 避免程序崩溃。

Finally 子句:始终执行(例如,关闭文件、关闭数据库连接、使用消息结束程序)

使用 finally

try:
    # 可能引发异常的代码
    result = 10 / 0
except ZeroDivisionError:
    # 处理异常的代码
    print("不能除以零。")
finally:
    # 无论是否发生异常都始终会执行的代码
    print("这始终会执行。")

在此示例中:

  • 如果发生异常(例如除以零),则 except 块会处理它。
  • 无论是否发生异常,finally 块都会执行。这确保了清理代码或重要的最后步骤始终会执行。

没有 finally: 如果你不使用 finally 块,你可能必须依赖其他机制来确保某些代码始终运行,例如将它放置在每个条件路径中或使用不同的结构:

try:
    # 可能引发异常的代码
    result = 10 / 0
except ZeroDivisionError:
    # 处理异常的代码
    print("不能除以零。")
# 这里没有 `finally` 块,因此如果发生异常,此代码将不会始终运行
print("如果发生异常,这可能不会执行。")

在这种情况下,try-except 块之后的代码(print("如果发生异常,这可能不会执行。"))仅在未引发异常时运行。如果捕获到异常,则不会执行 except 块之后的代码。

自定义错误:

a = int(input("输入 5 到 9 之间的值:"))
if a < 5 or a > 9:
   raise ValueError("值应为 5 < x < 9 :)")
  • 使用 raise 关键字创建自定义错误。
  • 当我们想在引发特定异常时执行某些特定操作时非常有用(例如,向管理员发送错误报告、调用 API 等)。

简写 if-else:

a = 330000
b = 3303

print("A") if a > b else print("=") if a == b else print("B")
c = 9 if a > b else 0
result = value_if_true if condition else value_if_false
  • 用于简单的 if-else 语句,尤其是在基于条件向变量赋值时。

枚举 (Enumerate):

marks = [12, 56, 32, 98, 12, 45, 1, 4]
index = 0
for mark in marks:
   print(mark)
   if index == 3:
      print("太棒了,Aryab")
   index += 1
for index, mark in enumerate(marks, start=1):
   print(index, mark)
   if index == 3:
      print("太棒了")
  • 允许循环遍历序列(列表、元组、字符串)并同时获取序列中每个元素的索引和值。
  • 当对索引和值都执行操作时非常有用。
fruits = ['苹果', '香蕉', '芒果']
for idx, fruit in enumerate(fruits, start=1):
   print(idx, fruit)
# 输出:
1 苹果
2 香蕉
3 芒果

虚拟环境:

  • 隔离 Python 环境,以便在多个项目中使用不同的版本、包和依赖项,而不会发生冲突。

  • 示例:项目 1 使用 OpenCV 版本 4.9.0,而另一个项目使用 OpenCV 版本 4.5。

  • 命令:

    python -m venv env
    env/scripts/activate
    pip freeze > requirements.txt
    pip install -r requirements.txt
    
  • 帮助在云端或新机器上轻松设置项目。

  • 检查版本的示例:

    import pandas as pd
    print(pd.__version__)
    

Import 的工作原理:

  • math 导入 sqrt 并重命名为 s

    from math import sqrt as s
    import math as math_builtin
    result = math_builtin.s(9) * math_builtin.pi
    
  • aryan.py:

    def welcome():
       print("嘿,欢迎!")
    
    aryan = "好孩子"
    
  • main.py:

    from aryan import welcome
    
  • 将代码从模块加载到当前脚本的过程,允许使用模块中定义的函数和变量。

  • math 导入所有内容的示例:

    from math import *
    
  • 重命名导入的模块:

    import math as m
    
  • 列出方法和属性:

    import math
    print(dir(math))
    

if __name__ == "__main__":

  • Python 脚本中用于确定脚本是直接运行还是作为模块导入到另一个脚本中的常见模式。
def main():
   print("直接运行脚本")

if __name__ == "__main__":
   main()
  • 此模式允许通过将脚本作为模块导入到另一个脚本中来重用脚本中的代码,而无需运行原始脚本中的代码。
  • 它有助于组织和分离应直接运行的代码与应作为模块导入的代码。它允许确定脚本是直接运行还是作为模块导入到另一个脚本中。

OS 模块

import os
if not os.path.exists("data"):
    os.mkdir("data")

for i in range(0, 100):
    os.mkdir(f"data/Day{i+1}")
  • os 模块是一个内置库,提供了与操作系统交互的函数。
  • 它允许读取、写入文件、运行系统命令等。
f = os.open("file.txt", os.O_RDONLY)
g = os.open("gfile.txt", os.O_WRONLY)
contents = os.read(f, 1024)

os.write(g, b"hello")
os.close(f)
os.close(g)
  • os.listdir -> 获取目录中的文件列表

    files = os.listdir(".")
    
  • mkdir -> 创建新目录

  • 运行系统命令:

    os.system("color 2")
    

局部变量和全局变量

x = 10
def my_function():
    global x
    x = 5  # 更改全局变量 (x)
    y = 5  # 局部变量

my_function()
print(x)  # 输出:5
print(y)  # 错误:在函数外部无法访问 y

注意: 避免在函数内修改全局变量。

文件 I/O

f = open('myfile.txt', 'r')  # 'r' -> 读取模式
print(f)
text = f.read()
print(text)
f.close()

写入文件

f = open('myfile.txt', 'a')
f.write('你好,世界!')
f.close()
with open('myfile.txt', 'a') as f:
    f.write("嘿,我在里面")

模式:

  1. 读取 (r):打开并读取;如果文件不存在,则会出错。
  2. 写入 (w):仅打开文件进行写入,如果文件不存在,则会创建一个新文件。
  3. 追加 (a):仅追加;如果文件不存在,则会创建一个新文件。
  4. 创建 (x):创建一个新文件,如果文件已存在,则会报错。
  5. 文本 (t):处理文本文件。
  6. 二进制 (b):用于二进制文件(图像、PDF)。

注意: 使用 with 关键字自动关闭文件。

Lambda 函数

def appl(fx, value):  # fx = 函数
    return 6 + fx(value)

double = lambda x: x * 2
cube = lambda x: x * x * x
avg = lambda x, y, z: (x + y + z) / 3

print(double(5))  # 输出:10
print(appl(lambda x: x * x, 2))  # 输出:10
  • 没有名称的小型匿名函数。
  • 语法:lambda arguments: expression

示例:

def multiply(x, y):
    return x * y

# LAMBDA 等价物
lambda x, y: x * y

lambda x, y: print(f"{x} * {y} = {x * y}")

Map, Filter, Reduce

  • 高阶函数:将其他函数作为参数。

Map

  • 将函数应用于序列中的每个元素,并返回一个新序列。
numbers = [1, 2, 3, 4, 5]
doubled = map(lambda x: x * 2, numbers)
print(list(doubled))  # 输出:[2, 4, 6, 8, 10]

Filter

  • 根据给定的谓词(返回布尔值)过滤元素序列,并返回一个仅包含满足谓词的元素的新序列。
numbers = [1, 2, 3, 4, 5]
evens = filter(lambda x: x % 2 == 0, numbers)
print(list(evens))  # 输出:[2, 4]

Reduce

  • 将一个函数应用于可迭代对象中的前两个元素,然后将该函数应用于结果和下一个元素,依此类推。
from functools import reduce
numbers = [1, 2, 3, 4, 5]
sum = reduce(lambda x, y: x + y, numbers)
print(sum)  # 输出:15

is vs ==

a = None
b = None
print(a is b)  # True:两者都是 None,对象在内存中的确切位置

print(a is None)  # True
print(a == b)  # True:值相同
  • 两者都是比较运算符。
  • is:比较对象的标识。
  • ==:比较对象的值。

示例:

a = [1, 2, 3]
b = [1, 2, 3]
print(a == b)  # True:值相同
print(a is b)  # False:内存中不同的对象

注意: 对于字符串和整数,is== 将返回相同的结果。

面向对象编程 (OOP)

面向对象编程的 4 大支柱

  • 继承:属性共享
  • 封装:数据隐藏
  • 抽象:简化接口
  • 多态:多种形式

面向对象编程

  • :用于创建对象的蓝图或模板。
    • 属性:对象的数据/状态。
    • 方法:对象可以执行的操作。
  • 对象:类的实例,包含自己的数据和方法。

封装

  • 对象的内部状态是隐藏的,只能通过对象的方法访问或修改。
  • 有助于保护对象的数据并防止其被意外修改。

访问说明符

  • 公共成员:默认;可以从类外部访问。
  • 受保护成员:单下划线 (_) 前缀;旨在供类及其子类内部使用。
  • 私有成员:双下划线 (__) 前缀;导致名称修改,使得从类外部访问更具挑战性。

抽象

抽象用于向用户隐藏函数的内部功能。用户与函数的基本实现交互,但内部工作是隐藏的。

多态

  • 不同类的对象可以被视为好像它们是公共类的对象一样。
  • 允许代码具有更大的灵活性。
class Animal:
    def speak(self):
        pass

class Dog(Animal):
    def speak(self):
        return "汪!"

class Cat(Animal):
    def speak(self):
        return "喵!"

class Bird(Animal):
    def speak(self):
        return "啾!"

# 用于演示多态性的函数
def make_animal_speak(animal):
    print(animal.speak())

# 创建不同动物的实例
dog = Dog()
cat = Cat()
bird = Bird()

# 演示多态性
make_animal_speak(dog)  # 输出:汪!
make_animal_speak(cat)  # 输出:喵!
make_animal_speak(bird) # 输出:啾!

类是用于创建对象的蓝图或模板,为状态(成员变量)和行为(成员函数或方法)的实现提供初始值。

class Details:
    name = "Aryan"
    age = 20

对象:类的实例

obj1 = Details()
print(obj1.name)  # 输出:Aryan
print(obj1.age)  # 输出:20

Self 参数

  • 对类当前实例的引用。
  • 用于访问属于类的变量。
class Details:
    name = "Aryan"
    age = 20

    def describe_person(self):
        print("我的名字是", self.name, ",我", self.age, "岁")

obj1 = Details()
obj1.describe_person()

示例

class Person:
    name = "Aryan"
    occ = "SDE"
    networth = 10

    def info(self):
        print(f"{self.name} 是一名 {self.occ}")

a = Person()
b = Person()
c = Person()
a.name = "Shubh"
a.occ = "CA"
b.name = "Radhika"
b.occ = "HR"
a.info()  # 输出:Shubh 是一名 CA
b.info()  # 输出:Radhika 是一名 HR
c.info()  # 输出:Aryan 是一名 SDE

构造函数

  • 构造函数是类中用于创建和初始化该类对象的特殊方法。
  • 它们是在创建类的对象时自动调用的唯一函数。
  • 主要目的是初始化或为类的数据成员赋值。
def __init__(self):
    # __init__ -> Python 中的保留函数
  1. 参数化构造函数:

    • 当构造函数接受 self 以及参数时。
    • 这些参数可以在类中用于为数据成员赋值。
    class Details:
        def __init__(self, animal, group):
            self.animal = animal
            self.group = group
    
    obj1 = Details("狮子", "食肉动物")
    print(obj1.animal, "属于", obj1.group)
    
  2. 默认构造函数:

    • 当构造函数不接受来自对象的任何参数,并且只有一个参数 - self
    class Details:
        def __init__(self):
            print("动物狮子:食肉动物")
    
    obj1 = Details()
    

装饰器

  • Python 装饰器是强大而通用的工具,允许你修改函数和方法的行为。

  • 它们扩展了函数的功能,而无需修改其源代码。

  • 装饰器将另一个函数作为参数,并返回一个修改原始函数行为的新函数。

  • 因此,新函数通常被称为“装饰”函数。

    @decorator_function
    def my_function():
        pass
    
    def smart_divide(func):
        def inner(a, b):
            print("我将要除", a, "和", b)
            if b == 0:
                print("无法除")
                return
            return func(a, b)
        return inner
    
    @smart_divide
    def divide(a, b):
        print(a / b)
    
    divide(2, 5)
    # 输出:
    # 我将要除 2 和 5
    # 0.4
    

Getter

  • Python 中的 Getter 是用于访问对象属性值的方法。
  • 它们用于返回特定属性的值,并使用 @property 装饰器定义。
   class MyClass:
       def __init__(self, value):
           self._value = value

       @property
       def value(self):
           return self._value

   obj = MyClass(10)
   print(obj.value)  # 输出:10

注意: Getter 不接受参数,我们不能通过 getter 方法设置值。

Setter

    class MyClass:
        def __init__(self, value):
            self._value = value

        @property
        def value(self):
            return self._value

        @value.setter
        def value(self, new_val):
            self._value = new_val

    obj = MyClass(10)
    obj.value = 20
    print(obj.value)  # 输出:20

注意: Setter 用于数据封装。

继承

  • 当一个类派生自另一个类时,子类会继承父类的所有公共和受保护的属性和方法。
  • 此外,它可以有自己的属性和方法。这被称为继承。
  • 派生类从基类继承特性,从而实现代码的重用。

继承类型:

  1. 单继承

  2. 多重继承

  3. 多级继承

  4. 分层继承

  5. 混合继承

单继承

  • 它使派生类能够从单个父类继承属性。
class Parent:
    def func1(self):
        print("父类")

class Child(Parent):
    def func2(self):
        print("子类")

obj = Child()
obj.func1()  # 输出:父类
obj.func2()  # 输出:子类

多重继承

  • 当一个类从多个基类派生时,称为多重继承。
  • 基类的所有特性都继承到派生类中。
class Mother:
    mothername = ""

    def mother(self):
        print(self.mothername)

class Father:
    fathername = ""

    def father(self):
        print(self.fathername)

class Son(Mother, Father):
    def parents(self):
        print(self.fathername)
        print(self.mothername)

s1 = Son()
s1.fathername = "爸爸"
s1.mothername = "妈妈"
s1.parents()

多级继承

  • 基类和派生类的特性进一步继承到新的派生类中。
class Grandfather:
    def __init__(self, grandfathername):
        self.grandfathername = grandfathername

class Father(Grandfather):
    def __init__(self, fathername, grandfathername):
        Grandfather.__init__(self, grandfathername)
        self.fathername = fathername

class Son(Father):
    def __init__(self, fathername, grandfathername, sonname):
        Father.__init__(self, fathername, grandfathername)
        self.sonname = sonname

    def print_name(self):
        print("爷爷:", self.grandfathername)
        print("爸爸:", self.fathername)
        print("儿子:", self.sonname)

s1 = Son("王子", "拉姆", "拉尔")
s1.print_name()

分层继承

  • 当从单个基类创建多个派生类时,称为分层继承。
class Parent:
    def func1(self):
        print("父类")

class Child1(Parent):
    def func2(self):
        print("子类 1")

class Child2(Parent):
    def func3(self):
        print("子类 2")

obj1 = Child1()
obj2 = Child2()
obj1.func1()
obj2.func1()
obj1.func2()
obj2.func3()

混合继承

  • 由多种继承类型组成。
class School:
    def func1(self):
        print("学校")

class Student1(School):
    def func2(self):
        print("学生 1")

class Student2(School):
    def func3(self):
        print("学生 2")

class Student3(Student1, School):
    def func4(self):
        print("Student3 中的函数")

obj1 = Student3()
obj1.func1()
obj1.func2()

访问修饰符或说明符

  • 用于在实现继承时限制类变量和方法在类外部的访问。

类型:

  1. 公共访问修饰符
  2. 私有访问修饰符
  3. 受保护访问修饰符
class Student:
    def __init__(self):
        self._name = "哈利"  # 受保护的访问修饰符

    def _funName(self):  # 受保护的方法
        return "Aryan"

class Subject(Student):
    pass

obj = Student()
obj1 = Subject()
print(dir(obj))  # 列出 _funName、__init__ 等。

# 通过 Student 类的对象调用
print(obj._name)
print(obj._funName())

# 通过 Subject 类的对象调用
print(obj1._name)
print(obj1._funName())
  • 公共访问修饰符: 默认情况下,所有变量和方法都是公共的。

    • self.age = age -> 公开访问
  • 私有访问修饰符: 变量或方法只能在类内部访问。

    • 在 Python 中,没有私有访问修饰符的概念;但是,按照惯例,以 __ 开头的变量被认为是私有的。
    • 通常被理解为不使用,但仍然可以使用。
class Student:
    def __init__(self, age, name):
        self.__age = age  # 私有变量

    def __funName(self):  # 私有函数
        self.y = 34
        print(self.y)

class Subject(Student):
    pass

obj = Student(21, "Aryan")
obj1 = Subject()

# 以下所有操作都会给出属性错误
print(obj.__age)
print(obj.__funName())
print(obj1.__age)
print(obj1.__funName())

如何访问私有变量?*obj._Student__name*

方法重写

class Shape:
    def __init__(self, x, y):
        self.x = x
        self.y = y

    def area(self):
        return self.x * self.y

class Circle(Shape):
    def __init__(self, r):
        self.r = r
        super().__init__(r, r)

    def area(self):
        return 3.14 * super().area()

rec = Shape(3, 5)
print(rec.area())

# 输出:15

c = Circle(5)
print(c.area())  # 输出:78.5
  • 方法重写允许你在派生类中重新定义方法,从而覆盖基类中的方法。
  • 当你创建派生类的实例并调用重写的方法时,将执行派生类中的方法版本,而不是基类中的版本。

静态方法

静态方法属于类,而不是类的实例。

  • 使用 @staticmethod 装饰器定义。
  • 无权访问类的实例(即 self)。
  • 用于创建不需要访问实例数据的实用程序函数。
class Math:
   @staticmethod
   def add(a, b):
      return a + b

result = Math.add(1, 2)
print(result)  # 输出:3

类变量与实例变量

  • 类变量在类的所有实例之间共享。

    • 示例:用于存储所有实例通用的信息。
  • 实例变量对于类的每个实例都是唯一的。

    • 示例:用于存储每个实例特定的信息。

访问变量:

  • 类变量:ClassName.variableself.__class__.variable
  • 实例变量:self.variable_name
class Animal:
   species = "哺乳动物"  # 类变量

   def __init__(self, name):
      self.name = name  # 实例变量

a1 = Animal("狗")
a2 = Animal("猫")

print(a1.species)  # 输出:哺乳动物
print(a2.name)     # 输出:猫

练习:清理文件夹内的杂乱(重命名 PNG 文件)

根据序列号重命名文件夹中的所有 PNG 图像(例如,1.png2.png)。

import os

files = os.listdir("clutter_folder")
i = 1
for file in files:
    if file.endswith(".png"):
        os.rename(f"clutter_folder/{file}", f"clutter_folder/{i}.png")
        i += 1

库类练习

创建一个带有两个实例变量的 Library 类:noBooks(书籍数量)和 books。演示如何添加书籍并打印信息。

class Library:
   def __init__(self):
      self.noBooks = 0
      self.books = []

   def addBook(self, book):
      self.books.append(book)
      self.noBooks = len(self.books)

   def showInfo(self):
      print(f"书籍数量:{self.noBooks}")
      for book in self.books:
         print(book)

l1 = Library()
l1.addBook("哈利波特")
l1.addBook("霍比特人")
l1.showInfo()

# 输出:
# 书籍数量:2
# 哈利波特
# 霍比特人

Python 类方法

  • 类方法绑定到类,而不是实例。
  • 对整个类进行操作,而不是对特定实例进行操作。
  • 使用 @classmethod 装饰器定义。
  • 用于创建工厂方法或备选构造函数。
class Employee:
   company = "苹果"

   def show(self):
      print(f"姓名:{self.name},公司:{self.company}")

   @classmethod
   def changeCompany(cls, newCompany):
      cls.company = newCompany

e1 = Employee()
e1.name = "Aryan"
e1.show()  # 输出:姓名:Aryan,公司:苹果
Employee.changeCompany("特斯拉")
e1.show()  # 输出:姓名:Aryan,公司:特斯拉

类方法作为备选构造函数

class Employee:
   def __init__(self, name, salary):
      self.name = name
      self.salary = salary

   @classmethod
   def fromStr(cls, string):
      name, salary = string.split("-")
      return cls(name, int(salary))

e1 = Employee("Aryan", 1200)
print(e1.name)     # 输出:Aryan
print(e1.salary)   # 输出:1200

e2 = Employee.fromStr("John-1500")
print(e2.name)     # 输出:John
print(e2.salary)   # 输出:1500

有用的方法:dir()__dict__help()

  • dir():返回属性和方法列表,包括特殊方法。
  • __dict__:返回对象属性的字典表示形式。
  • help():显示对象的帮助文档。
class Person:
   def __init__(self, name, age):
      self.name = name
      self.age = age

p = Person("John", 30)
print(p.__dict__)   # 输出:{'name': 'John', 'age': 30}
print(dir(p))       # 输出:['__class__', '__delattr__', ...]

Super 关键字

  • super() 函数用于引用父类。
  • 在类继承中,用于扩展父类方法的行为非常有用。
class Employee:
   def __init__(self, name, id):
      self.name = name
      self.id = id

class Programmer(Employee):
   def __init__(self, name, id, lang):
      super().__init__(name, id)
      self.lang = lang

harry = Programmer("哈利", 23, "Python")
print(harry.name)  # 输出:哈利
print(harry.lang)  # 输出:Python

Dunder(魔术)方法

  • 自定义类行为的特殊方法。
  • 示例:实现加法、比较运算符等。
  1. __init__:在创建新实例时调用(构造函数)。
  2. __str____repr__:将对象转换为字符串。
  3. __len__:返回对象的长度。
  4. __call__:使对象可以像函数一样调用。
class Employee:
   def __init__(self, name):
      self.name = name

   def __len__(self):
      return len(self.name)

   def __str__(self):
      return f"员工:{self.name}"

   def __repr__(self):
      return f"Employee({self.name})"

   def __call__(self):
      print(f"你好,我是 {self.name}")

e = Employee("Aryan")
print(len(e))      # 输出:5
print(str(e))      # 输出:员工:Aryan
e()                # 输出:你好,我是 Aryan

方法重写

  • 允许你在派生类中重新定义方法。
  • 当你调用重写的方法时,将执行派生类方法。
class Shape:
   def __init__(self, x, y):
      self.x = x
      self.y = y

   def area(self):
      return self.x * self.y

class Circle(Shape):
   def __init__(self, r):
      super().__init__(r, r)

   def area(self):
      return 3.14 * super().area()

rect = Shape(3, 5)
print(rect.area())  # 输出:15

circle = Circle(5)
print(circle.area())  # 输出:78.5

运算符重载

  • 允许你为自定义数据类型重新定义数学和比较运算符的行为。
  • 示例:添加两个 Vector 对象。
class Vector:
   def __init__(self, i, j, k):
      self.i = i
      self.j = j
      self.k = k

   def __add__(self, other):
      return Vector(self.i + other.i, self.j + other.j, self.k + other.k)

   def __str__(self):
      return f"{self.i}i + {self.j}j + {self.k}k"

v1 = Vector(3, 5, 6)
v2 = Vector(1, 2, 9)
v3 = v1 + v2
print(v3)  # 输出:4i + 7j + 15k

注意: super() 有助于扩展基类方法的行为,而不是完全替换它。


练习:将 PDF 合并为一个 PDF

from PyPDF2 import PdfWriter
import os

merger = PdfWriter()
files = [file for file in os.listdir() if file.endswith(".pdf")]

for pdf in files:
    merger.append(pdf)

merger.write("Merged-pdf.pdf")
merger.close()

输出:

  • 将当前目录中的所有 PDF 文件合并为一个名为 Merged-pdf.pdf 的文件。

时间模块:

  • 提供了一组处理时间相关操作的函数,例如计时、格式化和时间转换。

  • 常用函数:

    • time.time():返回自 Epoch(1970 年)以来的当前时间(以秒为单位)。

      示例:

      import time
      start_time = time.time()
      print("当前时间:", start_time)
      
    • time.sleep(seconds):将当前线程的执行暂停指定的秒数。

      示例:

      import time
      print("开始")
      time.sleep(2)
      print("2 秒后结束")
      
    • time.strftime():根据特定格式将时间值格式化为字符串。

      示例:

      import time
      t = time.localtime()
      formatted_time = time.strftime("%Y-%m-%d, %H:%M:%S", t)
      print(formatted_time)
      

命令行实用程序:

  • 命令行程序对于自动化任务和高效地在开发工作流程中工作至关重要。

基本示例:

import argparse

parser = argparse.ArgumentParser()
parser.add_argument("arg1", help="Arg1 的描述")
parser.add_argument("arg2", help="Arg2 的描述")
args = parser.parse_args()

print(args.arg1)
print(args.arg2)

文件下载器示例:

import argparse
import requests
import shutil

def download_file(url, local_filename=None):
    if local_filename is None:
        local_filename = url.split('/')[-1]
    response = requests.get(url, stream=True)
    with open(local_filename, 'wb') as out_file:
        shutil.copyfileobj(response.raw, out_file)
    del response

if __name__ == "__main__":
    parser = argparse.ArgumentParser(description="从 URL 下载文件")
    parser.add_argument("url", help="文件的 URL")
    parser.add_argument("output", help="输出文件名")
    args = parser.parse_args()
    download_file(args.url, args.output)
    print("文件已下载:", args.output)

输出:

  • 从提供的 URL 下载文件,并使用指定的输出名称保存。

海象运算符 (:=):

  • 在 Python 3.8 中引入,海象运算符允许在表达式内进行赋值。

示例:

happy = False
print("之前:", happy)
print("之后:", happy := True)

foods = list()
while (food := input("你喜欢什么食物?")) != "quit":
    foods.append(food)

print("你喜欢的食物:", foods)

shutil 模块:

  • Python 中高级文件操作实用程序。

函数:

  • shutil.copy(src, dst):复制文件。
  • shutil.copy2(src, dst):复制文件以及元数据。
  • shutil.copytree(src, dst):递归复制目录。
  • shutil.move(src, dst):移动文件或目录。
  • shutil.rmtree(path):删除目录树。

Beautiful Soup (bs4):Web 抓取

  • Beautiful Soup 是一个用于 Web 抓取的 Python 库。
import requests
from bs4 import BeautifulSoup

url = "https://example.com"
r = requests.get(url)
soup = BeautifulSoup(r.text, "html.parser")

print(soup.prettify())

for heading in soup.find_all("h1"):
    print(heading.text)

输出:

  • 以结构化格式打印整个网页内容和所有 <h1> 标题。

生成器:

  • 生成器是特殊类型的函数,允许你逐个迭代值,而无需在内存中创建完整的列表。

示例:

def my_generator():
    for i in range(5):
        yield i

gen = my_generator()
print(next(gen))  # 输出:0

for j in gen:
    print(j)  # 输出:1, 2, 3, 4

函数缓存 (@lru_cache):

  • 缓存函数结果,以避免对相同输入进行重复计算,这对于昂贵的计算非常有用。

示例:

from functools import lru_cache
import time

@lru_cache(maxsize=None)
def fx(n):
    time.sleep(5)  # 模拟一个缓慢的函数
    return n * 5

print(fx(20))  # 第一次调用,需要 5 秒
print(fx(2))   # 第一次调用,需要 5 秒
print(fx(6))   # 第一次调用,需要 5 秒

# 缓存调用,输出是立即的
print(fx(20))
print(fx(2))
print(fx(6))

正则表达式 (Regex):

  • 使用模式匹配和操作字符串的强大工具。

基本正则表达式:

import re
pattern = r"表达式"
text = "你好,世界!"
match = re.search(pattern, text)

if match:
    print("找到匹配项!")
else:
    print("未找到匹配项。")

示例:

import re

text = "猫在帽子里"
pattern = r"[a-z]+at"
matches = re.findall(pattern, text)
print("匹配项:", matches)  # 输出:['cat', 'hat']

new_text = re.sub(pattern, "dog", text)
print("更新的文本:", new_text)  # 输出:"The dog is in the dog"

提取电子邮件:

import re

text = "邮箱是 example@example.com"
pattern = r"\w+@\w+\.\w+"
match = re.search(pattern, text)

if match:
    email = match.group()
    print("提取的电子邮件:", email)

AsyncIO

  • 允许以并发和非阻塞的方式进行高性能 I/O 操作。
  • 模块:asyncio
import asyncio
import requests

async def function1():
    url = "https://example.com/wallpaper.jpg"
    response = requests.get(url)
    open("instagram.ico", "wb").write(response.content)
    return "aryan"

async def function2():
    url = "https://example.com/preview.jpg"
    response = requests.get(url)
    open("insta2.png", "wb").write(response.content)

async def main():
    l = await asyncio.gather(function1(), function2())
    print(l)

asyncio.run(main())

输出:

  • instagram.icoinsta2.png 将被下载。
  • 将打印列表 ['aryan', None]

多线程

  • 允许在单个进程中并发运行多个执行线程。
  • 在 Python 中,我们使用 threading 模块来实现多线程。
  • 创建一个线程 -> 调用其 start() 方法。
  • join() 停止执行,直到线程完成。
import threading

def my_func():
    print("来自线程的问候", threading.current_thread().name)

thread = threading.Thread(target=my_func)
thread.start()
thread.join()

输出:

  • 来自线程的问候 Thread-1 (或类似,取决于线程名称)。

函数:

  1. threading.Thread(target, args)

    • 创建一个新线程,该线程使用参数运行目标函数。
  2. threading.Lock()

    • 创建一个锁,可用于同步线程之间对共享资源的访问。
    • 锁确保一次只有一个线程可以执行关键部分。

带有锁的示例:

import threading

def increment(counter, lock):
    for i in range(100):
        lock.acquire()
        counter[0] += 1
        lock.release()

if __name__ == "__main__":
    counter = [0]  # 使用列表允许在线程中进行修改
    lock = threading.Lock()
    threads = []

    for i in range(2):
        thread = threading.Thread(target=increment, args=(counter, lock))
        threads.append(thread)
        thread.start()

    for thread in threads:
        thread.join()

    print(f"最终计数器值:{counter[0]}")

输出:

  • 最终计数器值将为 200

使用 ThreadPoolExecutor

import time
from concurrent.futures import ThreadPoolExecutor

def func(seconds):
    print(f"休眠 {seconds} 秒")
    time.sleep(seconds)
    return seconds

def main():
    time1 = time.perf_counter()

    # 使用线程
    with ThreadPoolExecutor() as executor:
        t1 = executor.submit(func, 4)
        t2 = executor.submit(func, 2)
        t3 = executor.submit(func, 1)

        print(t1.result())
        print(t2.result())
        print(t3.result())

    time2 = time.perf_counter()
    print(f"在 {time2 - time1} 秒内完成")

main()

输出:

  • 线程将打印休眠语句,并且由于线程并发运行,因此总耗时将减少。

多进程

  • Python 中的一个模块,提供了一种并行运行多个进程的方法。
  • 允许你利用系统上的多个内核/处理器,这可以显著提高代码的性能。
import concurrent.futures
import requests
import os

def download_file(url, name):
    try:
        print(f"开始下载 {name}")
        response = requests.get(url)
        file_path = f"{name}.jpg"
        with open(file_path, "wb") as file:
            file.write(response.content)
        print(f"完成下载 {name}")
    except Exception as e:
        print(f"下载 {name} 时出错:{e}")

if __name__ == "__main__":
    url = "https://picsum.photos/200/300"
    with concurrent.futures.ProcessPoolExecutor() as executor:
        pros = []
        for i in range(50):
            pros.append(executor.submit(download_file, url, f"image_{i}"))

        for future in concurrent.futures.as_completed(pros):
            future.result()

输出:

  • 该脚本将并发下载 50 张图像。

多进程与多线程

序号多进程多线程1.添加 CPU 以提高计算能力。创建单个进程的多个线程以实现并发。2.同时执行多个进程。同时执行一个进程的多个线程。3.分为对称和非对称多进程。不分为类别。4.进程创建耗时。线程创建更经济。5.每个进程都拥有单独的地址空间。所有线程共享一个公共地址空间。


本文由gemini翻译自@ARYANK-08的python fundamentals