[Python] "Static" method in Module

Pagina: 1
Acties:

  • Grijze Vos
  • Registratie: December 2002
  • Laatst online: 23:50
Ik ben voor een project van mijn opleiding aan het klooien in Python. Ik zit nu met het volgende rare probleem.

Ik heb een module met een variabele, en die variabele wil ik vanuit een andere module kunnen setten. Ik wil het liefste natuurlijk deze variabele afschermen en de set via een functie laten doen, maar Python's namespaces zitten me daar behoorlijk bij te irriteren.

Testopstelling:

module 1, bla.py:
Python:
1
2
3
4
5
6
7
testVar = "bla"

def setTest(t):
    testVar = t

def showTest():
    print testVar


module 2 bla2.py
Python:
1
2
3
4
5
6
7
8
9
import bla

#dit werkt dus niet.
bla.setTest("bla2")
bla.showTest()

#dit werkt wel, maar ik wil testVar graag private maken, en dan kan dit natuurlijk niet.
bla.testVar = "bla"
bla.showTest()


uitvoer:
code:
1
2
bla
bla2


Een andere oplossing die ik zou kunnen doen is een class maken in die module, daar een static method op maken etc, maar dat vind ik nogal overhead voor zoiets simpels.

Misschien dat ik niet in de goede "mindset" zit met Python ofzo, dit is dan ook mn eerste keer dat ik in aanraking kom met deze taal. Iemand enige ideeen?

Op zoek naar een nieuwe collega, .NET webdev, voornamelijk productontwikkeling. DM voor meer info


Verwijderd

Je zou global kunnen gebruiken:
Python:
1
2
3
4
5
testVar = "bla"

def setTest(t):
    global testVar
    testVar = t

Waarom in de oorspronkelijke versie showTest() wel werkt, is omdat Python eerst op functie-niveau op zoek gaat naar testVar een daarna op module-niveau. in setTest() wordt testVar echter meteen op functie-niveau geassigned. Door global kan je dit gedrag dus veranderen.

  • Michali
  • Registratie: Juli 2002
  • Laatst online: 09-12-2025
Hier kun je het beste een hulp class voor gebruiken:

Python:
1
2
3
4
5
6
7
8
9
class StaticMethod:
    def __init__(self, method):
        self.__call__ = method

class A:
    def eenStaticMehod:
        # je code
        pass
    eenStaticMethod = StaticMethod(eenStaticMethod)


Bron: http://aspn.activestate.c...kbook/Python/Recipe/52304

Noushka's Magnificent Dream | Unity


Verwijderd

Of je gebruikt de standaard ingebouwde staticmethod decorator:

Python:
1
2
3
4
5
class A(object):
    @staticmethod
    def eenStaticMehod():
        # je code
        pass


De classmethod decorator is misschien nog iets handiger, maar dat mag je zelf even opzoeken ;)

Verwijderd

Wat _J_R_R de eerste keer zei is de juiste oplossing. Dat gedrag komt door de scoping regels van Python: oftewel, als je assignt aan een variabele in een functie, wordt deze automatisch gezien als lokale variabele, tenzij je hem expliciet als global declareert. Alleen uitlezen kan wel.

  • Grijze Vos
  • Registratie: December 2002
  • Laatst online: 23:50
Bedankt voor de input, ik heb het zelf toch ietsie anders aangepakt, vond ik zelf net een tikkie mooier.

Python:
1
2
3
4
5
6
7
8
9
10
class _privateClass():
    eenVar = None


def setEenVar(v):
    _privateClass.eenVar = v


def getEenVar():
    return _privateClass.eenVar


Zo zijn de functies toch gewoon functies op het niveau van de module, en kan ik toch mn variabelen afschermen in de private class.

Op zoek naar een nieuwe collega, .NET webdev, voornamelijk productontwikkeling. DM voor meer info


Verwijderd

Grijze Vos schreef op zondag 21 mei 2006 @ 18:43:
Bedankt voor de input, ik heb het zelf toch ietsie anders aangepakt, vond ik zelf net een tikkie mooier.

Python:
1
2
3
4
5
6
7
8
9
10
class _privateClass():
    eenVar = None


def setEenVar(v):
    _privateClass.eenVar = v


def getEenVar():
    return _privateClass.eenVar


Zo zijn de functies toch gewoon functies op het niveau van de module, en kan ik toch mn variabelen afschermen in de private class.
Er hoeven geen haakjes achter een klassenaam (mag wel natuurlijk, je hebt zo een lege inheritancelijst).

