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

Cho*_*Sun 19 python lambda namespaces names

我看到了以下代码:

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],:,:])
Run Code Online (Sandbox Code Playgroud)

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

我正在阅读一个casscf代码,这是量子化学中的算法,作者使用这个lambda函数来得到2电子积分.显然,他决定反对它.

Ale*_*all 16

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

>>> 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'
Run Code Online (Sandbox Code Playgroud)

如果您创建自己的类,则可以添加所需的任何属性.在这种情况下,您可以创建一个__init__方法分配属性的类,但这可能不值得使用样板.所以你可以创建一个空类:

>>> class Data(object): pass
>>> d = Data()
>>> d.x = 0
>>> d.x
0
Run Code Online (Sandbox Code Playgroud)

显然,程序员要么不知道这个,要么不想要声明类的额外行,并且已经提出了自己的存储数据的解决方法.原来的功能,尽管是一个内置式让你属性添加到它们:

>>> def foo(): pass
>>> foo.x = 0
>>> foo.x
0
Run Code Online (Sandbox Code Playgroud)

上面和lambda都可以在一个语句中创建这样的容器.我其实认为这是一个很好的主意.


Aar*_*all 11

使用lambda:None函数有什么好处?

这里发生了什么

eris = lambda:None
eris.jkcpp = ...
Run Code Online (Sandbox Code Playgroud)

是作者正在使用函数对象为其创建命名空间__dict__.

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

从表面上看,这并没有什么不妥,但如果其他人试图阅读代码来了解正在传递的这个功能正在发生什么,那么他们可能会想:

会不会被称为?为什么我们绕过一个可赎回的人?返回None的callable不是很有用,这必定是某种hack.

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

命名空间

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

from types import SimpleNamespace
eris = SimpleNamespace()
eris.jkcpp = ...
Run Code Online (Sandbox Code Playgroud)

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

class NS(object): 
    pass

eris = NS()
eris.jkcpp = ...
Run Code Online (Sandbox Code Playgroud)

如果您需要一个简单的命名空间,这些都是正常的选项

缺点

但是,我还没有使用这些形式的命名空间.我要么发现一个namedtuple就足以满足我想要在数据中携带语义的地方(特别是在有很多数据的时候很有用),或者我使用的是一个多变量的可变对象pass.

就像它们一样,它们在编程上与简单的字典完全没有区别.名称指向的值存储在对象中__dict__.你也可以绕过一个dict实例.虚线查找会增加一些开销(在查看对象的字典之前检查对象的类型是否具有数据描述符).

结论:

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

但是不要对命名空间使用do-nothing函数.这是误导,对任何人都没有意义.