Kaip nustatyti objekto dydį „Python“?

C, mes galime rasti int , char ir kt. Noriu sužinoti, kaip gauti objektų dydį, pvz., Eilutę, sveikąjį skaičių ir kt. pythone.

Susijęs klausimas: Kiek baitų viename elemente yra Python sąraše (tuple)?

Naudoju XML failą, kuriame yra dydžio laukai, apibrėžiantys vertės dydį. Turiu analizuoti šį XML ir atlikti savo kodavimą. Kai noriu pakeisti tam tikro lauko vertę, patikrinsiu šios vertės dydžio lauką. Čia noriu palyginti, ar nauja vertė, kurią turiu įvesti, yra tokio paties dydžio kaip XML. Turiu patikrinti naujos vertės dydį. Stygos atveju galiu pasakyti jo ilgį. Tačiau int, float ir tt Aš supainioti.

470
16 янв. user46646 nustatytas 16 sausis 2009-01-16 08:07 '09, 08:07 2009-01-16 08:07
@ 11 atsakymų

Tiesiog naudokite sys.getsizeof funkciją, nustatytą sys modulyje.

sys.getsizeof(object[, default]) :

Grąžina objekto dydį baitais. Objektas gali būti bet kokio tipo objektas. Visi įterptieji objektai grąžins teisingus rezultatus, tačiau tai neturėtų būti teisinga trečiųjų šalių plėtiniams, nes šis įgyvendinimas yra konkretus.

default argumentas leidžia nustatyti vertę, kuri bus grąžinta, jei objekto tipas nesuteiks galimybės gauti dydį ir skambinti „ TypeError .

getsizeof skambina getsizeof objektais ir prideda papildomą šiukšlių surinkėjo pridėtinę getsizeof jei objektą tvarko šiukšlių surinkėjas.

Python 3.0 naudojimo pavyzdys:

 >>> import sys >>> x = 2 >>> sys.getsizeof(x) 24 >>> sys.getsizeof(sys.getsizeof) 32 >>> sys.getsizeof('this') 38 >>> sys.getsizeof('this also') 48 

Jei esate python <2.6 ir neturite sys.getsizeof , galite naudoti šį išplėstinį modulį . Niekada nenaudojote.

500
16 янв. Atsakymas duotas nosklo 16 jan. 2009-01-16 13:42 '09 13:42 2009-01-16 13:42

Kaip nustatyti objekto dydį „Python“?

Atsakymas „Tiesiog naudokite sys.getsizeof“ nėra išsamus atsakymas.

Šis atsakymas veikia tiesiogiai įterptųjų objektų atžvilgiu, tačiau neatsižvelgia į tai, ką šie objektai gali turėti, visų pirma, kokie tipai, pvz., Rinkiniai, sąrašai, dicts ir rinkiniai. Juose gali būti vienas kito pavyzdžiai, taip pat numeriai, stygos ir kiti objektai.

Išsamesnis atsakymas

Naudojant 64 bitų „Python 3.6“ iš „Anaconda“ platinimo, nuo sys.getsizeof nustatiau minimalų šių objektų dydį ir pastebėjau, kad rinkiniai ir diktuojamos erdvės yra tokios tuščios, kad jos vėl neatsiranda, kol nebus nustatytas nustatytas kiekis (kuris gali skirtis priklausomai nuo nustatyto dydžio) kalbos):

Python 3:

 Bytes type empty + scaling notes 24 int NA 28 long NA 37 str + 1 byte per additional character 52 unicode + 4 bytes per additional character 56 tuple + 8 bytes per additional item 72 list + 32 for first, 8 for each additional 232 set sixth item increases to 744; 22nd, 2280; 86th, 8424 280 dict sixth item increases to 1048; 22nd, 3352; 86th, 12568 * 120 func def does not include default args and other attrs 64 class inst has a __dict__ attr, same scaling as dict above 16 __slots__ class with slots has no dict, seems to store in mutable tuple-like structure. 904 class def has a proxy __dict__ structure for class attrs 104 old class makes sense, less stuff, has real dict though. 

Atkreipkite dėmesį, kad žodynai ( bet ne kolekcijos ) yra kompaktiškesni Python 3.6.

Manau, kad 8 baitai už papildomą elemento nuorodą daro daug prasmės 64 bitų įrenginyje. Šie 8 baitai rodo vietą atmintyje, kurioje yra elementas. 4 baitai yra fiksuotas unikodo plotis Python 2, jei aš teisingai prisimenu, bet Python 3 str tampa unicode plotis, lygus maksimaliam simbolių plotiui.

(Ir daugiau informacijos apie laiko tarpsnius žr. Šiame atsakyme )

Rekursyvus lankytojas už išsamesnę funkciją

