Неожиданное поведение метода append ().Почему при добавлении словаря в список предыдущие элементы списка перезаписываются? - PullRequest
0 голосов
/ 30 января 2019

Следующий код проверяет наличие названия компании (из tickerList ) или ее фрагмента в тексте новости (из newsList ).В случае, когда компания обнаружена в новостях , печать выдает ожидаемый тикер компании, но после добавления этой новости в список происходит что-то бессмысленное :(При добавлении словаря ( news ) в список ( tickersNews ) перезаписываются ли предыдущие элементы списка. Почему?

Следует отметить, что приновости добавляются в виде словаря, преобразованного в строку, все работает как надо

import re

tickersList = [('ATI', 'Allegheny rporated', 'Allegheny Technologies Incorporated'), ('ATIS', 'Attis', 'Attis Industries, Inc.'), ('ATKR', 'Atkore International Group', 'Atkore International Group Inc.'), ('ATMP', 'Barclays + Select M', 'Barclays ETN+ Select MLP'), ('ATNM', 'Actinium', 'Actinium Pharmaceuticals, Inc.'), ('ATNX', 'Athenex', 'Athenex, Inc.'), ('ATOS', 'Atossa Genetics', 'Atossa Genetics Inc.'), ('ATRA', 'Atara Biotherapeutics', 'Atara Biotherapeutics, Inc.'), ('ATRC', 'AtriCure', 'AtriCure, Inc.'), ('ATRO', 'Astronics', 'Astronics Corporation'), ('ATRS', 'Antares Pharma', 'Antares Pharma, Inc.'), ('ATSG', 'Air Transport Services Group', 'Air Transport Services Group, Inc.'),  ('CJ', 'C&J Energy', 'C&J Energy Services, Inc.'), ('CJJD', 'China Jo-Jo Drugstores', 'China Jo-Jo Drugstores, Inc.'), ('CLAR', 'Clarus', 'Clarus Corporation'), ('CLD', 'Cloud Peak Energy', 'Cloud Peak Energy Inc.'), ('CLDC', 'China Lending', 'China Lending Corporation'), ('CLDR', 'Cloudera', 'Cloudera, Inc.')]

newsList = [
    {'title':'Atara Biotherapeutics Announces Planned Chief Executive Officer Transition'},
    {'title':'Chongqing Jingdong Pharmaceutical and Athenex Announce a Strategic Partnership and Licensing Agreement to Develop and Commercialize KX2-391 in China'}
           ]

tickersNews = []

for news in newsList:
    # pass through the list of companies looking for their mention in the news
    for ticker, company, company_full in tickersList:
        # clear the full name of the company from brackets, spaces, articles,
        # points and commas and save fragments of the full name to the list
        companyFullFragments = company_full.replace(',', '')\
            .replace('.', '').replace('The ', ' ')\
            .replace('(', ' ').replace(')', ' ')\
            .replace('  ', ' ').strip().split()
        # looking for a company in the news every time cutting off
        # the last fragment from the full company name
        for i in range(len(companyFullFragments), 0, -1):
            companyFullFragmentsString = ' '.join(companyFullFragments[:i]).strip()
            lookFor_company = r'(^|\s){0}(\s|$)'.format(companyFullFragmentsString)
            results_company = re.findall(lookFor_company, news['title'])
            # if the title of the news contains the name of the company,
            # then we add the ticker, the found fragment and the full name
            # of the company to the news, print the news and add it to the list
            if results_company:
                news['ticker'] = ticker#, companyFullFragmentsString, company_full
                print(news['ticker'], 'found')
                #tickersNews.append(str(news))
                #-----------------------------Here is the problem!(?)
                tickersNews.append(news)
                # move on to the next company
                break

print(20*'-', 'appended:')
for news in tickersNews:
    print(news['ticker'])

Вывод (список слов):

ATRA found
ATNX found
CJJD found
CLDC found
-------------------- appended:
ATRA
CLDC
CLDC
CLDC

Вывод (список строк):

ATRA found
ATNX found
CJJD found
CLDC found
-------------------- appended as a strings:
["{'title': 'Atara Biotherapeutics Announces Planned Chief Executive Officer Transition', 'ticker': 'ATRA'}", "{'title': 'Chongqing Jingdong Pharmaceutical and Athenex Announce a Strategic Partnership and Licensing Agreement to Develop and Commercialize KX2-391 in China', 'ticker': 'ATNX'}", "{'title': 'Chongqing Jingdong Pharmaceutical and Athenex Announce a Strategic Partnership and Licensing Agreement to Develop and Commercialize KX2-391 in China', 'ticker': 'CJJD'}", "{'title': 'Chongqing Jingdong Pharmaceutical and Athenex Announce a Strategic Partnership and Licensing Agreement to Develop and Commercialize KX2-391 in China', 'ticker': 'CLDC'}"]

1 Ответ

0 голосов
/ 30 января 2019

Проблема возникает из 2 строк: news['ticker'] = ticker и tickersNews.append(news), которые расположены внутри цикла for.Гораздо проще версия вашей проблемы:

a = 10
a = 20
a = 30
print(a, a, a)

Вывод будет 30 30 30.Я думаю, это очевидно.

Для решения проблемы вы можете использовать несколько подходов.

Первая возможность (самый простой).Заменить tickersNews.append(news) на tickersNews.append(news.copy()).

Вторая возможность (предпочтительно).Не используйте tickersNews.Для каждого news создайте пустой список news['ticker_list'] = list().Для каждого ticker добавьте его к news['ticker_list']:

import re

tickersList = [('ATI', 'Allegheny rporated', 'Allegheny Technologies Incorporated'), ('ATIS', 'Attis', 'Attis Industries, Inc.'), ('ATKR', 'Atkore International Group', 'Atkore International Group Inc.'), ('ATMP', 'Barclays + Select M', 'Barclays ETN+ Select MLP'), ('ATNM', 'Actinium', 'Actinium Pharmaceuticals, Inc.'), ('ATNX', 'Athenex', 'Athenex, Inc.'), ('ATOS', 'Atossa Genetics', 'Atossa Genetics Inc.'), ('ATRA', 'Atara Biotherapeutics', 'Atara Biotherapeutics, Inc.'), ('ATRC', 'AtriCure', 'AtriCure, Inc.'), ('ATRO', 'Astronics', 'Astronics Corporation'), ('ATRS', 'Antares Pharma', 'Antares Pharma, Inc.'), ('ATSG', 'Air Transport Services Group', 'Air Transport Services Group, Inc.'),  ('CJ', 'C&J Energy', 'C&J Energy Services, Inc.'), ('CJJD', 'China Jo-Jo Drugstores', 'China Jo-Jo Drugstores, Inc.'), ('CLAR', 'Clarus', 'Clarus Corporation'), ('CLD', 'Cloud Peak Energy', 'Cloud Peak Energy Inc.'), ('CLDC', 'China Lending', 'China Lending Corporation'), ('CLDR', 'Cloudera', 'Cloudera, Inc.')]

newsList = [
    {'title':'Atara Biotherapeutics Announces Planned Chief Executive Officer Transition'},
    {'title':'Chongqing Jingdong Pharmaceutical and Athenex Announce a Strategic Partnership and Licensing Agreement to Develop and Commercialize KX2-391 in China'}
           ]

for news in newsList:
    news['ticker_list'] = list()
    for ticker, company, company_full in tickersList:
        companyFullFragments = company_full.replace(',', '')\
            .replace('.', '').replace('The ', ' ')\
            .replace('(', ' ').replace(')', ' ')\
            .replace('  ', ' ').strip().split()
        for i in range(len(companyFullFragments), 0, -1):
            companyFullFragmentsString = ' '.join(companyFullFragments[:i]).strip()
            lookFor_company = r'(^|\s){0}(\s|$)'.format(companyFullFragmentsString)
            results_company = re.findall(lookFor_company, news['title'])
            if results_company:
                news['ticker_list'].append(ticker)
                # print(ticker, 'found')
                break

print('tickers for news:')

for news in newsList:
    print(news['ticker_list'])

Вывод будет:

tickers for news:
['ATRA']
['ATNX', 'CJJD', 'CLDC']
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...