global vermeiden

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.
nemomuk
User
Beiträge: 862
Registriert: Dienstag 6. November 2007, 21:49

Freitag 1. August 2008, 17:15

Hallo,

ich versuche gerade keine globalen Vriablen in meinem Programm zu verwenden und wollte fragen, wie ich das am geschicktesten und besten mache.

Bsp:

Code: Alles auswählen

size = 0
def test():
    global size
    size += 123
if __name__ == "__main__":
    test()
    print size
Nun wollte ich eine eigene Funktion schreiben, die das += für mich erledigt, leider stehe ich vor dem problem, wie ich auf das "size" dann zugreife...

Code: Alles auswählen

size = 0
def test():
    size_add(123)
def size_add(size1)
    size += size1
if __name__ == "__main__":
    test()
    print size
Danke!
Benutzeravatar
Hyperion
Moderator
Beiträge: 7472
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Freitag 1. August 2008, 17:33

Indem du der Funktion size als zusätzlichen Parameter mit gibst!
BlackJack

Freitag 1. August 2008, 20:21

Ohne ``global``:

Code: Alles auswählen

def test(size):
    return size_add(size, 123)

def size_add(size, inkrement):
    return size + inkrement

def main():
    size = test(0)
    print size

if __name__ == '__main__':
    main()
nemomuk
User
Beiträge: 862
Registriert: Dienstag 6. November 2007, 21:49

Freitag 1. August 2008, 20:48

Danke!
Leonidas
Administrator
Beiträge: 16024
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Samstag 2. August 2008, 13:12

Wenn man ``global`` vermeiden will, dann vermeidet man auch modulglobale Variablen. So hat BlackJack ``size`` gar nicht im Modul stehen.
My god, it's full of CARs! | Leonidasvoice vs Modvoice
meneliel
User
Beiträge: 256
Registriert: Montag 25. Juni 2007, 08:35
Kontaktdaten:

Montag 4. August 2008, 14:04

Ich hab das inzwischen auch schon "probiert", ganz ohne garstige gobale Variablen auszukommen, hab dann aber festgestellt, dass sie mitunter ganz nützlich sein können.

Wenn ich eine Variable am Ende wirklich in fast jeder Funktion brauche, erscheint es mir deutlich praktischer sie einfach globalisieren, statt sie mehreren Funktion zu übergeben.
EyDu
User
Beiträge: 4871
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Montag 4. August 2008, 14:37

Das sagst du genau so lange, bis du mal Ewigkeiten nach einem Fehler suchst, der auf komischen Seiteneffekten basiert. Außerdem macht es das unmöglich deine Funktionen noch vernünftig zu testen.
Benutzeravatar
jens
Moderator
Beiträge: 8461
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Dienstag 5. August 2008, 07:38

Noch eine Möglichkeit: Eine Klasse mit Klassenweite Variablen zu nutzten.

CMS in Python: http://www.pylucid.org
GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
nemomuk
User
Beiträge: 862
Registriert: Dienstag 6. November 2007, 21:49

Dienstag 5. August 2008, 10:39

@jens: So mache ich es jetzt auch, das ist zwar in gewisser Weise ein Klassenmissbrauch, macht das Programm aber sehr viel übersichtlicher und erspart einem sehr viel Arbeit...
Benutzeravatar
snafu
User
Beiträge: 5466
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Dienstag 5. August 2008, 12:01

Ich würd's so machen:

Code: Alles auswählen

In [1]: class Size(object):
   ...:     def __init__(self):
   ...:         self.size = 0
   ...:     def add(self, number):
   ...:         return self.size + number
   ...: 

In [2]: size = Size()

In [3]: size.add(23)
Out[3]: 23

In [4]: size.add(42)
Out[4]: 65
Zuletzt geändert von snafu am Mittwoch 6. August 2008, 12:51, insgesamt 1-mal geändert.
Benutzeravatar
veers
User
Beiträge: 1219
Registriert: Mittwoch 28. Februar 2007, 20:01
Wohnort: Zürich (CH)
Kontaktdaten:

Dienstag 5. August 2008, 14:55

SchneiderWeisse hat geschrieben:@jens: So mache ich es jetzt auch, das ist zwar in gewisser Weise ein Klassenmissbrauch, macht das Programm aber sehr viel übersichtlicher und erspart einem sehr viel Arbeit...
Wieso Missbrauch? Das ist eine der Ideen von OOP - die Logik zusammen mit den Daten zu kapseln. Solange sich die Grösse einer Klasse in grenzen hält funktioniert das auch ganz gut ;)

