您当前的位置:首页 > 电脑百科 > 程序开发 > 语言 > Python

Python代码优化小技巧

时间:2023-09-07 14:01:40  来源:微信公众号  作者:测试玩家勇哥

Python/ target=_blank class=infotextkey>Python 是 一种用着很爽的语言。Python也有着很多特性和技巧,可以帮助我们编写更高效、更优雅、更易维护的代码。下面勇哥将介绍一些我常用的Python代码优化的简单小技巧,少写很多代码,包括:

  • • 短路运算(Short-circuit operation)

  • • 切片(Slice)

  • • 列表推导式(List Comprehension)

  • • 生成器表达式(Generator Expression)

  • • 枚举(Enumerate)

  • • 三元运算符(Ternary Operator)

  • • 字典(Dict)

  • • 装饰器(Decorator)

  • • 上下文管理器(Context Manager)

  • • lambda表达式(Lambda Expression)

  • • map函数(Map Function)

  • • filter函数(Filter Function)

  • • @property 装饰器(Property Decorator)

  • • __slots__ 属性(Slots Attribute)

短路运算(Short-circuit operation)

咱们都知道,短路运算也就是 ”与 ,或 ,非“ 这几个组成。但是有些时候,我们很多 if-else语句其实可以使用这种短路运算来简写代码的

例, 获取用户信息,不存在的用户则返回匿名用户, 代码:

def get_user(user):
    # 常规代码
    if user:
        return user
    return "匿名用户"
    
# 短路来简写代码

def get_user(user):
    return user or "匿名用户"

使用短路运算处理,那么就只需要一行代码即可,这样写也挺易读的。

切片替代循环(Slice)

使用切片代替循环或递归来操作序列。切片是一种用于从一个序列(如字符串、列表、元组等)中获取一部分或全部元素的语法。

例,反转数据,代码:

# 使用循环
def reverse(lst):
    new_lst = []
    for i in range(len(lst) - 1, -1, -1):
        new_lst.Append(lst[i])
    return new_lst

lst = [1, 2, 3, 4, 5]
print(reverse(lst)) # [5, 4, 3, 2, 1]

# 使用切片
def reverse(lst):
    return lst[::-1]

lst = [1, 2, 3, 4, 5]
print(reverse(lst)) # [5, 4, 3, 2, 1]

切片的操作比循环或递归更简单并且高效,因为切片是基于内置函数实现的,而循环或递归是基于自定义函数实现。

列表推导式(List Comprehension)

列表推导式是一种用于从一个可迭代对象(如列表、元组、字典、集合等)创建一个新的列表的简洁的语法。

例,从一个列表中筛选出所有的偶数,并将它们乘以2,代码:

# 使用普通的循环
lst = [1, 2, 3, 4, 5, 6]
new_lst = []
for x in lst:
    if x % 2 == 0:
        new_lst.append(x * 2)
print(new_lst) # [4, 8, 12]
# 使用列表推导式
lst = [1, 2, 3, 4, 5, 6]
new_lst = [x * 2 for x in lst if x % 2 == 0]
print(new_lst) # [4, 8, 12]

一行代码实现循环、条件判断和赋值等操作,提高了代码的可读性和效率,而且运行速度也更快(可以思考一下为什么更快)。

生成器表达式(Generator Expression)

生成器表达式是一种类似于列表推导式的语法,但是它不会一次性生成一个完整的列表,而是返回一个生成器对象,可以按需逐个产生元素。

例,计算一个列表中所有偶数的平方和,代码:

# 使用普通的循环
lst = [1, 2, 3, 4, 5, 6]
sum = 0
for x in lst:
    if x % 2 == 0:
        sum += x ** 2
print(sum) # 56
# 使用生成器表达式
lst = [1, 2, 3, 4, 5, 6]
sum = sum(x ** 2 for x in lst if x % 2 == 0)
print(sum) # 56

这个生成器表达式可以节省内存空间,提高性能,适合处理大量或无限的数据,而且不会占用额外的内存空间,特别适用于读取大批量的数据。当然我们也可以用yeild也能做一个生成器,这个太东西很牛逼。

枚举(Enumerate)

枚举是一种用于同时获取可迭代对象中的元素和索引的函数。枚举可以避免使用额外的变量来记录索引,提高了代码的可读性和效率。

例,打印一个列表中每个元素及其对应的索引,代码:

