Аргументы по умолчанию получают оценку во время компиляции функции в объект функции. При использовании этой функции, несколько раз с помощью этой функции, они являются и остаются одним и тем же объектом.
Когда они изменяются, когда они мутируются (например, добавляя к нему элемент), они остаются мутированными по последовательным вызовам.
Они остаются мутированными, потому что каждый раз они являются одним и тем же объектом .
Поскольку список связан с функцией, когда объект функции компилируется и инстанцируется, это:
def foo(mutable_default_argument=[]): # make a list the default argument
"""function that uses a list"""
почти точно эквивалентно этому:
_a_list = [] # create a list in the globals
def foo(mutable_default_argument=_a_list): # make it the default argument
"""function that uses a list"""
del _a_list # remove globals name binding
Вот демонстрация - вы можете проверить, что они являются одним и тем же объектом каждый раз, когда они ссылаются на
example.py
print('1. Global scope being evaluated')
def create_list():
'''noisily create a list for usage as a kwarg'''
l = []
print('3. list being created and returned, id: ' + str(id(l)))
return l
print('2. example_function about to be compiled to an object')
def example_function(default_kwarg1=create_list()):
print('appending "a" in default default_kwarg1')
default_kwarg1.append("a")
print('list with id: ' + str(id(default_kwarg1)) +
' - is now: ' + repr(default_kwarg1))
print('4. example_function compiled: ' + repr(example_function))
if __name__ == '__main__':
print('5. calling example_function twice!:')
example_function()
example_function()
и работает это с python example.py
:
1. Global scope being evaluated
2. example_function about to be compiled to an object
3. list being created and returned, id: 140502758808032
4. example_function compiled:
5. calling example_function twice!:
appending "a" in default default_kwarg1
list with id: 140502758808032 - is now: ['a']
appending "a" in default default_kwarg1
list with id: 140502758808032 - is now: ['a', 'a']
Этот порядок выполнения часто путает новых пользователей Python. Если вы понимаете модель исполнения Python, это становится вполне ожидаемым.
Но поэтому обычная инструкция для новых пользователей заключается в том, чтобы вместо этого создать свои аргументы по умолчанию:
def example_function_2(default_kwarg=None):
if default_kwarg is None:
default_kwarg = []
Это использует None singleton как объект-дозор, чтобы сообщить функции, есть ли у нас аргумент, отличный от значения по умолчанию. Если мы не получаем никакого аргумента, то мы действительно хотим использовать новый пустой список []
в качестве значения по умолчанию.
Как говорится в разделе в разделе управления потоком :
Если вы не хотите, чтобы по умолчанию были разделены между последующими вызовами, вы можете написать такую функцию, как это:
def f(a, L=None): if L is None: L = [] L.append(a) return L
Для семейства Debian / Ubuntu мы обычно рекомендуем
$ sudo apt-get install r-base-dev
, поскольку он извлекает все пакеты, которые обычно необходимы для компиляции. И этот подход все время тестируется, так как на это полагаются автоматизированные разработчики пакетов (а также дополнительные встроенные сборки для каждого пакета). Пакет gfortran
также указан здесь; возможно, у вас есть неработающая ссылка из предыдущей установки, поэтому я также попробую dpkg --purge gfortran; apt-get install gfortran
. Тем не менее, десятки пакетов R (и самого R) используют Fortran, поэтому здесь не должно быть никакой магии.
Для будущих утерянных душ также помогает проверять версии всех компиляторов (за https://askubuntu.com/questions/276892/cannot-find-lgfortran ). В моем случае gcc и gfortran были равны 4.8.4, но g ++ - 4.6.
Похоже, что другие предложения уже исправили вашу проблему, но ваш вопрос также применился ко мне, но в моем случае решение было другим. Моя проблема заключалась в том, что мои версии gcc и g ++ отличались от моей версии gfortran. Я использовал следующее, чтобы переключать их так, чтобы они были одинаковыми.
g++ --version
gcc --version
gfortran --version
sudo update-alternatives --config g++
sudo update-alternatives --config gcc
sudo update-alternatives --config gfortran
В моем случае у меня была только одна версия gfortran, поэтому я просто изменил версии g ++ и gcc в соответствии с версией gfortran.
gcc
на 5.4.1 заставляла его работать для gfortran
6.2.0.
– Evpok
14 February 2017 в 09:59
Я использую Centos, и я не могу получить r-base-dev. Я также установил gfortran, и его версия совпадает с версией gcc и g ++; он все еще не работает. Однако я решил эту проблему, создав ~/.R/Makevars
, используя
cd ~
mkdir .R
touch Makevars
. Я нашел каталог, в котором я установил gfortran (видимо, проблема в том, что R не может его найти) с помощью
which gfortran
Он сказал, что я установил gfortran в usr/bin/gfortran
. Затем я добавил флаги в .R/Makevars
, чтобы сказать R:
F77 = /usr/bin/gfortran
FC = $F77
FLIBS = -L/usr/bin/gfortran
Вы можете редактировать файл Makevars таким образом:
vi .R/Makevars
Теперь вы ввели vi
, которая может редактировать текстовые файлы. Введите i
для редактирования; вы увидите INSERT
в нижней части окна терминала. Затем вы можете ввести то, что я поставил выше. Чтобы сохранить изменения и выйти из vi
, нажмите клавишу esc и введите :wq
.
Я не совсем уверен, правильно ли вставил линию FLIBS, так как для MacOS это совсем другое. В MacOS есть каталог под gfortran, для которого есть ссылки на библиотеки, но, по-видимому, gfortran
не является каталогом в Linux. По крайней мере, это сработало для меня, а также решило проблему /usr/bin/ld: cannot find -lquadmath
, поэтому я установил R-пакеты, требующие gfortran плавно.
У меня была такая же проблема при попытке установить пакет CRAN VGAM на Ubuntu 12.10 64bit. У меня уже установлен r-base-dev, но второй ответ Эндрю Редда на ответ Дирка Эддельбуэттеля сработал для меня.
В частности, я получал две ошибки:
/usr/bin/ld: cannot find -lgfortran
/usr/bin/ld: cannot find -lquadmath
которые были исправлены строками:
sudo ln -s /usr/lib/x86_64-linux-gnu/libgfortran.so.3 /usr/lib/libgfortran.so
sudo ln -s /usr/lib/x86_64-linux-gnu/libquadmath.so.0 /usr/lib/libquadmath.so
Обратите внимание, что только первая строка будет необходимо позаботиться о проблеме с исходного поста. Вторая строка исправлена моей дополнительной ошибкой с lquadmath.
Такая же проблема при установке R-пакета minqa на ubuntu 12.04, R3.1.0., x86 32bits (на самом деле это была часть установки пакета каретки).
Решено
sudo ln -s /usr/lib/i386-linux-gnu/libgfortran.so.3 /usr/lib/libgfortran.so
r-base-dev переустановка не работает, и я не пытался переустановить gfortran из-за всех зависимостей.
В зависимости от системы / версии,
ls -l /usr/lib/libgfortran.so
проверяет, что ссылка существует / права.
sudo ln -s /usr/lib/x86_64-linux-gnu/libgfortran.so.3 /usr/lib/libgfortran.so
(это то, что сработало для меня в Linux Mint 18.3)
– seaotternerd
12 July 2018 в 00:24
Если вы используете gcc44, вам понадобятся:
yum install gcc44-gfortran
gcc-*
,g++-*
иgfortran-*
и / или их эквивалентами библиотек? «Что-то смешное» иногда является простой ошибкой оператора. На моем полеlibgfortran.so.3
живет в/usr/lib/x86_64-linux-gnu/
и идет из пакетаlibgfortran3
. – Dirk Eddelbuettel 10 June 2011 в 15:11ldconfig -p | grep libgfortran
, и он должен показать, что libgfortran.so.3 найден из каталога/usr/lib/x86_64-linux-gnus
. Или еще моя (довольно новая) коробка на работе отключена :) – Dirk Eddelbuettel 10 June 2011 в 17:38