Он работает:
fn back(&mut self) -> &mut Link {
let mut anchor = &mut self.root;
while anchor.is_some(){
anchor = &mut {anchor}.as_mut().unwrap().next;
}
anchor
}
Да, python может расчехлять лямбда-функции ... но только если у вас есть что-то, что использует copy_reg
, чтобы зарегистрировать, как распиливать лямбда-функции - пакет dill
загружает copy_reg
, который вам нужен, в реестр рассола для вас, когда вы import dill
.
Python 2.7.8 (default, Jul 13 2014, 02:29:54)
[GCC 4.2.1 Compatible Apple Clang 4.1 ((tags/Apple/clang-421.11.66))] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>>
>>> import dill # the code below will fail without this line
>>>
>>> import pickle
>>> s = pickle.dumps(lambda x, y: x+y)
>>> f = pickle.loads(s)
>>> assert f(3,4) == 7
>>> f
<function <lambda> at 0x10aebdaa0>
получите укроп здесь: https://github.com/uqfoundation
Нет, Python не может расчехлять лямбда-функции:
>>> import cPickle as pickle
>>> s = pickle.dumps(lambda x,y: x+y)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/copy_reg.py", line 70, in _reduce_ex
raise TypeError, "can't pickle %s objects" % base.__name__
TypeError: can't pickle function objects
Не уверен, что вы сделали, что это удалось ...
Python может мариновать лямбда. Мы рассмотрим Python 2 и 3 отдельно, поскольку реализация pickle различна в разных версиях Python.
pickle
использует реестр рассолов, который ничего, кроме отображения из type
в функцию, используемую для сериализации (травления) объектов этого типа. Вы можете увидеть реестр pickle как:
>> pickle.Pickler.dispatch
{bool: <function pickle.save_bool>,
instance: <function pickle.save_inst>,
classobj: <function pickle.save_global>,
float: <function pickle.save_float>,
function: <function pickle.save_global>,
int: <function pickle.save_int>,
list: <function pickle.save_list>,
long: <function pickle.save_long>,
dict: <function pickle.save_dict>,
builtin_function_or_method: <function pickle.save_global>,
NoneType: <function pickle.save_none>,
str: <function pickle.save_string>,
tuple: <function pickle.save_tuple>,
type: <function pickle.save_global>,
unicode: <function pickle.save_unicode>}
Чтобы разложить пользовательские типы, Python предоставляет модуль copy_reg
для регистрации наших функций. Вы можете прочитать об этом здесь . По умолчанию модуль copy_reg
поддерживает травление следующих дополнительных типов:
>> import copy_reg
>> copy_reg.dispatch_table
{code: <function ipykernel.codeutil.reduce_code>,
complex: <function copy_reg.pickle_complex>,
_sre.SRE_Pattern: <function re._pickle>,
posix.statvfs_result: <function os._pickle_statvfs_result>,
posix.stat_result: <function os._pickle_stat_result>}
Теперь тип функций lambda
- types.FunctionType
. Однако встроенная функция для этого типа function: <function pickle.save_global>
не может сериализовать лямбда-функции. Поэтому все сторонние библиотеки, такие как dill
, cloudpickle
и т. Д., Переопределяют встроенный метод для сериализации лямбда-функций с некоторой дополнительной логикой. Давайте импортируем dill
и посмотрим, что он делает.
>> import dill
>> pickle.Pickler.dispatch
{_pyio.BufferedReader: <function dill.dill.save_file>,
_pyio.TextIOWrapper: <function dill.dill.save_file>,
_pyio.BufferedWriter: <function dill.dill.save_file>,
_pyio.BufferedRandom: <function dill.dill.save_file>,
functools.partial: <function dill.dill.save_functor>,
operator.attrgetter: <function dill.dill.save_attrgetter>,
operator.itemgetter: <function dill.dill.save_itemgetter>,
cStringIO.StringI: <function dill.dill.save_stringi>,
cStringIO.StringO: <function dill.dill.save_stringo>,
bool: <function pickle.save_bool>,
cell: <function dill.dill.save_cell>,
instancemethod: <function dill.dill.save_instancemethod0>,
instance: <function pickle.save_inst>,
classobj: <function dill.dill.save_classobj>,
code: <function dill.dill.save_code>,
property: <function dill.dill.save_property>,
method-wrapper: <function dill.dill.save_instancemethod>,
dictproxy: <function dill.dill.save_dictproxy>,
wrapper_descriptor: <function dill.dill.save_wrapper_descriptor>,
getset_descriptor: <function dill.dill.save_wrapper_descriptor>,
member_descriptor: <function dill.dill.save_wrapper_descriptor>,
method_descriptor: <function dill.dill.save_wrapper_descriptor>,
file: <function dill.dill.save_file>,
float: <function pickle.save_float>,
staticmethod: <function dill.dill.save_classmethod>,
classmethod: <function dill.dill.save_classmethod>,
function: <function dill.dill.save_function>,
int: <function pickle.save_int>,
list: <function pickle.save_list>,
long: <function pickle.save_long>,
dict: <function dill.dill.save_module_dict>,
builtin_function_or_method: <function dill.dill.save_builtin_method>,
module: <function dill.dill.save_module>,
NotImplementedType: <function dill.dill.save_singleton>,
NoneType: <function pickle.save_none>,
xrange: <function dill.dill.save_singleton>,
slice: <function dill.dill.save_slice>,
ellipsis: <function dill.dill.save_singleton>,
str: <function pickle.save_string>,
tuple: <function pickle.save_tuple>,
super: <function dill.dill.save_functor>,
type: <function dill.dill.save_type>,
weakcallableproxy: <function dill.dill.save_weakproxy>,
weakproxy: <function dill.dill.save_weakproxy>,
weakref: <function dill.dill.save_weakref>,
unicode: <function pickle.save_unicode>,
thread.lock: <function dill.dill.save_lock>}
Теперь давайте попробуем раскрыть лямбда-функцию.
>> pickle.loads(pickle.dumps(lambda x:x))
<function __main__.<lambda>>
РАБОТАЕТ !!
В Python 2 у нас есть две версии pickle
-
import pickle # pure Python version
pickle.__file__ # <install directory>/python-2.7/lib64/python2.7/pickle.py
import cPickle # C extension
cPickle.__file__ # <install directory>/python-2.7/lib64/python2.7/lib-dynload/cPickle.so
. Теперь давайте попробуем раскрыть лямбда с реализацией C cPickle
.
>> import cPickle
>> cPickle.loads(cPickle.dumps(lambda x:x))
TypeError: can't pickle function objects
Что пошло не так? Давайте посмотрим таблицу отправки cPickle
.
>> cPickle.Pickler.dispatch_table
AttributeError: 'builtin_function_or_method' object has no attribute 'dispatch_table'
Реализация pickle
и cPickle
отличается. Importing
Укроп делает только версию Python pickle
. Недостатком использования pickle
вместо cPickle
является то, что он может достигать 1000 раз медленнее, чем cPickle.
In Python 3, нет модуля с именем cPickle
. У нас есть pickle
, который также не поддерживает травление функций lambda
по умолчанию. Посмотрим, что это таблица отправки:
>> import pickle
>> pickle.Pickler.dispatch_table
<member 'dispatch_table' of '_pickle.Pickler' objects>
Подождите. Я попытался найти dispatch_table pickle
не _pickle
. _pickle
является альтернативной и более быстрой реализацией C рассола. Но мы еще не импортировали его! Эта реализация C импортируется автоматически, если она доступна, в конце чистого модуля Python pickle
.
# Use the faster _pickle if possible
try:
from _pickle import (
PickleError,
PicklingError,
UnpicklingError,
Pickler,
Unpickler,
dump,
dumps,
load,
loads
)
except ImportError:
Pickler, Unpickler = _Pickler, _Unpickler
dump, dumps, load, loads = _dump, _dumps, _load, _loads
Нам все еще остается вопрос о травлении лямбда в Python 3. Ответ вы НЕ МОЖЕТЕ с помощью нативного pickle
или _pickle
. Вам нужно будет импортировать dill
или cloudpickle и использовать это вместо встроенного модуля рассола.
>> import dill
>> dill.loads(dill.dumps(lambda x:x))
<function __main__.<lambda>>
Надеюсь, это устранит все сомнения.