Использование блестящей идеи DSM:
from __future__ import print_function
import pandas as pd
categories = set(['Economics', 'English', 'Histo', 'Literature'])
def correct_categories(cols):
return [cat for col in cols for cat in categories if col.startswith(cat)]
df = pd.read_csv('data.csv', sep=r'\s+', index_col='Id')
#print(df)
print(df.groupby(correct_categories(df.columns),axis=1).sum())
Выход:
Economics English Histo Literature
Id
56 1 1 2 1
11 1 0 0 1
6 1 1 0 0
43 2 0 1 1
14 1 1 1 0
Вот еще одна версия, которая заботится о «Histo / History» проблематичной ..
from __future__ import print_function
import pandas as pd
#categories = set(['Economics', 'English', 'Histo', 'Literature'])
#
# mapping: common starting pattern: desired name
#
categories = {
'Histo': 'History',
'Economics': 'Economics',
'English': 'English',
'Literature': 'Literature'
}
def correct_categories(cols):
return [categories[cat] for col in cols for cat in categories.keys() if col.startswith(cat)]
df = pd.read_csv('data.csv', sep=r'\s+', index_col='Id')
#print(df.columns, len(df.columns))
#print(correct_categories(df.columns), len(correct_categories(df.columns)))
#print(df.groupby(pd.Index(correct_categories(df.columns)),axis=1).sum())
rslt = df.groupby(correct_categories(df.columns),axis=1).sum()
print(rslt)
print('History\n', rslt['History'])
Выход:
Economics English History Literature
Id
56 1 1 2 1
11 1 0 0 1
6 1 1 0 0
43 2 0 1 1
14 1 1 1 0
History
Id
56 2
11 0
6 0
43 1
14 1
Name: History, dtype: int64
PS Вы можете захотеть добавить отсутствующие категории в categories
map / dictionary
В прошлом году на comp.lang.python было очень хорошее обсуждение этого вопроса. Он очень хорошо отвечает на ваш вопрос.
Импорт довольно прост. Просто помните следующее:
'import' и 'from xxx import yyy' являются исполняемыми операциями. Они выполняются, когда запущенная программа достигает этой строки.
Если модуль отсутствует в sys.modules, тогда импорт создает новую запись модуля в sys.modules и затем выполняет код в модуле. Он не возвращает управление вызывающему модулю до тех пор, пока выполнение не завершится.
Если модуль существует в sys.modules, тогда импорт просто возвращает этот модуль, завершил ли он выполнение. Вот почему циклический импорт может возвращать модули, которые кажутся частично пустыми.
Наконец, исполняемый скрипт работает в модуле с именем __main__, при импорте скрипта под собственным именем будет создан новый модуль, не связанный с __main __.
Возьмите эту партию вместе, и вы не должны получать никаких сюрпризов при импорте модулей.
Хорошо, я думаю, что у меня довольно крутое решение. Допустим, у вас есть файл a
и файл b
. У вас есть def
или class
в файле b
, который вы хотите использовать в модуле a
, но у вас есть что-то еще, либо def
, class
, либо переменная из файла a
что вам нужно в вашем определении или классе в файле b
. Что вы можете сделать, это внизу файла a
после вызова функции или класса в файле a
, которая необходима в файле b
, но прежде чем вызывать функцию или класс из файла b
, который вам нужен для файла a
, скажем import b
Затем, и вот ключевая часть во всех определениях или классах файла b
, которым нужны def
или class
из файла a
(назовем это CLASS
), вы говорите from a import CLASS
Это работает, потому что вы можете импортировать файл b
без Python, выполняющего какие-либо из операторов импорта в файле b
, и, таким образом, вы избегаете любых циклических импорта.
Например:
class A(object):
def __init__(self, name):
self.name = name
CLASS = A("me")
import b
go = B(6)
go.dostuff
class B(object):
def __init__(self, number):
self.number = number
def dostuff(self):
from a import CLASS
print "Hello " + CLASS.name + ", " + str(number) + " is an interesting number."
Voila.
from a import CLASS
фактически не пропускает выполнение всего кода в a.py. Я думаю, это то, что на самом деле происходит здесь:
– Matthias Fripp
4 June 2015 в 07:17
from a import CLASS
фактически не пропускает выполнение всего кода в a.py. Это то, что на самом деле происходит: (1) Весь код в a.py запускается как специальный модуль «__ main __». (2) В import b
код верхнего уровня в b.py запускается (определяя класс B), а затем управляет возвратом в «__ main __». (3) "__ main __" в конечном итоге передает управление go.dostuff()
. (4), когда dostuff () приходит к import a
, он запускает весь код в a.py снова i>, на этот раз в качестве модуля «a»; затем он импортирует объект CLASS из нового модуля «a». На самом деле, это будет работать одинаково хорошо, если вы использовали import a
в любом месте b.py.
– Matthias Fripp
4 June 2015 в 07:28
Циркулярный импорт может сбивать с толку, потому что импорт делает две вещи:
Первый выполняется только один раз, а последний - в каждом заявлении импорта. Циркулярный импорт создает ситуацию, когда импортирующий модуль использует импортированный с частично выполненным кодом. В результате он не увидит объекты, созданные после оператора импорта. Ниже образец кода демонстрирует это.
Циркулярный импорт не является наивысшим злом, которого можно избежать любой ценой. В некоторых рамках, таких как Flask, они вполне естественны, и настройка вашего кода для их устранения не делает код лучше.
main.py
print 'import b'
import b
print 'a in globals() {}'.format('a' in globals())
print 'import a'
import a
print 'a in globals() {}'.format('a' in globals())
if __name__ == '__main__':
print 'imports done'
print 'b has y {}, a is b.a {}'.format(hasattr(b, 'y'), a is b.a)
b.by
print "b in, __name__ = {}".format(__name__)
x = 3
print 'b imports a'
import a
y = 5
print "b out"
a.py
print 'a in, __name__ = {}'.format(__name__)
print 'a imports b'
import b
print 'b has x {}'.format(hasattr(b, 'x'))
print 'b has y {}'.format(hasattr(b, 'y'))
print "a out"
python main.py вывод с комментариями
import b
b in, __name__ = b # b code execution started
b imports a
a in, __name__ = a # a code execution started
a imports b # b code execution is already in progress
b has x True
b has y False # b defines y after a import,
a out
b out
a in globals() False # import only adds a to main global symbol table
import a
a in globals() True
imports done
b has y True, a is b.a True # all b objects are available
У меня есть пример, который поразил меня!
foo.py
import bar
class gX(object):
g = 10
bar.py
from foo import gX
o = gX()
main.py
import foo
import bar
print "all done"
В командной строке: $ python main.py
Traceback (most recent call last):
File "m.py", line 1, in <module>
import foo
File "/home/xolve/foo.py", line 1, in <module>
import bar
File "/home/xolve/bar.py", line 1, in <module>
from foo import gX
ImportError: cannot import name gX
import bar
в foo.py
до конца
– warvariuc
5 August 2013 в 10:52
bar
и foo
оба должны использовать gX
, «самое чистое» решение - поместить gX
в другой модуль и импортировать этот модуль foo
и bar
. (самый чистый в том смысле, что нет скрытых семантических зависимостей.)
– Tim Wilder
17 December 2013 в 22:32
bar
не может даже найти gX
в foo. круговой импорт сам по себе хорош, но это просто, что gX
не определяется при импорте.
– Martian2049
18 January 2017 в 04:31
Модуль a.py:
import b
print("This is from module a")
Модуль b.py
import a
print("This is from module b")
Запустит «Модуль a»:
>>>
'This is from module a'
'This is from module b'
'This is from module a'
>>>
Он выводит эти 3 строки, пока он должен выводить бесконечность из-за циклического импорта. Что происходит строка за строкой при запуске «Module a»:
import b
. поэтому он посетит модуль b import a
. поэтому он будет посещать модуль a import b
, но отмечает, что эта строка больше не будет выполняться больше , поскольку каждый файл на python выполняет импортировать строку только один раз, не имеет значения, где и когда он выполняется. поэтому он перейдет к следующей строке и напечатает "This is from module a"
. "This is from module b"
"This is from module a"
, и программа будет закончена. Я полностью согласен с ответом pythoneer здесь. Но я наткнулся на какой-то код, который был испорчен циркулярным импортом и вызвал проблемы при попытке добавить модульные тесты. Поэтому, чтобы быстро исправить это, не изменяя все, вы можете решить проблему, выполнив динамический импорт.
# Hack to import something without circular import issue
def load_module(name):
"""Load module using imp.find_module"""
names = name.split(".")
path = None
for name in names:
f, path, info = imp.find_module(name, path)
path = [path]
return imp.load_module(name, f, path[0], info)
constants = load_module("app.constants")
Опять же, это не постоянное исправление, но может помочь кому-то, кто хочет исправить ошибку импорта без меняя слишком много кода.
Приветствия!
Как и другие ответы, этот шаблон допустим в python:
def dostuff(self):
from foo import bar
...
. Это позволит избежать выполнения оператора импорта, когда файл импортируется другими модулями. Только если существует логическая циклическая зависимость, это не сработает.
Большинство Circular Imports на самом деле не являются логическим циклическим импортом, а скорее повышают ошибки ImportError
из-за того, как import()
оценивает операторы верхнего уровня весь файл при вызове.
Эти ImportErrors
можно почти всегда избегать, если вы действительно хотите, чтобы ваш импорт был сверху:
Рассмотрим этот циклический импорт:
# profiles/serializers.py
from images.serializers import SimplifiedImageSerializer
class SimplifiedProfileSerializer(serializers.Serializer):
name = serializers.CharField()
class ProfileSerializer(SimplifiedProfileSerializer):
recent_images = SimplifiedImageSerializer(many=True)
# images/serializers.py
from profiles.serializers import SimplifiedProfileSerializer
class SimplifiedImageSerializer(serializers.Serializer):
title = serializers.CharField()
class ImageSerializer(SimplifiedImageSerializer):
profile = SimplifiedProfileSerializer()
От David Beazleys отличный разговор Модули и пакеты: Live и Let Die! - PyCon 2015 , 1:54:00
, вот способ обработки круговых импортов в python:
try:
from images.serializers import SimplifiedImageSerializer
except ImportError:
import sys
SimplifiedImageSerializer = sys.modules[__package__ + '.SimplifiedImageSerializer']
Это попытка импортировать SimplifiedImageSerializer
, и если ImportError
поднят, потому что он уже импортируется, он вытащит его из importcache.
PS: Вы должны прочитать весь этот пост в голосе Дэвида Бэйсли.
Циклический импорт завершается, но вам нужно быть осторожным, чтобы не использовать циклически импортированные модули во время инициализации модуля.
Рассмотрим следующие файлы:
a.py:
print "a in"
import sys
print "b imported: %s" % ("b" in sys.modules, )
import b
print "a out"
b.py:
print "b in"
import a
print "b out"
x = 3
Если вы выполните a.py, вы получите следующее:
$ python a.py
a in
b imported: False
b in
a in
b imported: True
a out
b out
a out
Во втором импортировании b.py (во втором a in
) интерпретатор Python не импортирует b
еще раз, потому что он уже существует в модуле dict.
Если вы попытаетесь получить доступ к b.x
из a
во время инициализации модуля вы получите AttributeError
.
Добавьте следующую строку к a.py
:
print b.x
Затем на выходе:
$ python a.py
a in
b imported: False
b in
a in
b imported: True
a out
Traceback (most recent call last):
File "a.py", line 4, in <module>
import b
File "/home/shlomme/tmp/x/b.py", line 2, in <module>
import a
File "/home/shlomme/tmp/x/a.py", line 7, in <module>
print b.x
AttributeError: 'module' object has no attribute 'x'
Это связано с тем, что модули выполняются при импорте и в момент доступа к b.x
линия x = 3
еще не выполнена, что произойдет только после b out
.
Если вы выполняете import foo
внутри bar
и import bar
внутри foo
, он будет работать нормально. К тому моменту, когда что-то действительно выполняется, оба модуля будут полностью загружены и будут иметь ссылки друг на друга.
Проблема заключается в том, что вместо этого вы делаете from foo import abc
и from bar import xyz
. Поскольку теперь каждый модуль требует, чтобы другой модуль уже был импортирован (чтобы имя, которое мы импортируем, существует), прежде чем оно может быть импортировано.
from foo import *
и from bar import *
также будут работать нормально.
– Akavall
12 May 2014 в 17:54
from x import y
и все еще получает круговую ошибку импорта
– Greg Ennis
30 June 2014 в 15:09
import
. Таким образом, это не будет ошибкой, но вы не можете получить все переменные, которые вы ожидаете.
– augurar
24 December 2016 в 02:41
from foo import *
и from bar import *
, все, что выполняется в foo
, находится в фазе инициализации bar
, а фактические функции в bar
еще не определены ...
– Martian2049
18 January 2017 в 03:37