常州微信网站建设咨询,东莞网站建站推广,万网网站后台管理系统,大连建网站公司这篇文章整理了50个简洁的提示#xff0c;可以提高您的代码可读性和效率。这些提示来自个人项目、彻底的代码审查和与资深开发人员的启发性讨论。
无论您是新手还是经验丰富的开发人员#xff0c;这篇文章都应该能够帮助您学到一些东西。
这个列表包括常见的Python模式、核…这篇文章整理了50个简洁的提示可以提高您的代码可读性和效率。这些提示来自个人项目、彻底的代码审查和与资深开发人员的启发性讨论。
无论您是新手还是经验丰富的开发人员这篇文章都应该能够帮助您学到一些东西。
这个列表包括常见的Python模式、核心概念和最佳实践。 由于没有特定的顺序请随时直接跳转到您感兴趣的部分。
不再废话让我们来看看吧
1 — 三元操作符
Python中的三元操作符提供了一种内联方式来编写条件表达式。当您需要根据条件为变量分配一个值时它们特别有用。
age 25
status 成年人 if age 18 else 未成年人print(status)
# 成年人在这个示例中如果年龄大于或等于18status变量的值将是成年人否则将是未成年人。
当它们用于列表推导式时三元操作符非常有用
scores [100, 46, 54, 23, 20, 99]
threshold 50
results [通过 if score threshold else 未通过 for score in scores]print(results)
# [通过, 未通过, 通过, 未通过, 未通过, 通过]或者用于lambda函数
scores [100, 46, 54, 23, 20, 99]
threshold 50results map(lambda score: 通过 if score threshold else 未通过, scores)
print(results)
# [通过, 未通过, 通过, 未通过, 未通过, 通过]2 — 上下文管理器
想象一下您用Python打开一个文件在文件中写入了一些行然后在您甚至无法关闭它之前发生了异常。
虽然这对于初学者开发人员来说似乎不是什么问题但它会占用一个永远不会被清除的内存资源文件描述符并且可能会阻止部分数据被写入。
上下文管理器可以帮助您避免这种情况。它们用于管理资源并确保这些资源被正确初始化和清理。
它们通过封装资源管理的逻辑在上下文管理器对象内有助于编写更可读和可维护的代码。
→ 最常见的上下文管理器是使用open创建的
with open(file.txt, r) as file:# 如果在这里发生了任何错误data file.read()open()函数返回一个文件对象它充当上下文管理器。当with语句内部的块退出时它会自动关闭文件确保正确的清理。
您还可以在其他情况下使用上下文管理器来处理 数据库连接
import psycopg2with psycopg2.connect(databasemydb) as conn:cursor conn.cursor()cursor.execute(SELECT * FROM table)results cursor.fetchall()在这个示例中psycopg2库的connect()方法返回一个连接对象它充当上下文管理器当块退出时会自动关闭连接。 锁定资源
import threading
lock threading.Lock()def some_function():with lock:# 临界代码段在这里threading模块的Lock()对象被用作上下文管理器以确保一次只有一个线程可以访问关键代码段。
3 — 创建自己的上下文管理器
有时您可能需要定义自己的上下文管理器。
为此您需要定义一个实现__enter__()和__exit__()方法的类
enter()在with块启动时调用exit()在执行离开with代码块时调用
以下是一个测量代码块执行时间的自定义上下文管理器示例
示例1计时器
import timeclass Timer:def __enter__(self):self.start_time time.time()def __exit__(self, exc_type, exc_val, exc_tb):elapsed_time time.time() - self.start_timeprint(f执行时间0.0556秒)这个示例非常简单。让我们看看另一个模仿open行为的示例。
示例2自定义文件打开器
class WritableFile:def __init__(self, file_path):self.file_path file_pathdef __enter__(self):print(打开文件)self.file_obj open(self.file_path, modew)return self.file_objdef __exit__(self, exc_type, exc_val, exc_tb):if self.file_obj:self.file_obj.close()print(文件成功关闭)虽然这些示例相当简单但它们应该为您提供一个构建更高级上下文管理器的起点代码段其中执行适当的资源清理。
4 — 枚举
如果您想要迭代一个序列并同时跟踪每个项目的索引那么应该使用enumerate函数。
它通过消除手动管理单独的索引变量使代码更加简洁。
fruits [苹果, 香蕉, 橙子]
for index, fruit in enumerate(fruits):print(f索引{index}水果{fruit})# 索引0水果苹果
# 索引1水果香蕉
# 索引2水果橙子5 — Zip
zip函数允许同时迭代多个序列
names [Alice, Bob, Charlie]
ages [25, 30, 35]
for name, age in zip(names, ages):print(f姓名{name}年龄{age})# 姓名Alice年龄25
# 姓名Bob年龄30
# 姓名Charlie年龄35作为有趣的用例zip还可以从两个列表创建一个字典其中键来自第一个列表值来自第二个列表。
keys [a, b, c]
values [1, 2, 3]
my_dict dict(zip(keys, values))
print(my_dict)# {a: 1, b: 2, c: 3}6 — 使用sorted对复杂对象进行排序
sorted函数允许您根据某些属性对复杂对象进行排序。
要访问要排序的属性值您必须使用自定义的key函数。
假设您要根据age键对这些人进行排序。
people [{name: Alice, age: 25},{name: Bob, age: 30},{name: Charlie, age: 20}
]
只需将key参数设置为指向age值。sorted_people sorted(people, keylambda x: x[age])
print(sorted_people)# [{name: Charlie, age: 20}, {name: Alice, age: 25}, {name: Bob, age: 30}]如果将字典替换为对象它的工作方式也是一样的
class Person:def __init__(self, name, age):self.name nameself.age agepeople [Person(Alice, 25),Person(Bob, 30),Person(Charlie, 20)
]
sorted_people sorted(people, keylambda x: x.age)
print([person.name for person in sorted_people])print(sorted_people)# [Charlie, Alice, Bob]7 — 使用生成器节省内存
Python生成器是一种可迭代类型可用于即时生成一系列值而不必将它们全部存储在内存中。它们使用yield关键字定义而不是return。
这是一个计算斐波那契数的简单生成器。
def fibonacci_generator():a, b 0, 1while True:yield aa, b b, a b调用这个函数实际上不会运行它。它创建并返回一个生成器对象。
fib fibonacci_generator()fib
# generator object fibonacci_generator at 0x7fea39c31890这个生成器对象仅在传递给next函数时生成斐波那契值。
next(fb)
# 0
next(fb)
# 1
next(fb)
# 1
next(fb)
# 2或者使用for循环迭代在底层基本上调用了next函数。
这是内存高效的因为它避免了预先生成整个无限序列。
生成器的一个自然用例是逐行或分块读取大型数据集
def read_large_file(filename):with open(filename, r) as file:for line in file:yield line#逐行处理而不是加载整个文件
file_generator read_large_file(large_file.txt)for line in file_generator:process_line(line) #处理8 — 使用f-strings改进字符串格式化
f-strings改进了字符串格式化语法它们是字符串文字以f开头包含用于替换为其值的表达式的花括号。
语法非常简单。
name Alice
age 25
print(f你好{name}你今年{age}岁) # 你好Alice你今年25岁甚至可以用它来计算任意表达式比如函数调用
def add_numbers(a, b):return a bx 5
y 3
print(f{x}和{y}的和是{add_numbers(x, y)}。) # 输出5和3的和是8。带有特定精度的浮点数
pi 3.14159265359
print(fπ的值约为{pi:.2f}。)
# 输出π的值约为3.14。对象。
class Person:def __init__(self, name, age):self.name nameself.age ageperson Person(Bob, 25)
print(f姓名{person.name}年龄{person.age})
# 输出姓名Bob年龄25字典在字典键周围使用简单的引号
data_scientist {name: Ahmed BESBES, age: 32}
fThis data scientist is {data_scientist[name]}, aged {data_scientist[age]}.这个数据科学家是Ahmed BESBES年龄是32岁。 9 — 使用迭代器协议构建可迭代对象 您是否曾经想知道简单的for循环在幕后是如何工作的
答案不在for循环本身而是在被迭代的对象中也称为可迭代对象。这些可以是列表、字典或集合。
事实上可迭代对象支持迭代器协议并实现__iter__()和__next__()双下划线方法。
这些双下划线方法是使得可以迭代一组元素或执行自定义迭代的核心方法。
下面是一个自定义迭代器的示例它接受一个数字列表并在运行时生成它们的平方
class SquareIterator:def__init__(self, numbers):self.numbers numbersself.index 0def __iter__(self):return selfdef __next__(self):if self.index len(self.numbers):raise StopIterationsquare self.numbers[self.index] ** 2self.index 1return square在__iter__()方法中返回迭代器对象本身。当初始化迭代器时调用此方法。
在__next__()方法中定义检索迭代中下一个元素的逻辑。
当没有更多元素可以迭代时此方法应引发StopIteration异常。请注意索引在这里递增以跟踪其位置
我们可以像这样使用这个自定义迭代器
numbers [1, 2, 3, 4, 5]
iterator SquareIterator(numbers)for square in iterator:print(square)# 1
# 4
# 9
# 16
# 2510 — 创建自定义异常类以记录您的代码
我从未考虑过创建自定义异常类。我只依赖于内置的异常。
事实是在大型代码库中使用它们会带来多重好处。
它们允许您创建更具体和有意义的异常准确表示代码中发生的错误或异常情况。这有助于调试提高了协作
如果您的同事开始向同一存储库推送代码他们更容易通过具有明确消息而不是通用的ValueError异常来调试错误
这是一个自定义异常类的示例当输入字符串长度超过阈值时引发异常。
class NameTooLongError(Exception):用于过长名称的自定义异常。def __init__(self, name, max_length):self.name nameself.max_length max_lengthsuper().__init__(f名称{name}太长允许的最大长度为{max_length}个字符。)def process_name(name):max_length 10 # 允许的最大名称长度if len(name) max_length:raise NameTooLongError(name, max_length)else:print(名称处理成功, name)# 示例用法
try:input_name AVeryLongNameprocess_name(input_name)
except NameTooLongError as e:print(错误, e)本文由mdnice多平台发布