В чем преимущество использования функции лямбда: None?
Я увидел следующий код:
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, который является алгоритмом квантовой химии, и автор использовал эту лямбда-функцию для получения двухэлектронных интегралов.
И тогда решил против него, видимо.
Ответы
Ответ 1
Это выглядит как трюк для создания простого объекта для хранения значений в одной строке. Большинство встроенных объектов не позволяют вам устанавливать на них произвольные атрибуты:
>>> 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'
Если вы создадите свой собственный класс, вы можете добавить все необходимые атрибуты. В этом случае вы можете создать класс, метод __init__
которого присваивает атрибуты, но это может и не стоить шаблона. Поэтому вы можете просто создать пустой класс:
>>> class Data(object): pass
>>> d = Data()
>>> d.x = 0
>>> d.x
0
По-видимому, программист либо не знает об этом, либо не хочет эту дополнительную строку, где объявлен класс, и придумал свой собственный метод обхода для хранения данных. Оказывается, функции, несмотря на встроенный тип, позволяют добавлять к ним атрибуты:
>>> def foo(): pass
>>> foo.x = 0
>>> foo.x
0
Как выше, так и лямбда позволяют создать такой контейнер в одном выражении. Я на самом деле думаю, что это отличная идея.
Ответ 2
В чем преимущество использования функции лямбда: None?
Что здесь происходит
eris = lambda:None
eris.jkcpp = ...
заключается в том, что автор создает пространство имен, используя объект функции для __dict__
.
Пространство имен - это домен, где юридические имена Python сопоставляются с объектами, а когда вы делаете что-то вроде выше, преимущество пространства имен заключается в том, что имена не в локальной и глобальной области, где они могут быть перезаписаны или перезаписаны там, где одинаковые имена предназначены для указания на разные объекты.
Нет ничего плохого в этом, но если другие пытаются прочитать код, чтобы понять, что происходит с этой передаваемой функцией, тогда они, вероятно, думают:
Будет ли это когда-нибудь называться? Почему мы проходим вокруг вызываемого? Вызываемый, который возвращает None, не очень полезен, это должен быть какой-то хак.
Чтобы избежать путаницы, используйте объект, который семантически понимается как пространство имен.
Пространство имен
У нас есть объект SimpleNamespace в стандартной библиотеке Python 3:
from types import SimpleNamespace
eris = SimpleNamespace()
eris.jkcpp = ...
В Python 2 было бы обычно делать что-то вроде:
class NS(object):
pass
eris = NS()
eris.jkcpp = ...
Если вам нужно простое пространство имен, это опции ok.
Downsides
Однако мне еще предстоит использовать эти формы пространств имен. Я либо обнаружил, что namedtuple будет достаточным, когда я хочу, чтобы семантика была перенесена с данными (особенно полезно, когда их было много), или я использую изменяемый объект с более чем просто pass
в нем.
Как они есть, они действительно не отличаются, программно, от простого словаря. Значения, на которые указывают имена, хранятся в объекте __dict__
. Вы можете также обходить экземпляр dict
. Пунктирный поиск добавляет немного накладных расходов (проверено, чтобы увидеть, имеет ли тип объекта дескрипторы данных, прежде чем искать в словаре объектов).
Вывод:
У экземпляра пространства имен могут быть некоторые недостатки, но может быть более читаемым. Показатели удобочитаемости. Если вы считаете, что ваша программа нуждается в простом пространстве имен, используйте ее.
Но не используйте функцию do-nothing для пространства имен. Это вводит в заблуждение и не имеет смысла никому.