[Python] Probleem met globale variabelen

Pagina: 1
Acties:
  • 336 views sinds 30-01-2008
  • Reageer

Acties:
  • 0 Henk 'm!

  • DumbAss
  • Registratie: April 2002
  • Laatst online: 16-08 11:30
Ik ben net begonnen met python en loop tegen een probleem aan.
Ik heb een script deze importeert een zelfgeschreven module genaamd "command". Dit is een klassebestand.
Het script heeft de naam ssh.py. Als ik deze uitvoer declareer ik een globale variabele "s". Deze wil ik later gebruiken in de module command.

Dus in ssh.py doe ik:
code:
1
2
echoCommand = command.command('ls -al')
exitstatus = echoCommand.run()

Hier instantieer ik het object. In de functie run() vraag ik de globale "s" op. Maar hier herkent hij hem niet.

Als error krijg ik:
code:
1
NameError: global name 's' is not defined


Ik heb al gezocht in de documentatie van Python, maar naar mijn weten zou dit gewoon moeten werken. Iemand een idee of een richting waarin ik moet kijken?

Vanutsteen.nl => nerds only | iRacing


Acties:
  • 0 Henk 'm!

  • PommeFritz
  • Registratie: Augustus 2001
  • Laatst online: 20-07-2024

PommeFritz

...geen friet

voeg toe:
code:
1
global s

FireFox - neem het web in eigen hand


Acties:
  • 0 Henk 'm!

  • DumbAss
  • Registratie: April 2002
  • Laatst online: 16-08 11:30
Yes, dat heb ik ook gedaan. Zowel in mijn main script, de functie in de class en de class zelf. Maar nog steeds herkent hij "s" niet.
edit:
Heeft dit ook te maken met het feit dat ik bij iedere functie in een class opnieuw import moet doen?

[ Voor 34% gewijzigd door DumbAss op 16-07-2006 01:57 ]

Vanutsteen.nl => nerds only | iRacing


Acties:
  • 0 Henk 'm!

  • Soultaker
  • Registratie: September 2000
  • Laatst online: 00:24
Als je een variabele buiten een klasse of functie definieert, zit het in de namespace die bij die module hoort. Een globale namespace is er dus niet echt. Om aan een variabele te refereren die in een andere module gedeclareert is, moet je expliciet de module erbij aangeven, of de variabele expliciet importeren in de namespace in de huidige module.

Een voorbeeld van het eerste:
Python:
1
2
3
4
5
6
# A.py
x = 123

# B.py
import A
print A.x

Een voorbeeld van het tweede:
Python:
1
2
3
4
5
6
# A.py
x = 123

# B.py
from A import x
print x

Acties:
  • 0 Henk 'm!

  • Confusion
  • Registratie: April 2001
  • Laatst online: 01-03-2024

Confusion

Fallen from grace

Een alternatief is nog om geen globale variabelen te gebruiken en de variabele een attribuut van een of andere klasse te laten zijn.

Wie trösten wir uns, die Mörder aller Mörder?


Acties:
  • 0 Henk 'm!

  • DumbAss
  • Registratie: April 2002
  • Laatst online: 16-08 11:30
Hee bedankt voor de reacties. Ik denk nu dat ik het een beetje snap. Maar nu:
s is een instantie van het object pxssh (pxssh.py). Hoe kan ik deze nu gebruiken in bijvoorbeeld de module command (command.py)? En command is dan ook weer een class.

Hebben jullie tevens nog trucs om de imports een beetje overzichtelijk te houden? Aangezien je deze bij iedere methode opnieuw moet doen.

[ Voor 6% gewijzigd door DumbAss op 16-07-2006 11:28 ]

Vanutsteen.nl => nerds only | iRacing


Acties:
  • 0 Henk 'm!

  • djc
  • Registratie: December 2001
  • Laatst online: 08-09 23:18

djc

DumbAss schreef op zondag 16 juli 2006 @ 11:27:
Hee bedankt voor de reacties. Ik denk nu dat ik het een beetje snap. Maar nu:
s is een instantie van het object pxssh (pxssh.py). Hoe kan ik deze nu gebruiken in bijvoorbeeld de module command (command.py)? En command is dan ook weer een class.