# 使用普通的循环
lst = ["a", "b", "c", "d", "e"]
index = 0
for x in lst:
    print(index, x)
    index += 1
# 输出:
# 0 a
# 1 b
# 2 c
# 3 d
# 4 e
# 使用枚举
lst = ["a", "b", "c", "d", "e"]
for index, x in enumerate(lst):
    print(index, x)
# 输出:
# 0 a
# 1 b
# 2 c
# 3 d
# 4 e

使用枚举的代码更加简洁和清晰,而且不需要手动更新索引。

三元运算符(Ternary Operator)

三元运算符是一种用于根据一个条件表达式来选择两个不同的值的简洁的语法。

例,根据一个数字的正负来赋值一个字符串,代码:

# 使用普通的if-else语句
num = -5
if num > 0:
    sign = "positive"
else:
    sign = "negative"
print(sign) # negative
# 使用三元运算符
num = -5
sign = "positive" if num > 0 else "negative"
print(sign) # negative

三元运算符可以用一行代码实现简单的条件判断和赋值,提高了代码的可读性和效率,而且不需要多余的变量和语句。

字典处理条件判断

遇到if循环语句很长的时候,其实可以使用字典来替代,两者的执行效率没有试验过,感觉差不了多少。

例, 使用字典来判断返回值, 代码:

# 使用多个if-elif-else语句
def foo(x):
    if x == "a":
        return 1
    elif x == "b":
        return 2
    elif x == "c":
        return 3
    else:
        return -1

print(foo("a")) # 1
print(foo("d")) # -1

# 使用字典
def foo(x):
    dic = {"a": 1, "b": 2, "c": 3}
    return dic.get(x, -1)

print(foo("a")) # 1
print(foo("d")) # -1

合理利用字典的get方法,可以减少很多代码的使用。

装饰器(Decorator)

装饰器是一种用于在不修改原函数定义和调用的情况下,给函数添加额外的功能或修改其行为的语法。

例,给一个函数添加一个计时的功能,记录其运行时间,代码:

# 使用普通的函数调用
import time

def foo():
    # do something
    time.sleep(1)

start = time.time()
foo()
end = time.time()
print(f"foo() took {end - start} seconds to run.") 
# 使用装饰器
import time

def timer(func):
    def wrapper(*args, **kwargs):
        start = time.time()
        result = func(*args, **kwargs)
        end = time.time()
        print(f"{func.__name__}() took {end - start} seconds to run.")
        return result
    return wrapper

@timer # 相当于 foo = timer(foo)
def foo():
    # do something
    time.sleep(1)

foo() 

装饰器能做的事太多了,比如flask 框架,真尼玛装饰器用到飞天。勇哥也就一般用于实现一些通用的功能,如日志、缓存、计时、权限检查等,让代码可复用更强一写。

上下文管理器(Context Manager)

上下文管理器是一种用于在执行某些操作之前和之后自动执行一些预设的操作的语法。上下文管理器可以用于实现一些资源管理的功能,

例如,打开一个文件,读取其内容,并在完成后自动关闭文件,代码:

# 使用普通的try-finally语句
file = open("test.txt", "r")
try:
    content = file.read()
    print(content)
finally:
    file.close()
# 使用上下文管理器
with open("test.txt", "r") as file:
    content = file.read()
    print(content)

使用上下文管理器我们一般用于 打开和关闭文件、获取和释放锁、连接和断开数据库等。代码的安全性问题和可读性也很好处理。

Lambda 表达式(Lambda Expression)