En merk op dat je nog steeds geen private variabelen hebt, want die bestaan simpelweg niet in Python:

Python:
1
2
3
4
import jouwmod

jouwmod._privateClass.eenVar = 5
print jouwmod.getEenVar()                  # Print "5"

  • Grijze Vos
  • Registratie: December 2002
  • Laatst online: 23:50
Verwijderd schreef op zondag 21 mei 2006 @ 22:18:
[...]


Er hoeven geen haakjes achter een klassenaam (mag wel natuurlijk, je hebt zo een lege inheritancelijst).
Mag zelfs niet merk ik net (compiled niet met haakjes). Ik typte dit stukje hierboven uit de losse pols.
En merk op dat je nog steeds geen private variabelen hebt, want die bestaan simpelweg niet in Python.
Nee, idd, je kunt hem nog steeds aanspreken. Maar de intentie dat die variabele private is is iig duidelijk, en daar gaat het dan uiteindelijk om I guess.

Ik vind Python nog steeds een beetje raar aanvoelen. Ik weet niet.

Op zoek naar een nieuwe collega, .NET webdev, voornamelijk productontwikkeling. DM voor meer info


  • Michali
  • Registratie: Juli 2002
  • Laatst online: 09-12-2025
Als je 2 underscores voor een instance variabel zet, dan is hij toch private? Ik weet niet of dat ook voor andere variabelen geldt, maar het kan in sommige gevallen dus wel.

Noushka's Magnificent Dream | Unity


Verwijderd

Michali schreef op maandag 22 mei 2006 @ 09:16:
Als je 2 underscores voor een instance variabel zet, dan is hij toch private? Ik weet niet of dat ook voor andere variabelen geldt, maar het kan in sommige gevallen dus wel.
Als je dat doet wordt de naam ge"mangled", door de naam van de klasse er in te verwerken. Als ik het me goed herinner gaat dat zo (Google voor de echte details):

Python:
1
2
3
class Poep:
    def __init__(self):
        self.__prive = 1


Wordt geïnterpreteerd als:

Python:
1
2
3
class Poep:
    def __init__(self):
        self.__Poep__prive = 1


Dit heeft dus tot gevolg dat de variabele wel een beetje private is, maar als je weet wat er met de naam gebeurt, je nog steeds bij de variabele kunt.

Python:
1
2
3
p = Poep()
print p.__prive              # Werkt niet
print p.__Poep__prive   # Werkt wel


Nogmaals, prive variabelen bestaan echt niet in Python. Het gebruik van members van een klasse wordt aangegeven door conventie. Beginnen met een underscore, of met twee underscores, geeft aan dat de member prive-ish is, en dat je er als externe gebruiker beter van af kunt blijven als je wil dat de klasse werkt zoals geadverteerd.

Van de andere kant, als je ècht iets specifieks wilt veranderen aan hoe de klasse, of een object, werkt, dan kun je altijd lekker in zijn ingewanden gaan liggen peuren.

  • djc
  • Registratie: December 2001
  • Laatst online: 08-09-2025

djc

Verwijderd schreef op maandag 22 mei 2006 @ 13:18:
Nogmaals, prive variabelen bestaan echt niet in Python. Het gebruik van members van een klasse wordt aangegeven door conventie. Beginnen met een underscore, of met twee underscores, geeft aan dat de member prive-ish is, en dat je er als externe gebruiker beter van af kunt blijven als je wil dat de klasse werkt zoals geadverteerd.
Precies: Python gaat er vanuit dat we allemaal "consenting adults" zijn, en dat we geen private variabelen gaan zitten misbruiken. De __privates zijn dus ook niet bedoeld om iets echt heel erg private te maken, maar om problemen te verhelpen met inheritance (zodat verschillende classes in de inheritance chain dezelfde variabele-namen kunnen gebruiken zonder elkaar daarbij in de weg te zitten).

Rustacean


Verwijderd

Grijze Vos schreef op maandag 22 mei 2006 @ 01:12:
[...]

Mag zelfs niet merk ik net (compiled niet met haakjes). Ik typte dit stukje hierboven uit de losse pols.
Als we toch al een beetje off-topic zijn: je kan beter al je classes uit object inheriten (class Foo(object): pass). Zo maak je ze "new-style". Old-style classes, zoals jij ze nu maakt, bestaan alleen nog vanwege backwardscompabiliteit: new-style classes hebben vele voordelen. In Python 3000 worden old-style classes verwijderd.
Pagina: 1