使用 lambda:None 函数作为命名空间的优势?

Advantage of using a lambda:None function as a namespace?

我看到了以下内容code

eris = lambda:None
eris.jkcpp = np.einsum('iipq->ipq', eriaa[:ncore[0],:ncore[0],:,:])
eris.jc_PP = np.einsum('iipq->pq', eriab[:ncore[0],:ncore[0],:,:])

我们可以为 lambda:None 定义的函数定义任意属性吗?

我在看一个casscf代码,这是量子化学中的一个算法,作者用这个lambda函数得到了2电子积分。 然后 decided against it,显然。

这看起来像是创建一个简单对象以在一行中保存值的技巧。大多数内置对象不允许您在其上设置任意属性:

>>> object().x = 0
Traceback (most recent call last):
  File "<input>", line 1, in <module>
AttributeError: 'object' object has no attribute 'x'
>>> ''.x = 0
Traceback (most recent call last):
  File "<input>", line 1, in <module>
AttributeError: 'str' object has no attribute 'x'
>>> [].x = 0
Traceback (most recent call last):
  File "<input>", line 1, in <module>
AttributeError: 'list' object has no attribute 'x'

如果您自己制作 class,那么您可以添加任何您想要的属性。在这种情况下,您可以制作一个 class 其 __init__ 方法分配属性,但这可能不值得样板。所以你可以做一个空的 class:

>>> class Data(object): pass
>>> d = Data()
>>> d.x = 0
>>> d.x
0

显然,程序员要么没有意识到这一点,要么不想要声明 class 的额外行,并提出了他们自己的存储数据的解决方法。事实证明,函数尽管是内置类型 do 允许您向它们添加属性:

>>> def foo(): pass
>>> foo.x = 0
>>> foo.x
0

以上内容和 lambda 都可以让您在一条语句中创建这样的容器。我实际上认为这是个好主意。

What is the advantage of using a lambda:None function?

这是怎么回事

eris = lambda:None
eris.jkcpp = ...

是作者正在使用函数对象的命名空间(__dict__)。

非常不常见。我会避免它。

名称空间 是合法 Python 名称映射到对象的域,当您执行上述操作时,命名空间 是名称不在本地和全局范围内,在这些范围内它们可以 覆盖或被覆盖,其中相同的名称旨在指向不同的对象。

从表面上看这没什么问题,但如果其他人试图阅读代码以了解传递的这个函数发生了什么,那么他们可能会想:

Will the lambda ever be called? Why are we passing around a callable? A callable that returns None isn't very useful, this must be some kind of hack.

为避免混淆,请使用将在语义上被理解为命名空间的对象。

命名空间

我们在 Python 3 的标准库中有一个 SimpleNamespace 对象:

from types import SimpleNamespace

eris = SimpleNamespace()
eris.jkcpp = ...

在 Python 2 中,通常会执行以下操作:

class NS(object): 
    pass

eris = NS()
eris.jkcpp = ...

如果您需要一个简单的命名空间,这些都是不错的选择。

缺点

但是,我还没有看到这些命名空间形式的大量使用。我要么发现 namedtuple 就足够了,我希望语义与数据一起携带(当它们很多时特别有用),要么我使用一个可变对象,其中不仅仅是 pass

实际上,它们在编程上与简单字典没有什么不同。名称指向的值存储在对象的 __dict__ 中。您也可以传递一个 dict 实例。点查找也增加了一点开销(在查看对象的字典之前检查对象的类型是否有数据描述符)。

结论:

命名空间实例可能有一些缺点,但它可能更具可读性。可读性很重要。如果您认为您的程序需要一个简单的命名空间,请使用它。

但是不要对命名空间使用什么都不做的函数。它具有误导性,对任何人都没有意义。