Norėdami apimti daugumą šių tipų, parašiau šią rekursinę funkciją, kad galėtume įvertinti daugumos „Python“ objektų dydį, įskaitant daugumą įmontuotų elementų, tipų kolekcijų modulyje ir pasirinktinius tipus (su plyšiu ir kitais):

 import sys from numbers import Number from collections import Set, Mapping, deque try: # Python 2 zero_depth_bases = (basestring, Number, xrange, bytearray) iteritems = 'iteritems' except NameError: # Python 3 zero_depth_bases = (str, bytes, Number, range, bytearray) iteritems = 'items' def getsize(obj_0): """Recursively iterate to sum size of object  members.""" _seen_ids = set() def inner(obj): obj_id = id(obj) if obj_id in _seen_ids: return 0 _seen_ids.add(obj_id) size = sys.getsizeof(obj) if isinstance(obj, zero_depth_bases): pass # bypass remaining control flow and return elif isinstance(obj, (tuple, list, Set, deque)): size += sum(inner(i) for i in obj) elif isinstance(obj, Mapping) or hasattr(obj, iteritems): size += sum(inner(k) + inner(v) for k, v in getattr(obj, iteritems)()) # Check for custom object instances - may subclass above too if hasattr(obj, '__dict__'): size += inner(vars(obj)) if hasattr(obj, '__slots__'): # can have __slots__ with __dict__ size += sum(inner(getattr(obj, s)) for s in obj.__slots__ if hasattr(obj, s)) return size return inner(obj_0) 

Ir išbandžiau jį gana atsitiktinai (turiu jį pašalinti):

 >>> getsize(['a', tuple('bcd'), Foo()]) 344 >>> getsize(Foo()) 16 >>> getsize(tuple('bcd')) 194 >>> getsize(['a', tuple('bcd'), Foo(), {'foo': 'bar', 'baz': 'bar'}]) 752 >>> getsize({'foo': 'bar', 'baz': 'bar'}) 400 >>> getsize({}) 280 >>> getsize({'foo':'bar'}) 360 >>> getsize('foo') 40 >>> class Bar(): ... def baz(): ... pass >>> getsize(Bar()) 352 >>> getsize(Bar().__dict__) 280 >>> sys.getsizeof(Bar()) 72 >>> getsize(Bar.__dict__) 872 >>> sys.getsizeof(Bar.__dict__) 280 

Tai rūšies pertraukų klasės apibrėžimai ir funkcijų apibrėžimai, nes nesutraukiu po visų jų atributų, bet kadangi jie turi būti tik vieną kartą atmintyje procesui, jų dydis tikrai nesvarbu.

221
19 мая '15 в 7:26 2015-05-19 07:26 atsakymą pateikė Aarono salė gegužės 19 d., 15 val

Dėl numpy getsizeof masyvų getsizeof - man tai visuomet grąžina 40 dėl kokios nors priežasties:

 from pylab import * from sys import getsizeof A = rand(10) B = rand(10000) 

Tada („ipython“):

 In [64]: getsizeof(A) Out[64]: 40 In [65]: getsizeof(B) Out[65]: 40 

Laimei

 In [66]: A.nbytes Out[66]: 80 In [67]: B.nbytes Out[67]: 80000 
76
30 июля '10 в 19:33 2010-07-30 19:33 Atsakymą pateikė Mike Dewar , liepos 30 d., 10 val., 19:33, 2010-07-30 19:33

Tai gali padaryti asize paketo asizeof modulis.

Naudokite šiuos veiksmus:

 from pympler import asizeof asizeof.asizeof(my_object) 

Skirtingai nuo sys.getsizeof , jis veikia jūsų sukurtiems objektams . Jis net veikia su numpy.

 >>> asizeof.asizeof(tuple('bcd')) 200 >>> asizeof.asizeof({'foo': 'bar', 'baz': 'bar'}) 400 >>> asizeof.asizeof({}) 280 >>> asizeof.asizeof({'foo':'bar'}) 360 >>> asizeof.asizeof('foo') 40 >>> asizeof.asizeof(Bar()) 352 >>> asizeof.asizeof(Bar().__dict__) 280 >>> A = rand(10) >>> B = rand(10000) >>> asizeof.asizeof(A) 176 >>> asizeof.asizeof(B) 80096 

Kaip minėta ,

Objektų, pvz., Klasių, funkcijų, metodų, modulių ir tt, dydžio (baito) kodas gali būti įjungtas nustatant code=True parinktis.

Ir jei jums reikia kitų gyvų duomenų, Pympler

modulis „ muppy naudojamas „Python“ programos stebėjimui internetu ir „ Class Tracker modulis suteikia galimybę analizuoti pasirinktų „Python“ objektų veikimo laiką.

55
10 нояб. atsakymas, kurį pateikė serv-inc 10 nov. 2015-11-10 17:01 '15, 17:01, 2015-11-10 17:01

Tai gali būti sudėtingesnė, nei atrodo, priklausomai nuo to, kaip norite suskaičiuoti dalykus. Pvz., Jei turite int sąrašą, ar norite, kad sąraše būtų nuorodų į ints? (t. y. tik sąrašas, o ne tai, kas joje yra), arba norite įtraukti faktinius duomenis, į kuriuos jis atkreipia dėmesį, šiuo atveju jums reikia susidoroti su dvigubomis nuorodomis ir kaip išvengti dvigubo skaičiavimo, kai du objektai turi nuorodas ant to paties objekto.