Hebben jullie tevens nog trucs om de imports een beetje overzichtelijk te houden? Aangezien je deze bij iedere methode opnieuw moet doen.
Volgens mij haal je wat dingen door elkaar. Een Python bestand op je harde schijf is direct ook een Python module. Deze kun je importeren. IN de module vind je dan de objecten en/of variabelen die je daar gedefinieerd hebt. Je kunt er bij komen door gewoon een puntje tussen de module-naam en de variabele/klasse-naam te zetten, dus bijvoorbeeld module.functie.

Je mag zoveel klassen als je wilt in een module definieren -- je hoeft ze niet te verspreiden. Het lijkt alsof je enigszins compulsief elke klasse in een eigen bestand hebt gegooid, maar dat is niet altijd de beste aanpak -- logischer is het om aan elkaar gerelateerde klassen in 1 bestand te zetten.

Je imports doe je meestal globaal (op module-niveau). Je zet dus bovenaan command.py bijvoorbeeld "import pxssh", daarna kan je met px = pxssh.pxssh() een object van de klasse pxssh in de module pxssh instantiëren.

Rustacean


Acties:
  • 0 Henk 'm!

  • DumbAss
  • Registratie: April 2002
  • Laatst online: 16-08 11:30
Manuzhai schreef op zondag 16 juli 2006 @ 16:37:
[...]
Volgens mij haal je wat dingen door elkaar. Een Python bestand op je harde schijf is direct ook een Python module. Deze kun je importeren. IN de module vind je dan de objecten en/of variabelen die je daar gedefinieerd hebt. Je kunt er bij komen door gewoon een puntje tussen de module-naam en de variabele/klasse-naam te zetten, dus bijvoorbeeld module.functie.

Je mag zoveel klassen als je wilt in een module definieren -- je hoeft ze niet te verspreiden. Het lijkt alsof je enigszins compulsief elke klasse in een eigen bestand hebt gegooid, maar dat is niet altijd de beste aanpak -- logischer is het om aan elkaar gerelateerde klassen in 1 bestand te zetten.

Je imports doe je meestal globaal (op module-niveau). Je zet dus bovenaan command.py bijvoorbeeld "import pxssh", daarna kan je met px = pxssh.pxssh() een object van de klasse pxssh in de module pxssh instantiëren.
Nog even een vraagje. Ik heb een module genaam log. Deze bevat een functie: logError().
In een ander bestand, bovenaan en net onder class doe ik:
code:
1
import log

Bij def login(self) heb ik log nodig. Maar als ik dan
code:
1
log.logError("String")

doe, dan krijg ik de error:
code:
1
NameError: global name 'log' is not defined

Hoe kan dit dan? Moet ik de module dan toch per functie importeren?

Vanutsteen.nl => nerds only | iRacing


Acties:
  • 0 Henk 'm!

  • Soultaker
  • Registratie: September 2000
  • Laatst online: 00:24
Volgens mij heb je het nog niet helemaal begrepen. Met een 'import' statement importeer je alle declaraties uit een andere module in de huidige module, onder een bepaalde naam. Met 'global' kun je de declaraties in de huidige module binnen de scope van een functie halen.

Je module 'log' bevat 'logError'. Je huidige module doet 'import log', waardoor die module onder de naam 'log' beschikbaar is in de huidige module, maar alleen in de globale scope. Als je 'm in een functie wil gebruiken doe je dus:
Python:
1
2
3
4
5
import log
# ...
def functie():
  global log
  log.logError('string')


In zo'n geval zou je ook kunnen overwegen om niet de hele module, maar slechts de functie logError te importeren:
code:
1
2
3
4
5
from log import logError
# ...
def functie():
    global logError
    logError('blaat')


Het gaat er in ieder geval om dat je begrijpt, dat elke module een aantal variabelen kent. Je kunt andere modules (of delen daaruit, zoals ik mijn tweede voorbeeld) koppelen aan variabelen in je huidige module. Binnen een functie heb je geen beschikking tot variabelen die daarbuiten gedefinieerd zijn, tenzij je met 'global' aangeeft dat je een variabele van de huidige module wil gebruiken.

Acties:
  • 0 Henk 'm!

  • DumbAss
  • Registratie: April 2002
  • Laatst online: 16-08 11:30
