Heim  >  Artikel  >  Backend-Entwicklung  >  Detaillierte grafische Erläuterung des Python-Set-Typs (Listen-Tupel-Dikt-Set-Generator)

Detaillierte grafische Erläuterung des Python-Set-Typs (Listen-Tupel-Dikt-Set-Generator)

高洛峰
高洛峰Original
2017-03-20 10:24:001931Durchsuche

Zu den in

Python integrierten Sammlungstypen gehören list, tuple, set und dict.

Liste: sieht aus wie Array, ist aber leistungsfähiger als Array und unterstützt Funktionen wie Indizierung, Slicing, Suche und Addition.

Tupel-Tupel: Die Funktion ähnelt der Liste, aber nach der Generierung sind die Länge und die Elemente nicht variabel (die Elemente der Elemente sind immer noch variabel), was eine leichtere und sicherere Liste zu sein scheint.

Dictionary-Dikt: Eine Hash-Tabelle mit Schlüssel-Wert-Paar-Struktur, die dieselben Eigenschaften wie ein Schlüssel hat, ist ungeordnet und nicht wiederholbar, und das Hinzufügen, Löschen und Ändern ist praktisch Und schnell.

Set: Ein ungeordneter und sich nicht wiederholender Satz, der nur Schlüssel und keine Werte enthält. Ich hoffe, dass Python nicht so ist Wert, daher werden viele Hinweise weggelassen.

Generator:

wird als Generator oder Listenverständnis bezeichnet, bei dem es sich um einen speziellen Datentyp handelt Es handelt sich eigentlich nicht um eine Datenstruktur, sondern enthält nur den Algorithmus und den temporären Zustand und hat die Funktion der Iteration.

Sehen Sie sich zunächst die Speichernutzung an und verwenden Sie Generatoren, um Mengen, Diktate, Generatoren, Tupel und Listen mit 100.000 Elementen zu generieren. Der von Diktat, Menge, Liste und Tupel verbrauchte Speicher nimmt nacheinander ab, und auch die Größe der generierten Objekte bleibt gleich. Da der Generator keine Datentabelle generiert, muss er keinen Speicher verbrauchen:

import sys
from memory_profiler import profile

@profile
def create_data(data_size):
    data_generator = (x for x in xrange(data_size))
    data_set = {x for x in xrange(data_size)}
    data_dict = {x:None for x in xrange(data_size)}
    data_tuple = tuple(x for x in xrange(data_size))
    data_list = [x for x in xrange(data_size)]
    return data_set, data_dict, data_generator, data_tuple, data_list

data_size = 100000
for data in create_data(data_size):
    print data.__class__, sys.getsizeof(data)

Line #    Mem usage    Increment   Line Contents
================================================
    14.6 MiB      0.0 MiB   @profile
                            def create_data(data_size):
    14.7 MiB      0.0 MiB       data_generator = (x for x in xrange(data_size))
    21.4 MiB      6.7 MiB       data_set = {x for x in xrange(data_size)}
    29.8 MiB      8.5 MiB       data_dict = {x:None for x in xrange(data_size)}
    33.4 MiB      3.6 MiB       data_tuple = tuple(x for x in xrange(data_size))
    38.2 MiB      4.8 MiB       data_list = [x for x in xrange(data_size)]
    38.2 MiB      0.0 MiB       return data_set, data_dict, data_generator, data_tuple, data_list
 
<type &#39;set&#39;> 4194528
<type &#39;dict&#39;> 6291728
<type &#39;generator&#39;> 72
<type &#39;tuple&#39;> 800048
<type &#39;list&#39;> 824464
Sehen Sie sich noch einmal die Suchleistung an. dict und set sind konstante Suchzeiten (O(1)) und list und Tupel sind lineare Suchzeiten. Verwenden Sie den Generator, um ein Objekt mit bestimmten Größenelementen zu generieren, und verwenden Sie für die Suche zufällig generierte Zahlen:

import time
import sys
import random
from memory_profiler import profile

def create_data(data_size):
    data_set = {x for x in xrange(data_size)}
    data_dict = {x:None for x in xrange(data_size)}
    data_tuple = tuple(x for x in xrange(data_size))
    data_list = [x for x in xrange(data_size)]
    return data_set, data_dict, data_tuple, data_list

def cost_time(func):
    def cost(*args, **kwargs):
        start = time.time()
        r = func(*args, **kwargs)
        cost = time.time() - start
        print &#39;find in %s cost time %s&#39; % (r, cost)
        return r, cost  #返回数据的类型和方法执行消耗的时间
    return cost

@cost_time
def test_find(test_data, data):
    for d in test_data:
        if d in data:
            pass
    return data.__class__.__name__

data_size = 100
test_size = 10000000
test_data = [random.randint(0, data_size) for x in xrange(test_size)]
#print test_data
for data in create_data(data_size):
    test_find(test_data, data)

输出:
----------------------------------------------
find in <type &#39;set&#39;> cost time 0.47200012207
find in <type &#39;dict&#39;> cost time 0.429999828339
find in <type &#39;tuple&#39;> cost time 5.36500000954
find in <type &#39;list&#39;> cost time 5.53399991989
Ein Satz von 100 Elementen, Suche Bei 1000 W ist der Unterschied deutlich zu erkennen. Diese Zufallszahlen sind jedoch alle in der Sammlung zu finden. Ändern Sie die Zufallszahlenmethode so, dass die Hälfte der generierten Zahlen gefunden werden kann und die andere Hälfte nicht gefunden werden kann. Aus den gedruckten Informationen ist ersichtlich, dass Liste und Tupel noch schlechter abschneiden, wenn die Hälfte der schlechtesten Suchbeispiele vorhanden ist.

