Вы вызываете конечную точку API, который генерирует фиктивную информацию один человек за раз - это занимает значительное количество времени.
Остальная часть кода почти не занимает времени.
Измените конечную точку, которую вы используете (на том, который вы используете, сбор больших имен не производится) или используйте встроенные фиктивные данные, предоставляемые модулями python.
Вы можетеясно видеть, что «подсчет и обработка имен» здесь не является узким местом:
from faker import Faker # python module that generates dummy data
from collections import Counter
import datetime
fake = Faker()
c = Counter()
# get 10.000 names, split them and add 1st part
t = datetime.datetime.now()
c.update( (fake.name().split()[0] for _ in range(10000)) )
print(c.most_common(10))
print((datetime.datetime.now()-t).total_seconds())
Вывод для 10000 имен:
[('Michael', 222), ('David', 160), ('James', 140), ('Jennifer', 134),
('Christopher', 125), ('Robert', 124), ('John', 120), ('William', 111),
('Matthew', 111), ('Lisa', 101)]
in
1.886564 # seconds
Общие рекомендации по оптимизации кода: сначала измерьте , а затем оптимизируйте узких мест .
Если вам нужен просмотр кода , вы можете проверить https://codereview.stackexchange.com/help/on-topic и посмотреть, соответствует ли ваш код требованиям для сайта обмена стеками просмотра кода.Как и в случае с SO, вначале нужно приложить некоторые усилия, то есть проанализировать , где тратит большую часть вашего времени.
Редактировать - с измерениями производительности:
import requests
import json
from collections import defaultdict
import datetime
# defaultdict is (in this case) better then Counter because you add 1 name at a time
# Counter is superiour if you update whole iterables of names at a time
d = defaultdict(int)
def insertToDict(n):
d[n] += 1
url = 'https://api.namefake.com'
api_times = []
process_times = []
requests.packages.urllib3.disable_warnings()
for x in range(10):
# for each name, break it to first and last name
try:
t = datetime.datetime.now() # start time for API call
# no need for authentication
responseObj = requests.get(url, verify=False)
jsonData = json.loads(responseObj.text)
# end time for API call
api_times.append( (datetime.datetime.now()-t).total_seconds() )
x = jsonData['name']
t = datetime.datetime.now() # start time for name processing
newName = ""
for name_char in x:
# make a string from the decoded python object concatenation
newName = newName + str(name_char)
# split by whitespaces
y = newName.split()
# parse the first name (check first if header exists (Prof. , Dr. , Mr. , Miss)
if "." in y[0] or "Miss" in y[0]:
insertToDict(y[2])
else:
insertToDict(y[0])
insertToDict(y[1])
# end time for name processing
process_times.append( (datetime.datetime.now()-t).total_seconds() )
except:
continue
newA = sorted(d, key=d.get, reverse=True)[:10]
print(newA)
print(sum(api_times))
print(sum( process_times ))
Вывод:
['Ruecker', 'Clare', 'Darryl', 'Edgardo', 'Konopelski', 'Nettie', 'Price',
'Isobel', 'Bashirian', 'Ben']
6.533625
0.000206
Вы можете сделать синтаксический анализ лучше .. Я этого не сделал, потому что этоне имеет значения.
Лучше использовать timeit для тестирования производительности (он вызывает код несколько раз и в среднем, сглаживать артефакты из-за кэширования / задержки / ...) (thx @ bruno desthuilliers ) - в этом случае я не использовал timeit, потому что я не хочу вызывать API 100000 раз для усреднения результатов