Byte-Größe von Variablen

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
lupussy
User
Beiträge: 3
Registriert: Sonntag 23. Juli 2006, 11:34

Hallo,

wie kann man herausfinden, welche Bytegröße eine Variable hat?

Mit type(a) kann ich den Datentyp der Variablen a bekommen, gibt es so etwas wie size(a)?

Danke
Lupussy
BlackJack

Nein, gibt's nicht. Es gibt bei einigen Grundtypen das, AFAIK undokumentierte, Attribut `__basicsize__`. Aber bei etwas komplexeren Datenstrukturen, wie Objekten ist die Frage nicht mehr so einfach zu beantworten, weil viel mit Referenzen gearbeitet wird. Die Frage ist dann was alles sinnvoller weise zur Grösse dazu zählt und was nicht.

Wozu brauchst Du das denn?
LunarEffect
User
Beiträge: 5
Registriert: Freitag 28. Dezember 2007, 00:48

Hmm, bei Strings kannst du einfach len(a) nehmen. Jede stelle eines strings hat nämlich 1 Byte (so weit ich weiß) ^^
Jan-Peer
User
Beiträge: 166
Registriert: Dienstag 2. Oktober 2007, 10:55

... zumindest so lange, wie in dem String keine Nicht-ASCII-Zeichen vorkommen.
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Oder es keine Unicode-Strings sind. Dort muss man dann erstmal nachschauen, ob das Python UCS-2 oder UCS-4 kompiliert ist.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
lupussy
User
Beiträge: 3
Registriert: Sonntag 23. Juli 2006, 11:34

Danke für Eure Antworten, insbesondere blackjack für den Hinweis auf __basicsize__.

Diese Funktion läßt sich folgendermaßen verwenden:

Code: Alles auswählen

from types import *

types = [IntType,  LongType, FloatType, 
    NoneType, BooleanType,
    StringType, UnicodeType,
    TupleType, ListType, DictType,  
    ]

for t in types:
    print "%20s : %3s" % (t, t.__basicsize__)
Dies liefert folgende Ausgabe:

<type 'int'> : 12
<type 'long'> : 14
<type 'float'> : 16
<type 'NoneType'> : 8
<type 'bool'> : 12
<type 'str'> : 24
<type 'unicode'> : 24
<type 'tuple'> : 12
<type 'list'> : 20
<type 'dict'> : 124

Auf

http://groups.google.com/group/comp.lan ... e7b89c434/

gibt es einen Hinweis auf das builtin-Modul struct mit folgendem Code-Beispiel:

"You can use the struct module to find the size in bytes:"

Code: Alles auswählen

import struct 

mylist = [10, 3.7, "hello"] 

int_count = 0 
float_count = 0 
char_count = 0 

for elmt in mylist: 
    if type(elmt) == int: 
        int_count += 1 
    elif type(elmt) == float: 
        float_count += 1 
    elif type(elmt) == str: 
        char_count += len(elmt) 

format_string = "%di%dd%dc" % (int_count, float_count, char_count) 
list_size_in_bytes  = struct.calcsize(format_string) 
print list_size_in_bytes 
--output:--
17

und einen Hinweis auf das Python-Paket mxTools

http://www.egenix.com/products/python/

Dieses enthält eine Funktion sizeof(object):

"sizeof(object), mx.Tools.sizeof(object)
Returns the number of bytes allocated for the given Python object.
Additional space allocated by the object and stored in pointers is not
taken into account (though the pointer itself is). If the object defines
tp_itemsize in its type object then it is assumed to be a variable size
object and the size is adjusted accordingly." (aus der Doku)

Der folgende Code

Code: Alles auswählen

import mx.Tools

list  = [1, 1L, 1., 1j, True, None, '', u'', [1], (1,), {}]

for i in list:
    print "%20s : %3s" % (type(i), mx.Tools.sizeof(i))
liefert die Ausgabe:

<type 'int'> : 12
<type 'long'> : 16
<type 'float'> : 16
<type 'complex'> : 24
<type 'bool'> : 12
<type 'NoneType'> : 8
<type 'str'> : 24
<type 'unicode'> : 24
<type 'list'> : 20
<type 'tuple'> : 16
<type 'dict'> : 124

Die Werte stimmen weitgehend mit denen von __basicsize__ gelieferten überein, bis auf long.

Um jetzt die byte-Größe z.B. von einem int-Typ zu bekommen, muss man wohl von den 12 byte die Größe des Pointers abziehen??
BlackJack

Welcher Pointer? Und wieso abziehen? Wenn Du ``a = 0`` hast, könnte man auch argumentieren, man müsste mindestens die Grösse eines Dictionaries, einer Zeichenkette der Länge 1 und einen Pointer zur Grösse des `int` *addieren*, um den Speicherverbrauch angeben zu können. Andererseits wird die 0 sehr oft referenziert, man könnte also sagen die verbraucht gar keinen (zusätzlichen) Speicher, weil die sowieso immer da ist.

Nochmal die Frage: Was willst Du genau wissen und warum willst Du das wissen?
lupussy
User
Beiträge: 3
Registriert: Sonntag 23. Juli 2006, 11:34

Hallo BlackJack,

Zum Pointer:

In der Doku zu sizeof(object) des Paketes mxTools heißt es:
... Returns the number of bytes allocated for the given Python object.
Additional space allocated by the object and stored in pointers is not
taken into account (though the pointer itself is).
Diesen Pointer meine ich.

Warum ich das wissen will? Ich kenne das sizeof() von C. In Lehrbüchern kommt es meist in dem Kapitel über Datentypen vor, wenn es darum geht, ihre Byte-Größe zu ermitteln und Bitmuster darzustellen.

Ich wollte einfach wissen, ob das auch in Python geht ;-).
BlackJack

Ich weiss immer noch nicht welchen Pointer Du bei einem `int` meinst. Werden da welche im Objekt angelegt? Und wenn in einem Objekt welche angelegt werden, warum willst Du die nicht mit zählen? Die tragen ja ganz eindeutig zur Grösse des Objekts bei.

`sizeof()` in C ist etwas anderes, das gibt's in Python so nicht. In C sind Bezeichner Namen für feste Speicheradressen und haben einen Typ der eine zur Übersetzungszeit feste Grösse hat. Diese Grösse kann man mit `sizeof()` ermitteln. In Python sind Bezeichner keine Namen für Speicheradressen und haben auch keinen Typ. Beides ist in Python eine Eigenschaft des Objekts an den ein Name gebunden wird. Allerdings ist die Frage wieviel Speicher ein Objekt belegt eben nicht so einfach zu beantworten, weil man immer dazu sagen müsste was einen *genau* interessiert. Nur das Objekt selbst? Inklusive seiner Attribute? Alle? Wenn nicht, welche ja und welche nicht!? Die Klasse? Alle Superklassen?

Dazu kommt dann noch der Umstand, dass sich viele Objekte andere Objeke "teilen". Wie soll so etwas in die Zählung eingehen?
Mad-Marty
User
Beiträge: 317
Registriert: Mittwoch 18. Januar 2006, 19:46

Also ich würde die object bytesize jetzt eher aus dem Grund interressant finden, um abzuschätzen wieviel RAM benötigt wird.

Gibts da schon was was aus sagen wir 10 durchschnittlichen objekten (komplexe objekte) sagen kann wie gross jedes ist um das hochzurechnnen auf X viele Objekte.
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Mad-Marty hat geschrieben:Gibts da schon was was aus sagen wir 10 durchschnittlichen objekten (komplexe objekte) sagen kann wie gross jedes ist um das hochzurechnnen auf X viele Objekte.
Das kannst nur du für eine konkrete Anwendung machen, denn bei der Abschätzung muss bekannt sein, wie sich der Speicherverbrauch in etwa verhält: Gleichverteilt, Normalverteilt steigt er polynomiell oder exponentiell, ... .

Das lässt sich aus wenigen konkreten Objekten nicht automatisch ermitteln.
BlackJack

@Mad-Marty: Was zählt denn zu der Grösse eines Objektes dazu? Entweder man nimmt so wenig, dass im Grunde jedes Objekt nahezu gleich gross ist, oder man nimmt mehr und hat dann das Problem, dass man die Grösse von den Objekten nicht einfach zusammen rechnen kann, weil Objekte, die an diesen Objekten hängen, doppelt gezählt werden.
Mad-Marty
User
Beiträge: 317
Registriert: Mittwoch 18. Januar 2006, 19:46

Tja ehrlich gesagt fällt mir da ja auch nix ein, wie ich die komplexen objekte mit einer ungefähren größe errechnen lassen könnte.

Natürlich ohne die caches der Objekte ... und da gehts schon los mit den Problemen ... :D

Doppelt zählen würde sich wahrscheinlich vemeiden lassen (id()).
Antworten