PS: Irgend wie erinnert mich das ganze an die Informatik Olympiade - die fanden da auch alle "ach einfach alles global machen ist doch viel einfacher". Kommt wohl davon wenn man 90% Wegwerfcode schreibt ;)
[url=http://29a.ch/]My Website - 29a.ch[/url]
"If privacy is outlawed, only outlaws will have privacy." - Phil Zimmermann
yipyip
User
Beiträge: 418
Registriert: Samstag 12. Juli 2008, 01:18

Dienstag 5. August 2008, 18:04

Gerade Python bietet doch sooo viele Moeglichkeiten,
ein 'global' zu vermeiden (hab's selbst noch nie gebraucht):

Code: Alles auswählen

#!/usr/bin/env python

# C style

size_struct = {'size': 10}

def size_add(struct, size):

  struct['size'] += size


# Lisp style

def make_sizer(size):

  return [size]


def get_size(sizer):

  return sizer[0]


def set_size(sizer, size):

  sizer[0] = size
  return sizer


def add_size(sizer, size):

  return make_sizer(get_size(sizer) + size)


def destructive_add_size(sizer, size):

  return set_size(sizer, get_size(sizer) + size)


# Python OO style

class Sizer(object):


  def __init__(self, size):

    self.size = size


  def __add__(self, other):

    return self.size + other


  def __iadd__(self, other):

    self.size += other
    return self


  def __repr__(self):

    return "('Sizer', %d)" % self.size


  def __str__(self):

    return '%d' % self.size


####
  
def main_sizer():
  
  print 'C style:'
  size_add(size_struct, 123)
  print size_struct['size']

  print 'Lisp style:'
  s = make_sizer(10)
  print get_size(add_size(s, 123))
  print get_size(s)
  destructive_add_size(s, 123)
  print get_size(s)

  print 'Python OO style:'
  s = Sizer(10)
  print s + 123
  print s
  s += 123
  print s
  print repr(s)
  

####

if __name__ == '__main__':

  main_sizer()
:wink:
yipyip
RedGargoyle
User
Beiträge: 3
Registriert: Mittwoch 13. Januar 2016, 13:12

Mittwoch 13. Januar 2016, 17:50

Jetzt mal abgesehen davon, dass bei der Verwendung von global Seiteneffekte auftreten können, habe ich folgende Frage:
Was ist ganz praktisch gesehen der Unterschied zwischen den folgenden Beispielen?

Variante 1:

Code: Alles auswählen

a=0
b=0
c=0

def f():
    global a,b,c
    # Teil der Funktion, der auf a, b, c zugreift oder a, b, c verändert

f()
Variante 2:

Code: Alles auswählen

a=0
b=0
c=0

def ff(a,b,c):
    # Teil der Funktion, der auf a, b, c zugreift oder a, b, c verändert
    return a,b,c

a,b,c = ff(a,b,c)
Der Teil der Funktion, der auf a, b, c zugreift oder a, b, c verändert, könnte zum Beispiel

Code: Alles auswählen

    a+=1
    c=b+2
lauten.
Ich konnte in der Benutzung beider Varianten keinen Unterschied feststellen.
DasIch
User
Beiträge: 2452
Registriert: Montag 19. Mai 2008, 04:21
Wohnort: Berlin

Mittwoch 13. Januar 2016, 18:30

Der Unterschied ist das Variante 1 Komposition verhindert. Komposition ist grundlegend in der Informatik sowohl in der Theorie als auch der Praxis. Von den Subatomaren Teilchen aus denen das Silizium besteht mit dem dein Computer gebaut wurde aufwärts bis in die Software besteht alles aus Komponenten die mit anderen Komponenten zusammengefügt werden um neue Komponenten zu erstellen die eine auf einer höheren Abstraktionsebene existieren.

Wenn du eine solche Funktion mit anderen Funktionen verbindest sickert durch das global ihr Zustand hinaus und kleckert dir die ganze Komposition voll und ruiniert alles. Du bleibst stecken und kommst keine Abstraktionsebene mehr höher. Damit wird die Funktion nahezu unbenutzbar weil du sie zwangsläufig mit anderen kombinieren musst um sie zu testen oder wiederzuverwenden. Nutzt du Sie trotzdem kannst du die Funktion nicht mehr für sich selbst betrachten, viel mehr musst du die Funktion und alles worauf sie wann und wo hingekleckert hat auch noch verstehen.

Außerdem bekommt man einen Würgereiz wenn man sowas sieht und das Problem wirklich verstanden hat weil man sich schon vor der Vorstellung des Zustands der sich überall hin verteilt anfängt zu ekeln.
BlackJack

Mittwoch 13. Januar 2016, 18:58

@RedGargoyle: Und jetzt versuch das mal aus einer anderen Funktion heraus aufzurufen.
Antworten