Soultaker schreef op zondag 16 juli 2006 @ 20:07:
Volgens mij heb je het nog niet helemaal begrepen. Met een 'import' statement importeer je alle declaraties uit een andere module in de huidige module, onder een bepaalde naam. Met 'global' kun je de declaraties in de huidige module binnen de scope van een functie halen.

Je module 'log' bevat 'logError'. Je huidige module doet 'import log', waardoor die module onder de naam 'log' beschikbaar is in de huidige module, maar alleen in de globale scope. Als je 'm in een functie wil gebruiken doe je dus:
Python:
1
2
3
4
5
import log
# ...
def functie():
  global log
  log.logError('string')


In zo'n geval zou je ook kunnen overwegen om niet de hele module, maar slechts de functie logError te importeren:
code:
1
2
3
4
5
from log import logError
# ...
def functie():
    global logError
    logError('blaat')


Het gaat er in ieder geval om dat je begrijpt, dat elke module een aantal variabelen kent. Je kunt andere modules (of delen daaruit, zoals ik mijn tweede voorbeeld) koppelen aan variabelen in je huidige module. Binnen een functie heb je geen beschikking tot variabelen die daarbuiten gedefinieerd zijn, tenzij je met 'global' aangeeft dat je een variabele van de huidige module wil gebruiken.
toon volledige bericht
Aha. Ok. En maakt het qua snelheid dan nog uit of je iedere keer een import doet of hem als global aanroept?

edit:

Staat python ook toe om dynamisch variabelen aan te maken? In php kun je zoiets doen:
[code]
$var = 'var2';
$$var = 'ehlo';
echo $var2; #Geeft dan 'ehlo'
[/code]
Gevonden:
exec("%s = "ehlo" % ("var2"))

[ Voor 8% gewijzigd door DumbAss op 17-07-2006 00:12 ]

Vanutsteen.nl => nerds only | iRacing


Acties:
  • 0 Henk 'm!

  • Confusion
  • Registratie: April 2001
  • Laatst online: 01-03-2024

Confusion

Fallen from grace

Dynamisch variabelen aanmaken is slechts zelden zinvol. Als je niet zeker weet of het de beste oplossing is, dan is het niet de beste oplossing.

Wie trösten wir uns, die Mörder aller Mörder?


Acties:
  • 0 Henk 'm!

  • djc
  • Registratie: December 2001
  • Laatst online: 08-09 23:18

djc

Soultaker schreef op zondag 16 juli 2006 @ 20:07:
Volgens mij heb je het nog niet helemaal begrepen. Met een 'import' statement importeer je alle declaraties uit een andere module in de huidige module, onder een bepaalde naam. Met 'global' kun je de declaraties in de huidige module binnen de scope van een functie halen.

Je module 'log' bevat 'logError'. Je huidige module doet 'import log', waardoor die module onder de naam 'log' beschikbaar is in de huidige module, maar alleen in de globale scope. Als je 'm in een functie wil gebruiken doe je dus:
Python:
1
2
3
4
5
import log
# ...
def functie():
  global log
  log.logError('string')


In zo'n geval zou je ook kunnen overwegen om niet de hele module, maar slechts de functie logError te importeren:
code:
1
2
3
4
5
from log import logError
# ...
def functie():
    global logError
    logError('blaat')


Het gaat er in ieder geval om dat je begrijpt, dat elke module een aantal variabelen kent. Je kunt andere modules (of delen daaruit, zoals ik mijn tweede voorbeeld) koppelen aan variabelen in je huidige module. Binnen een functie heb je geen beschikking tot variabelen die daarbuiten gedefinieerd zijn, tenzij je met 'global' aangeeft dat je een variabele van de huidige module wil gebruiken.
toon volledige bericht
Ten eerste zou ik je eerste stukje anders formuleren: met import formuleer je niet zozeer alle declaraties uit een andere module in je eigen module; met een import van de vorm "import log" maak je in je eigen module een referentie naar de andere module, die je kunt gebruiken om in je eigen module de onderdelen van die module te gebruiken. Als je "from log import logError" gebruikt importeer je een referentie naar de logError class in de log-module.

Verder is in beide voorbeelden die je hier "global" overbodig. Je hebt namelijk in beide gevallen al een referentie naar het object wat je nodig hebt in je scope op module-niveau; je kunt er dan vanzelf al bij binnen een functie of klasse. Er is een uitzondering hierop: als je iets nieuws wil toewijzen aan een variabele uit de globale (module-level) scope, moet je wel eerst global gebruiken; anders denkt Python dat je een lokale (in de scope van je functie/klasse) variabele wil aanmaken. In het geval van een functie of klasse die van buiten je lokale scope doet kan je dus in de meeste gevallen goed zonder een "global" statement; als je een constant-achtige variabele gebruikt ook.

Anders loop je extreem veel loze globals in je code te gooien, dat zou zonde zijn.

Rustacean


Acties:
  • 0 Henk 'm!

  • DumbAss
  • Registratie: April 2002
  • Laatst online: 16-08 11:30
Nou, bedankt allemaal. Ik wil niet zeggen dat ik alles nu snap. Maar ik heb er in ieder geval veel van geleerd.
Nog een vraagje dan: Zit er nog verschil in de verschillende soorten comentaren die je kunt geven in python? Bijvoorbeeld:
code:
1
#print "Hello World"

en
code:
1
##print "Hello World"

Vanutsteen.nl => nerds only | iRacing


Acties:
  • 0 Henk 'm!

  • djc
  • Registratie: December 2001
  • Laatst online: 08-09 23:18

djc

Nee, dat zijn geen verschillende soorten.

Alle tekens op een regel na het '#'-teken worden genegeerd door de Python-interpreter.

Rustacean


Acties:
  • 0 Henk 'm!

  • Soultaker
  • Registratie: September 2000
  • Laatst online: 00:24
Manuzhai schreef op maandag 17 juli 2006 @ 11:20:
Verder is in beide voorbeelden die je hier "global" overbodig.
[..]
Anders loop je extreem veel loze globals in je code te gooien, dat zou zonde zijn.
Je hebt gelijk; mijn fout. (Lang niet in Python gecode.)

Acties:
  • 0 Henk 'm!

  • djc
  • Registratie: December 2001
  • Laatst online: 08-09 23:18

djc

Soultaker schreef op dinsdag 18 juli 2006 @ 17:07:
Je hebt gelijk; mijn fout. (Lang niet in Python gecode.)
Zonde. ;)

Rustacean


Acties:
  • 0 Henk 'm!

  • DeMoN
  • Registratie: Maart 2001
  • Laatst online: 04-09 12:38

DeMoN

Pastafari

DumbAss schreef op dinsdag 18 juli 2006 @ 00:43:
Nou, bedankt allemaal. Ik wil niet zeggen dat ik alles nu snap. Maar ik heb er in ieder geval veel van geleerd.
Nog een vraagje dan: Zit er nog verschil in de verschillende soorten comentaren die je kunt geven in python? Bijvoorbeeld:
code:
1
#print "Hello World"

en
code:
1
##print "Hello World"
Je kunt btw ook:

"""" gebruiken, dus 3 quotes. Dit voornamelijk om grote stukken te uncommenten :)

code:
1
"""dit is uncommented txt"""


Wat wel leuk is, is dat je het ook kan printen, raar maar waar.
code:
1
2
3
4
5
6
txt = """
hoi hoi ik ben een ssssslang en kom even zeggen
   dat python              een 
superrrrtaaal issssssssss"""

print txt # en hij zal het in dezelfde opmaak printen :)

Gamertag: Cosmicv0id
"Het woord Gods is voor mij niets meer dan een expressie en het product van menselijke zwakheid. De Bijbel is een verzamelwerk van legendes die achtenswaardig zijn maar ook primitief en kinderachtig.'' - Albert Einstein


Acties:
  • 0 Henk 'm!

  • Soultaker
  • Registratie: September 2000
  • Laatst online: 00:24
Meer precies, met drie enkele of dubbele quotes kun je strings construeren die meerdere regels lang zijn. Met één (enkele op dubbele quote) kun je een string op een regel construeren. In beide gevallen zijn het gewone string literals.

Strings kun je als commentaar in je code zetten. Sterker nog, als je ze bovenaan een klasse- of functiedefinitie of bovenin een module zet, beschouwt de interpreter ze als documentatie van die module/klasse/functie. Die documentatie is met 'help(functie)' op te vragen en komt een een member __doc__ te staan.
Pagina: 1