def randint(index, data_size):
    return random.randint(0, data_size) if (x % 2) == 0 else random.randint(data_size, data_size * 2)

test_data = [randint(x, data_size) for x in xrange(test_size)]

输出:
----------------------------------------------
find in <type &#39;set&#39;> cost time 0.450000047684
find in <type &#39;dict&#39;> cost time 0.397000074387
find in <type &#39;tuple&#39;> cost time 7.83299994469
find in <type &#39;list&#39;> cost time 8.27800011635
Die Anzahl der Elemente erhöht sich von 10 auf 500. Statistiken über die Zeit, die jeweils für die Suche benötigt wird, werden verwendet, um die Zeitverbrauchskurve anzupassen. Die Ergebnisse beweisen dies dict und set spielen keine Rolle bei der Anzahl der Elemente. Da die Elemente wachsen, zeigen dict und tuple eine lineare Wachstumszeit:

import matplotlib.pyplot as plot
from numpy import *

data_size = array([x for x in xrange(10, 500, 10)])
test_size = 100000
cost_result = {}
for size in data_size:
    test_data = [randint(x, size) for x in xrange(test_size)]
    for data in create_data(size):
        name, cost = test_find(test_data, data) #装饰器函数返回函数的执行时间
        cost_result.setdefault(name, []).append(cost)

plot.figure(figsize=(10, 6))
xline = data_size
for data_type, result in cost_result.items():
    yline = array(result)
    plot.plot(xline, yline, label=data_type)

plot.ylabel(&#39;Time spend&#39;)
plot.xlabel(&#39;Find times&#39;)

plot.grid()

plot.legend()
plot.show()

Python集合类型(list tuple dict set generator)图文详解

Der Unterschied in der Iterationszeit ist sehr gering und Diktat und Satz erfordern etwas mehr Zeit:

@cost_time
def test_iter(data):
    for d in data:
        pass
    return data.__class__ .__name__

data_size = array([x for x in xrange(1, 500000, 1000)])
cost_result = {}
for size in data_size:
    for data in create_data(size):
        name, cost = test_iter(data)
        cost_result.setdefault(name, []).append(cost)

#拟合曲线图
plot.figure(figsize=(10, 6))
xline = data_size
for data_type, result in cost_result.items():
    yline = array(result)
    plot.plot(xline, yline, label=data_type)  

plot.ylabel(&#39;Time spend&#39;)
plot.xlabel(&#39;Iter times&#39;)

plot.grid()

plot.legend()
plot.show()

Python集合类型(list tuple dict set generator)图文详解

Der Zeitverbrauch für das Löschen von Elementen ist unten dargestellt. 1000 Elemente werden zufällig gelöscht. Der Tupeltyp kann keine Elemente löschen, daher wird kein Vergleich durchgeführt:


Python集合类型(list tuple dict set generator)图文详解

Die Hälfte der Elemente zufällig löschen, und der Graph wächst in exponentieller Zeit (O(n2)):

Python集合类型(list tuple dict set generator)图文详解

Der Zeitverbrauch für das Hinzufügen von Elementen wird unten angezeigt. Die Statistik der Additionszeit der Anzahl von Elemente in Schritten von 10000 sind alle lineare Wachstumszeiten. Es gibt keinen Unterschied, daher wird kein Vergleich durchgeführt:

@cost_time
def test_dict_add(test_data, data):
    for d in test_data:
        data[d] = None
    return data.__class__ .__name__

@cost_time
def test_set_add(test_data, data):
    for d in test_data:
        data.add(d)
    return data.__class__ .__name__

@cost_time
def test_list_add(test_data, data):
    for d in test_data:
        data.append(d)
    return data.__class__ .__name__

#初始化数据,指定每种类型对应它添加元素的方法
def init_data():
    test_data = {
        &#39;list&#39;: (list(), test_list_add),
        &#39;set&#39;: (set(), test_set_add),
        &#39;dict&#39;: (dict(), test_dict_add)
    }
    return test_data

#每次检测10000增量大小的数据的添加时间
data_size = array([x for x in xrange(10000, 1000000, 10000)])
cost_result = {}
for size in data_size:
    test_data = [x for x in xrange(size)]
    for data_type, (data, add) in init_data().items():
        name, cost = add(test_data, data) #返回方法的执行时间
        cost_result.setdefault(data_type, []).append(cost)

plot.figure(figsize=(10, 6))
xline = data_size
for data_type, result in cost_result.items():
    yline = array(result)
    plot.plot(xline, yline, label=data_type)

plot.ylabel(&#39;Time spend&#39;)
plot.xlabel(&#39;Add times&#39;)

plot.grid()

plot.legend()
plot.show()

Python集合类型(list tuple dict set generator)图文详解

Das obige ist der detaillierte Inhalt vonDetaillierte grafische Erläuterung des Python-Set-Typs (Listen-Tupel-Dikt-Set-Generator). Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn