你可能不知道的 6 个实用 Python 语言特性
数据类
任何及所有
高级切片操作员
论点剖析
函数工具
邓德/魔法方法
Python 编程语言的优势之一在于,它既易于初学者学习,同时又能为高级用户带来巨大的回报。
数据类
数据类是专门用作数据容器的类。它们通常不包含任何业务逻辑。
Python 提供了一个@dataclass装饰器,添加到类中后,它会自动生成几个有用的方法,这样你就无需手动编写它们。这些方法包括__init__生成构造函数的方法、__str__生成__repr__字符串表示的方法以及__eq__检查类实例是否相等的方法。
定义数据类很简单。
@dataclass()
class Article:
title: str
author: str
published_on: datetime
views: int
likes: int
您还可以选择为变量设置默认值。
@dataclass()
class Article:
title: str = "John Doe"
author: str = "Unknown"
published_on: datetime = datetime.now()
views: int = 0
likes: int = 0
如需查看自动生成方法的完整列表,您可以查阅官方文档。
任何及所有
有时,在执行某个操作之前,例如在语句中,需要检查多个条件if。Python 提供了布尔and运算or符来评估此类逻辑表达式。但是,当条件数量非常多时,语句可能会变得相当冗长笨拙。
` any()and`all()方法只是更简洁、更易读地一次性评估大量布尔表达式的方法。`is`any()等价于一系列or操作,而all()`is` 等价于一系列and操作。
假设你得到一份某学生的成绩清单……
marks = [67, 85, 48, ]
passing_marks = 33
……你想检查该学生是否符合升入下一年级的资格。一种方法是将每次比较结果与and运算符连接起来:
if marks[0] > passing_marks and marks[1] > passing_marks and marks[2] > passing_marks:
promoted = True
else:
promoted = False
您可以使用以下all()函数使这段代码更易于阅读:
if all([marks[0] > passing_marks, marks[1] > passing_marks, marks[2] > passing_marks]):
promoted = True
else:
promoted = False
最后,你可以将它与列表推导式结合起来,得到一个简洁明了的解决方案:
if all([subject_marks > passing_marks for subject_marks in marks]):
promoted = True
else:
promoted = False
这两个功能与运算符结合使用,可以进一步扩展其功能not。
以下是对这些方法的简要概述。
any()返回:True如果至少一个参数的值为 True。all()返回True所有参数都为 True 的情况not any()True如果所有参数都不为 True,则返回 true。not all():True如果至少一个参数的值为 False,则返回 true。
高级切片操作员
切片运算符通常用于访问列表或字符串的特定部分。
string = "Python is awesome!"
string[3] # 'h'
string[4:7] # 'on '
它还有许多更高级的用法。例如,可以使用负索引从末尾而不是开头进行切片。
string[-2] # 'e'
您还可以指定“步长”来跳过切片时一定数量的元素。
string[2:9:2] # 'to s'
步长值可以为负数。这将导致列表/字符串按相反顺序切片。
string[9:2:-2] # ' inh'
反转数组或列表的常用快捷方法是使用切片[::-1]。
string[::-1] # '!emosewa si nohtyP'
论点剖析
*和**是特殊运算符,允许将多个项目打包到(或从)单个变量中解包。
你可能在函数定义中见过 `and`*args和 ` **kwargspresent` 这两个词。当出现在函数定义中时,`and` 运算*符将多个参数合并成一个元组,而 ` **present` 运算符将多个关键字参数合并成一个字典。
def product(*args):
res = 1
for arg in args:
res *= arg
return res
product(3, 4, 5)
def print_dict(**kwargs):
for key in kwargs:
print(f"{key}: {kwargs[key]}")
print_dict(firstname="Bikramjeet", lastname="Singh")
另一方面,当出现在函数调用的上下文中时,它们的作用正好相反——*运算符将列表/元组的内容展开为单独的参数,而**运算符将字典的内容展开为单独的关键字参数。
list_of_nums = [3, 4, 5]
product(*list_of_nums)
d = {"firstname": "Bikramjeet", "lastname": "Singh"}
print_dict(**d)
对于参数数量较多的函数,通常最好先将它们收集到一个字典中,然后再传递给函数。
def my_function(arg1, arg2, arg3, arg4 ... ):
...
params = {'arg1': ...}
my_function(**params)
这些运算符的另一个用途是组合列表和字典。
combined_list = [*l1, *l2]
combined_dict = {**d1, **d2}
函数工具
Python 支持高阶函数——即可以接受其他函数并返回其他函数的函数。高阶函数的概念是 Python 其他几个特性(例如装饰器)的核心。
functools包提供了一些用于处理高阶函数的实用辅助函数。让我们来看其中的一些。
部分的
在某些情况下,您可能需要创建现有通用函数的“特化”版本。这可以通过“冻结”某些基本函数参数的值来实现。
考虑一个简单的函数,用于计算一个数的n次方:
def pow(base, exp):
res = 1
for i in range(exp):
res *= base
return res
pow(2, 3) # returns 8
平方运算非常常见,因此值得专门为此创建一个函数,这样我们就无需每次都传递 2 作为参数。然而,与其重写现有pow函数,我们可以直接在方法中复用它functools.partial。
square = functools.partial(pow, exp=2)
square(4) # returns 16, equivalent to pow(4, 2)
类似地,我们也可以创建一个立方体函数:
cube = functools.partial(pow, exp=3)
cube(5) # returns 125, equivalent to pow(5, 3)
缓存属性
这是一个装饰器,允许你缓存一些可能耗时较长的方法的返回值。例如,数据库调用通常是耗时较长的操作,因此,如果你预计它们的值不会经常变化,那么缓存它们是很有必要的。
@functools.cached_property
def my_expensive_method():
...
return result
该方法首次调用时会执行完整计算,并将返回值缓存起来。下次调用同一方法时,可以直接从缓存中获取结果。
请注意,该cached_property装饰器仅适用于 Python 3.8 及更高版本。对于较低版本的 Python,可以使用单独的软件包。
总订单
当您定义自定义类时,特别是当定义一个用于存储某种数值数据的容器时,定义比较方法__eq__(等于)、__gt__(大于)、__ge__(大于等于)、__lt__(小于)和(__le__小于等于)会很有帮助,这样可以更轻松地比较这些类的对象。
class Distance:
km: int # Kilometers
m: int # Meters
def __init__(self, km, m):
self.km = km
self.m = m
def __eq__(self, other):
return self.km == other.km and self.m == other.m
def __gt__(self, other):
if self.km > other.km:
return True
elif self.km < other.km:
return False
elif self.m > other.m:
return True
else:
return False
然而,定义所有这些方法可能很繁琐,并且会导致大量的样板代码,尤其是有 5 个方法的情况下。幸运的是,您不必这样做!给定 `a` 和 `b` 、` c` 或__eq__`d` 中的任意一个的逻辑,所有其他比较方法都可以推导出来。__gt____ge____lt____le__
例如,在上面的例子中,该__le__方法可以推导如下:
def __le__(self, other):
return not self > other
这就是@total_ordering装饰器的作用。当它应用于至少定义了一个__eq__比较方法(包括另一个比较方法)的类时,它会自动派生出所有其他比较方法。
@functools.total_ordering
class Distance:
...
邓德/魔法方法
双下划线方法是一种特殊方法,它允许你在自定义类中使用 Python 的内置运算符和关键字,例如+`& `、 *`&` len、`&` 等。这对于使代码更简洁、更易读非常有用。你可以在我之前的文章中了解更多关于双下划线方法的信息,点击此处阅读。
图片来自Pixabay的Paul Brennan。
文章来源:https://dev.to/bikramjeetsingh/6-nifty-python-language-features-you-might-not-know-about-6mi