Galite pažiūrėti į vieną iš python atminties profilių, pvz., Pysizer , kad pamatytumėte, ar jie atitinka jūsų poreikius.

12
16 янв. Atsakymą Brian pateikė sausio 16 d. 2009-01-16 16:00 '09 16:00 val. 2009-01-16 16:00

Štai greitas scenarijus, kurį parašiau remiantis ankstesniais atsakymais į visų kintamųjų dydžių sąrašą

 for i in dir(): print (i, sys.getsizeof(eval(i)) ) 
9
04 марта '13 в 20:34 2013-03-04 20:34 atsakymą pateikė alexey kovo 14 d. 13 d. 20:34 2013-03-04 20:34

Daug kartų susidūriau su šia problema, parašiau nedidelę funkciją (įkvėpta atsakymo @ aaron salės) ir bandymus, kurie darys tai, ko tikiuosi iš sys.getsizeof:

https://github.com/bosswissam/pysize

Jei jus domina priešistorė, čia

Redaguoti: toliau pateikiamo kodo pridėjimas patogumui. Norėdami peržiūrėti naujausią kodą, patikrinkite „github“ nuorodą.

  import sys def get_size(obj, seen=None): """Recursively finds size of objects""" size = sys.getsizeof(obj) if seen is None: seen = set() obj_id = id(obj) if obj_id in seen: return 0 # Important mark as seen *before* entering recursion to gracefully handle # self-referential objects seen.add(obj_id) if isinstance(obj, dict): size += sum([get_size(v, seen) for v in obj.values()]) size += sum([get_size(k, seen) for k in obj.keys()]) elif hasattr(obj, '__dict__'): size += get_size(obj.__dict__, seen) elif hasattr(obj, '__iter__') and not isinstance(obj, (str, bytes, bytearray)): size += sum([get_size(i, seen) for i in obj]) return size 
6
22 июля '16 в 1:21 2016-07-22 01:21 atsakymas pateikiamas liepos 22 d., 16 d., 1:21 2016-07-22 01:21

Jei kas nors susiduria su šiuo klausimu ir jam reikia daugiau „bulletproof“ nei „sys.getsizeof“ arba „Aaron Hall“ pateiktoje procedūroje, čia yra receptas, kuriuo siekiama iš esmės ir lanksčiai išspręsti problemas, pvz., Klases ir baitekodus (Deja, čia yra pernelyg sunku pakartoti ar protingai apibendrinti).

4
13 июля '15 в 19:02 2015-07-13 19:02 Atsakymą pateikė RichardW liepos 13 d. 15, 19:02 2015-07-13 19:02

Naudodami išteklių modulį , galite išmatuoti dabartinio proceso rezidentų rinkinio maksimalaus dydžio pasikeitimus, pavyzdžiui:

1
13 дек. Atsakymą Raymond pateikė gruodžio 13 d. 2016-12-13 09:04 '16 at 9:04 2016-12-13 09:04

Nė vienas iš atsakymų čia nėra iš tikrųjų bendro pobūdžio. Šis sprendimas bus rekursyviai naudojamas bet kokio tipo objektams:

 import gc def get_obj_size(obj): marked = {id(obj)} obj_q = [obj] sz = 0 while obj_q: cur_obj = obj_q.pop(0) sz += sys.getsizeof(cur_obj) all_refr = ((id(o), o) for o in gc.get_referents(cur_obj)) new_refr = list(filter(lambda o: o[0] not in marked, all_refr)) if len(new_refr) > 0: refr_id, refr = zip(*new_refr) obj_q.extend(refr) marked.update(refr_id) return sz 
0
10 дек. Atsakymą pateikė Liran Funaro, gruodžio 10 d. 2018-12-10 15:28 '18, 15:28 2018-12-10 15:28

Pirma: atsakymas.

 import sys try: print sys.getsizeof(object) except AttributeError: print "sys.getsizeof exists in Python ≥2.6" 

Diskusija:
„Python“ sistemoje niekada negalėsite pasiekti tiesioginių atminties adresų. Kodėl jums reikia ar norite sužinoti, kiek tokių objektų užima šis objektas? Šis klausimas yra visiškai netinkamas šiam abstrakcijos lygiui. Kai nudažysite savo namus, jūs neklausiate, kokie šviesos dažniai yra absorbuojami arba atspindėti kiekviename iš atomo vidų dažuose, tiesiog paklausti, kokia spalva - tai fizinės charakteristikos, kurios sukuria šią spalvą, nėra svarbios. Panašiai yra ir šio „Python“ objekto užimamų baitų skaičius.

Tad kodėl bandote naudoti „Python“ C kodui rašyti? :)

-4
16 янв. Atsakymą pateikė Jeff Shannon , 16 d. 2009-01-16 09:58 '09 9:58 am. 2009-01-16 09:58