探秘 :你不了解的 Python 隐藏特性

写在前面

Python 隐藏特性探秘会介绍一些不被大众所熟知的代码特性。在这篇文章中我介绍一些编码的技巧和Python的特性,希望能够在你的日常编码中帮助到你。

让我们开始吧——

1、函数对象

Python 中的所有东西都是某个类的实例化对象,当然也包括函数,但是这一事实可能让你感觉有悖直觉,别着急,让我们看一个例子。

def add_subject(name, subject, subjects=[]):
 subjects.append(subject)
 return {'name': name, 'subjects': subjects}

add_subject('person1''subject1')
add_subject('person2''subject2')
add_subject('person3''subject3')

输出 -
{'name''person1''subjects': ['subject1']}
{'name''person2''subjects': ['subject1''subject2']}
{'name''person3''subjects': ['subject1''subject2''subject3']}

是不是和你预想的结果不太一样,你是否觉得 person2 和 person3 的 subjects 多了一些东西。别着急,继续往下看。

Python中的可变性可能是最被误解和忽视的概念之一。

函数的默认参数在定义函数时就进行了初始化。因此,一旦定义了一个函数,函数对象就会在其__defaults__属性中存储默认参数。

下面我们通过代码来进行验证

def my_functions(a=1, b=2, c=3):
pass

print(my_functions.defaults)

输出 
(123)

那么,如果在函数定义中指定了一个可变的默认参数呢,您就不知不觉中改变了该函数所有调用的参数。

下面的代码显示了这一点。Python 没有在每次函数调用时创建一个新列表,而是向同一副本追加元素。

def add_subject(name, subject, subjects=[]):
 subjects.append(subject)
 return {'name': name, 'subjects': subjects}

print(add_subject.defaults)

add_subject('person1''subject1')
print(add_subject.defaults)

add_subject('person2''subject2')
print(add_subject.defaults)

add_subject('person3''subject3'))
print(add_subject.defaults)

输出 -
([],)
(['subject1'],)
(['subject1''subject2'],)
(['subject1''subject2''subject3'],)

如何避免这个问题呢?

不要在函数定义中指定可变的默认参数(例如列表),而是用 None 来替换它们。如果在函数调用期间函数没有收到相应的值,请在函数内部创建可变对象。

def add_subject(name, subject, subjects=None):
 if subjects is None:
  subjects = []

 subjects.append(subject)
 return {'name': name, 'subjects': subjects}

print(add_subject.defaults)
print(add_subject('person1''subject1'))
print(add_subject('person2''subject2'))

print(add_subject('person3''subject3'))

输出 -
(None,)
{'name''person1''subjects': ['subject1']}
{'name''person2''subjects': ['subject2']}
{'name''person3''subjects': ['subject3']}

如上所示,如果函数在被调用时没有收到任何值,我们会创建一个新的列表。这可以避免意外地改变同一个对象。

2、让类对象像函数一样可调用

如果你想让你一个类可以像函数一样可调用,可以通过定义__call__方法来实现。该方法将会使你的类像函数一样可调用。

class Multiplier:
 def init(self, a, b, c):
  self.a = a
  self.b = b
  self.c = c

 def __call__(self, x):
     return (self.a * x**2) + (self.b * x**2) + (self.c * x**2)

func = Multiplier(246)
print(func(2))    # 48

print(func(4))    # 192
print(callable(func))    # True

以上代码中,我们直接像使用函数一样使用 Multiplier 类。那么这样做会带来什么好处呢?

  • 我们实现可以以灵活、直观的方式使用的对象
  • 熟悉的函数调用语法有时可以使代码更具可读性
  • 它允许您在需要可调用对象的上下文中使用类对象。例如将类用作装饰器。

3、字符串方法

这里有一些 Python 字符串方法的新信息和很酷的地方。在 Python 中,startswith 和 endswith 字符串方法通常用于在字符串开头和结尾匹配子字符串。

places = ["India""London""Poland""Netherlands"]
for place in places:
 if place.startswith('Lo'or place.startswith('Po'):
  print(place)

然而,你知道可以将多个子字符串作为元组传递给这些方法吗?

places = ["India""London""Poland""Netherlands"]
for place in places:
if place.startswith(('Lo''Po')):
print(place)

这大大简化了你的条件代码,同时保持相同的功能。

4、使用 Frozenset

Python 中的字典要求其键是不可变的。由于集合是可变的,所以不能将集合用作键。

set_ex = {123}
dict_obj = {set_ex: "This is a Set"}

# Error - TypeError: unhashable type: 'set'

如果要使用集合,可以将其声明为不可变集合。

set_ex = frozenset({123})
dict_obj = {set_ex: "This is a Set"}

print(dict_obj[set_ex])

输出 - This is a Set

它是一个不可变的集合,意味着它的元素在创建后不能更改。因此,它们可以安全地用作字典的键。

5、Pickle 文件

Pickle 文件广泛用于数据对象持久化,即将数据对象存储到硬盘上。但是人们经常只将单个对象转储到文件中。为了存储多个对象,会创建多个文件。

你可能不知道我们可以在单个 Pickle 文件中存储很多对象。此外,在加载时,不需要加载所有对象。只需确保转储对象在同一上下文管理器(使用with)中。

import pickle

a, b, c = 123

with open("data.pkl""wb"as f:
 pickle.dump(a, f)
 pickle.dump(b, f)
 pickle.dump(c, f)

这段代码会在当前目录创建文件data.pkl 并存储a、b、c的值。

import pickle

with open("data.pkl""rb"as f:
 a = pickle.load(f)
 b = pickle.load(f)

print(f"{a = } {b = }")

结果:

a = 1 b = 2

当然,还有一种解决方案是将对象组合在一起作为元组。但在重新加载时,会加载整个元组。在某些情况下,这可能不是所需的。

总结

以上内容介绍了Python的一些隐藏特性。其中包括函数对象的特性,如默认参数的初始化和避免可变默认参数带来的问题;还有让类对象像函数一样可调用的方法;以及字符串方法的一些使用技巧。这些特性可以提高代码的灵活性和可读性,持续关注 harvey 的网络日志公众号,让我们在编程过程中更加高效和方便。


原文始发于微信公众号(harvey的网络日志):探秘 :你不了解的 Python 隐藏特性

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之家整理,本文链接:https://www.bmabk.com/index.php/post/203521.html

(0)
小半的头像小半

相关推荐

发表回复

登录后才能评论
极客之家——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!