Sindskort ben ik met wat nieuwe talen (Ruby, Python, C#) aan het experimenteren geslaan, omdat PHP me een beetje begon te vervelen
. Alhoewel ik wel wat algemene programmeervaardigheden en kennis bezit, ben ik qua python nog een beginneling. Hopelijk kunnen jullie me helpen.
Ik heb een vraag mbt het encapsuleren van data in een klasse. Vanuit mijn java-achtergrond ben ik gewend om simpelweg voor alle velden een private var te maken met public accessor methods (of deze door een IDE te laten genereren bij bijv. Data-driven EJB's). Het bekende verhaal dus.
Nu worden getters en setters in python beschouwd als zaken die de productiviteit en de leesbaarheid niet ten goede komen. Toen ik dit voor het eerst las dacht ik: "WTF? Wat moet je dan? public velden gebruiken? Dat is toch een stap terug?". Enfin, na wat rondneuzen kwam ik erachter dat dat inderdaad is wat men in python propageert. Het cruciale verschil met Java is echter dat je naderhand aan deze variabelen behavior kunt toevoegen mbv properties. Dit wordt mooi samengevat in het volgende stukje.
Als je nu een stukje implementatie wilt toevoegen aan bijvoorbeeld de naam, dan pas schrijf je een getter en evt een setter en koppel je deze mbv property() aan het veld "name".
Dit was mijn eerste poging, maar dit werkt niet. Als ik nu obj.name aanroep dan krijg ik nog steeds "jan janssen" terug en niet "Jan Janssen". M.a.w. het echte veld "name" prevaleert over de property "name". Het probleem is nu dat ik mijn class helemaal moet gaan refactoren. Wat mij de beste manier lijkt is alle self.name herschrijven naar self_name, en dat consistent doorvoeren in de hele klasse. Dus dan krijg je zoiets:
Dit werkt wel, maar echt elegant vind ik het niet. In python schrijft men tbv de productiviteit geen accessor methods voor simpele veld-toegang: akkoord. Maar wordt die productiviteit niet voor een gedeelte onderuit gehaald door het feit dat je elke occurrence van een bepaalde instantievariabele moet gaan herschrijven? En dat is niet eens het grootste probleem; met een goede editor en/of een slimme regex kom je een heel eind. Maar de leesbaarheid en daarmee de onderhoudbaarheid wordt er zo niet echt beter op, imho.
Mijn vraag is of er een betere/slimmere manier is om toch implementatie toe te voegen aan je velden zonder de api van je class te breken? Mijn excuses als dit een n00b-vraag is; ik ben nieuw met python.
Ik heb een vraag mbt het encapsuleren van data in een klasse. Vanuit mijn java-achtergrond ben ik gewend om simpelweg voor alle velden een private var te maken met public accessor methods (of deze door een IDE te laten genereren bij bijv. Data-driven EJB's). Het bekende verhaal dus.
Nu worden getters en setters in python beschouwd als zaken die de productiviteit en de leesbaarheid niet ten goede komen. Toen ik dit voor het eerst las dacht ik: "WTF? Wat moet je dan? public velden gebruiken? Dat is toch een stap terug?". Enfin, na wat rondneuzen kwam ik erachter dat dat inderdaad is wat men in python propageert. Het cruciale verschil met Java is echter dat je naderhand aan deze variabelen behavior kunt toevoegen mbv properties. Dit wordt mooi samengevat in het volgende stukje.
Dus je kunt behavior toevoegen of veranderen zonder dat je de api daarmee kapot maakt. Ideaal dus. Er is echter nog een dingetje waar ik over struikel in python. Stel je hebt de volgende class:Getters and setters are evil. Evil, evil, I say! Python objects are not Java beans. Do not write getters and setters. This is what the 'property' built-in is for. And do not take that to mean that you should write getters and setters, and then wrap them in 'property'. That means that until you prove that you need anything more than a simple attribute access, don't write getters and setters. They are a waste of CPU time, but more important, they are a waste of programmer time. Not just for the people writing the code and tests, but for the people who have to read and understand them as well.
In Java, you have to use getters and setters because using public fields gives you no opportunity to go back and change your mind later to using getters and setters. So in Java, you might as well get the chore out of the way up front. In Python, this is silly, because you can start with a normal attribute and change your mind at any time, without affecting any clients of the class. So, don't write getters and setters.
code:
1
2
3
4
| class Person: def __init__(self, name, email): self.name = "jan janssen" self.email = "a@b.com" |
Als je nu een stukje implementatie wilt toevoegen aan bijvoorbeeld de naam, dan pas schrijf je een getter en evt een setter en koppel je deze mbv property() aan het veld "name".
code:
1
2
3
4
5
6
7
8
9
10
11
| class Person: def __init__(self, name, email): self.name = "jan janssen" self.email = "a@b.com" def get_name(self): return self.name.capitalize() def set_name(self, name) self.name = name.capitalize() name = property(get_name, set_name) |
Dit was mijn eerste poging, maar dit werkt niet. Als ik nu obj.name aanroep dan krijg ik nog steeds "jan janssen" terug en niet "Jan Janssen". M.a.w. het echte veld "name" prevaleert over de property "name". Het probleem is nu dat ik mijn class helemaal moet gaan refactoren. Wat mij de beste manier lijkt is alle self.name herschrijven naar self_name, en dat consistent doorvoeren in de hele klasse. Dus dan krijg je zoiets:
code:
1
2
3
4
5
6
7
8
9
10
11
| class Person: def __init__(self, name, email): self._name = "jan janssen" self.email = "a@b.com" def get_name(self): return self._name.capitalize() def set_name(self, name): self._name = name.capitalize() name = property(get_name, set_name) |
Dit werkt wel, maar echt elegant vind ik het niet. In python schrijft men tbv de productiviteit geen accessor methods voor simpele veld-toegang: akkoord. Maar wordt die productiviteit niet voor een gedeelte onderuit gehaald door het feit dat je elke occurrence van een bepaalde instantievariabele moet gaan herschrijven? En dat is niet eens het grootste probleem; met een goede editor en/of een slimme regex kom je een heel eind. Maar de leesbaarheid en daarmee de onderhoudbaarheid wordt er zo niet echt beter op, imho.
Mijn vraag is of er een betere/slimmere manier is om toch implementatie toe te voegen aan je velden zonder de api van je class te breken? Mijn excuses als dit een n00b-vraag is; ik ben nieuw met python.
12 × LG 330Wp (Enphase) | Daikin FTXM-N 3,5+2,0+2,0kW | Panasonic KIT-WC03J3E5 3kW