lambda表达式(代替简单的函数定义来创建匿名函数。lambda表达式是一种用于定义一个只有一行代码的函数的简洁的语法。

例,处理排序sorted,指定字段,代码:

lst = [9,2,3,4,5,5,1,2,3]
# 不使用lambda表达式
def add(item):
   return item

print(sorted(add, item))

# 使用lambda表达式
print(sorted(lst, key=lambda x:x))

lambda表达式我们一般用来实现一些简单的功能,如排序、过滤、映射等。使用匿名函数,代码有时候少写一些外,还有一点就是 lambda 表达式用完就会在内存中舍弃,也挺好。

map 函数

map函数代替循环来对可迭代对象中的每个元素应用一个函数。map函数是一种用于将一个函数作用于一个可迭代对象中的每个元素,并返回一个新的可迭代对象的函数。

例,将一批字符列表字符串转数字列表,代码:

# 不使用map函数
lst = ["1", "2", "3", "4", "5"]
new_lst = []
for x in lst:
    new_lst.append(int(x))
print(new_lst) # [1, 2, 3, 4, 5]

# 使用map函数
lst = ["1", "2", "3", "4", "5"]
new_lst = list(map(int, lst))
print(new_lst) # [1, 2, 3, 4, 5]

是不是看起来代码又少了很多,而且这种内置函数,一般速度都比咱们自己写的代码运行效率高,基于这个强大的高阶函数,我们可以用来实现一些批量处理的功能,如类型转换、格式化、计算,数据合并等。

filter 函数

filter函数代替循环来从可迭代对象中筛选出满足一个条件的元素。filter函数是一种用于将一个条件函数作用于一个可迭代对象中的每个元素,并返回一个只包含满足条件元素的新的可迭代对象的函数。

例,从一个列表中挑选符合要求的数据出来组成另一个列表,代码:

# 不使用filter函数
lst = [1, 2, 3, 4, 5]
new_lst = []
for x in lst:
    if x % 2 == 0:
        new_lst.append(x)
print(new_lst) # [2, 4]

# 使用filter函数
lst = [1, 2, 3, 4, 5]
new_lst = list(filter(lambda x: x % 2 == 0, lst))
print(new_lst) # [2, 4]

filter函数可以用于实现一些筛选和过滤的功能,如删除空值、去重、选择子集等,也是一个很牛的高阶函数。

@properyt 装饰器

@property 装饰器有些时候可以用来替代 getersetter 方法来管理类书信。这个装饰器装饰的函数会转为一个属性的语法,可以在访问和修改属性的时候,执行一些额外的操作,不用显式调用。

例,对类属性的修改与获取, 代码:

# 不使用@property装饰器
class Person:
   def __init__(self, name, age):
       self.name = name
       self.age = age

   def get_name(self):
       return self.name

   def set_name(self, name):
       if not isinstance(name, str):
           rAIse TypeError("name must be a string")
       self.name = name

   def get_age(self):
       return self.age

   def set_age(self, age):
       if not isinstance(age, int):
           raise TypeError("age must be an integer")
       if age < 0 or age > 150:
           raise ValueError("age must be between 0 and 150")
       self.age = age

p = Person("kira", 40) # 实例化
print(p.get_name()) # kira
print(p.get_age()) # 40
p.set_name("勇哥")
p.set_age(35)
print(p.get_name()) # 勇哥
print(p.get_age()) # 35

# 使用@property装饰器
class Person:
   def __init__(self, name, age):
       self._name = name
       self._age = age

   @property
   def name(self):
       return self._name

   @name.setter
   def name(self, name):
       if not isinstance(name, str):
           raise TypeError("name must be a string")
       self._name = name

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

   @age.setter
   def age(self, age):
       if not isinstance(age, int):
           raise TypeError("age must be an integer")
       if age < 0 or age > 150:
           raise ValueError("age must be between 0 and 150")
       self._age = age

p = Person("kira", 30)
print(p.name) # kira
print(p.age) # 30
p.name = "勇哥"
p.age = 35
print(p.name) # 勇哥
print(p.age) # 35

从上面的代码,我们就可以了解到@property 可以做的事就很多了,比如实现属性管理,数据验证,类型转换,缓存... 可读性和安全性也不错.

slots属性

来到本文的最后一个要分享的 __slots__ 属性,这个事用来指定一个类可以有那些属性的语法,可以用来替代一下__dict__ 来节省类的内存空间,因为他避免了给每个实例创建一个 __dict__ 属性来存储所有属性和值。一般用于内存优化。

例,指定一个类实例时只有指定的属性,代码:

# 不使用__slots__属性
class Person:
   def __init__(self, name, age):
       self.name = name
       self.age = age

p = Person("勇哥", 90)
print(p.__dict__) 
print(p.__sizeof__()) 

输出

{'name': '测试玩家勇哥', 'age': 90}
32
# 使用__slots__属性
class Person:
    # 指定该类只能拥有name和age两个属性
    __slots__ = ("name", "age")

    def __init__(self, name, age):
        self.name = name
        self.age = age

p = Person("Alice", 20)
print(p.__sizeof__()) 
print(p.__dict__) 

输出

Traceback (most recent call last):
 File "D:appapitestdebugts.py", line 82, in <module>
   print(p.__dict__) # AttributeError: 'Person' object has no attribute '__dict__'
AttributeError: 'Person' object has no attribute '__dict__'
32

很明显,这个类已经没有了__dict__属性了,也就是可以减少内存占用,提高访问速度这种玩意,但是也有不好的地方,比如不能多重继承了,也不能添加新属性。要打印出来你限制的属性也就只能dir 或者 getter来获取了。总之小伙伴们看着使用吧。



Tags:Python代码   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,不构成投资建议。投资者据此操作,风险自担。如有任何标注错误或版权侵犯请与我们联系,我们将及时更正、删除。
▌相关推荐
如何进行Python代码的代码重构和优化?
Python是一种高级编程语言,它具有简洁、易于理解和易于维护的特点。然而,代码重构和优化对于保持代码质量和性能至关重要。什么是代码重构?代码重构是指在不改变代码外部行为的...【详细内容】
2024-02-22  Search: Python代码  点击:(33)  评论:(0)  加入收藏
PyCharm编辑器结合Black插件,轻松实现Python代码格式化
1、简介使用Black对Python代码进行格式化,可使代码看起来更美观。但是,随着项目规模不断变大,对每个文件运行Black变得很繁琐。能否在文件保存后立即运行Black呢?本文就来介绍在...【详细内容】
2023-12-06  Search: Python代码  点击:(191)  评论:(0)  加入收藏
六个技巧,提升Python代码性能!
很多小伙伴们总是会吐槽 Python 的性能速度慢。但是事实上程序运行速度的快慢都在很大程度上取决于编写程序的开发人员,以及开发人员的算法能力和对代码的优化能力。Python...【详细内容】
2023-11-13  Search: Python代码  点击:(188)  评论:(0)  加入收藏
你写的Python代码到底多快?这些测试工具了解了解
当我们写完一个脚本或一个函数,首先能保证得到正确结果,其次尽可能的快(虽然会说Py这玩意咋整都慢,但有的项目就是得要基于Py开发)本期将总结几种获取程序运行时间的方法,极大的帮...【详细内容】
2023-11-03  Search: Python代码  点击:(218)  评论:(0)  加入收藏
八个重构技巧使得Python代码更Pythonic
我们可以把这个 else 子句移到最开始。这也称为警卫声明。所以如果条件不成立,我们就不会执行其余的函数代码。这样就去掉了一个 else 子句,现在整个代码中的缩进少了一层。这...【详细内容】
2023-09-26  Search: Python代码  点击:(312)  评论:(0)  加入收藏
Python代码优化小技巧
Python 是 一种用着很爽的语言。Python也有着很多特性和技巧,可以帮助我们编写更高效、更优雅、更易维护的代码。下面勇哥将介绍一些我常用的Python代码优化的简单小技巧,少写...【详细内容】
2023-09-07  Search: Python代码  点击:(180)  评论:(0)  加入收藏
用Python给视频加水印
最新在小破站:Python自动化办公社区录制教程《给小白的50讲Python自动化办公》,考虑到版权问题,想给视频加个水印。但是找了一圈,没找到特别好用的软件工具,那就自己写一个吧。今...【详细内容】
2023-08-28  Search: Python代码  点击:(242)  评论:(0)  加入收藏
用AI写了个Python代码,拿来即用!
今年很火热的一个话题是“选什么专业才不会被AI抢饭碗”,对于一众码农来说,其实可以换个角度考虑“怎么利用AI去抢别人饭碗”网传AI替代率TOP25的职业当下AI狂飙的时代,AI能作...【详细内容】
2023-07-11  Search: Python代码  点击:(208)  评论:(0)  加入收藏
你必须知道的常用的足够简练的 11 个 Python代码
许多程序员喜欢Python,因为它的语法简单简洁。下面提供的这些 Python 代码足够简练,可用于解决常见问题。 1.提取字典的键值对dict1 = {&#39;A&#39;:33, &#39;B&#39;:43, &#39...【详细内容】
2023-05-21  Search: Python代码  点击:(336)  评论:(0)  加入收藏
您的Python代码需要重构吗?学会使用模块,让代码更加模块化!
Python模块是Python代码的组织单位,可以包含变量、函数、类和其他Python代码。模块可以在其他Python代码中引入和使用。在本节中,我们将介绍Python模块的基础知识。模块的文...【详细内容】
2023-05-08  Search: Python代码  点击:(216)  评论:(0)  加入收藏
▌简易百科推荐
Python 可视化:Plotly 库使用基础
当使用 Plotly 进行数据可视化时,我们可以通过以下示例展示多种绘图方法,每个示例都会有详细的注释和说明。1.创建折线图import plotly.graph_objects as go# 示例1: 创建简单...【详细内容】
2024-04-01  Python技术    Tags:Python   点击:(8)  评论:(0)  加入收藏
Python 办公神器:教你使用 Python 批量制作 PPT
介绍本文将介绍如何使用openpyxl和pptx库来批量制作PPT奖状。本文假设你已经安装了python和这两个库。本文的场景是:一名基层人员,要给一次比赛活动获奖的500名选手制作奖状,并...【详细内容】
2024-03-26  Python技术  微信公众号  Tags:Python   点击:(16)  评论:(0)  加入收藏
Python实现工厂模式、抽象工厂,单例模式
工厂模式是一种常见的设计模式,它可以帮助我们创建对象的过程更加灵活和可扩展。在Python中,我们可以使用函数和类来实现工厂模式。一、Python中实现工厂模式工厂模式是一种常...【详细内容】
2024-03-07  Python都知道  微信公众号  Tags:Python   点击:(31)  评论:(0)  加入收藏
不可不学的Python技巧:字典推导式使用全攻略
Python的字典推导式是一种优雅而强大的工具,用于创建字典(dict)。这种方法不仅代码更加简洁,而且执行效率高。无论你是Python新手还是有经验的开发者,掌握字典推导式都将是你技能...【详细内容】
2024-02-22  子午Python  微信公众号  Tags:Python技巧   点击:(32)  评论:(0)  加入收藏
如何进行Python代码的代码重构和优化?
Python是一种高级编程语言,它具有简洁、易于理解和易于维护的特点。然而,代码重构和优化对于保持代码质量和性能至关重要。什么是代码重构?代码重构是指在不改变代码外部行为的...【详细内容】
2024-02-22  编程技术汇    Tags:Python代码   点击:(33)  评论:(0)  加入收藏
Python开发者必备的八个PyCharm插件
在编写代码的过程中,括号几乎无处不在,以至于有时我们会拼命辨别哪个闭合括号与哪个开头的括号相匹配。这款插件能帮助解决这个众所周知的问题。前言在PyCharm中浏览插件列表...【详细内容】
2024-01-26  Python学研大本营  微信公众号  Tags:PyCharm插件   点击:(84)  评论:(0)  加入收藏
Python的Graphlib库,再也不用手敲图结构了
Python中的graphlib库是一个功能强大且易于使用的工具。graphlib提供了许多功能,可以帮助您创建、操作和分析图形对象。本文将介绍graphlib库的主要用法,并提供一些示例代码和...【详细内容】
2024-01-26  科学随想录  微信公众号  Tags:Graphlib库   点击:(86)  评论:(0)  加入收藏
Python分布式爬虫打造搜索引擎
简单分布式爬虫结构主从模式是指由一台主机作为控制节点负责所有运行网络爬虫的主机进行管理,爬虫只需要从控制节点那里接收任务,并把新生成任务提交给控制节点就可以了,在这个...【详细内容】
2024-01-25  大雷家吃饭    Tags:Python   点击:(58)  评论:(0)  加入收藏
使用Python进行数据分析,需要哪些步骤?
Python是一门动态的、面向对象的脚本语言,同时也是一门简约,通俗易懂的编程语言。Python入门简单,代码可读性强,一段好的Python代码,阅读起来像是在读一篇外语文章。Python这种特...【详细内容】
2024-01-15  程序员不二    Tags:Python   点击:(162)  评论:(0)  加入收藏
Python语言的特点及应用场景, 同其它语言对比优势
Python语言作为一种高级编程语言,具有许多独特的特点和优势,这使得它在众多编程语言中脱颖而出。在本文中,我们将探讨Python语言的特点、应用场景以及与其他语言的对比优势。一...【详细内容】
2024-01-09    今日头条  Tags:Python语言   点击:(253)  评论:(0)  加入收藏
站内最新
站内热门
站内头条