+ 2
[Solved] Can we build a method to call different setter base on the arguments?
As title suggested, I want to create a method which can call different setter. The idea is like a control panel of a big machine. The control panel represent the method, and the buttons are different setter. User pushes different button (argument) to fire different setter. In my code I created the method, and calling it with 2 attempts. The first one failed, and the second runs without error code but changes nothing. And Why? A side question too. In the same code I created the __str__ method, which calls the getter to create a String. It doesn't work too. I would like a hint what went wrong. https://code.sololearn.com/csSsZv1zsM56/?ref=app
11 Antworten
+ 5
Inside the class:
def changescore(self, topic, new_score):
setattr(self, topic, new_score)
Use it like this:
me.changescore("english", 75)
The NameError is caused by passing to the function a variable (english) which does not exist in the outside scope.
In your attempt: self.topic = ...
the code just creates a new internal field called topic and assigns to it whatever you were passing in the "topic" argument...
About the __str__ method, your current solution of referring to the internal properties like self._english is fine, when you are still inside the class.
From outside you would use me.english without parentheses to invoke the getter function. The property decorator puts a "façade" on top of the masked _english field. But you can also use self.english from inside, to drive the output through the getter function. Currently it makes no difference because the getter does not change the value shown.
+ 6
Wong Hei Ming this may not be exactly what you are attempting but might be a workaround
https://code.sololearn.com/cg0Yix2Jf6NB/?ref=app
+ 4
Use Tibor Santa 's advice, and you will get the desired result:
https://code.sololearn.com/c9kccA3794Nc/?ref=app
+ 3
I think actually the OOP capabilities of Python, are trying to copy the encapsulation practices of statically typed languages such as Java... and as a result they bring the worst of both worlds. Name mangling is not true encapsulation, and always having to refer to the instance as 'self', I find it rather annoying and verbose.
In my opinion using keyword arguments in this specific case, and storing the scores in a dictionary, looks much better than creating individual fields with property decorator.
See this code where I also added constraints about which subjects are valid, and the possibility to only specify the subjects of your choice, not all. You could also add validation related to the score value, for example that it cannot be negative or higher than 100.
https://code.sololearn.com/cIqb04erFmc8/?ref=app
+ 3
Tibor Santa, Vitaly Sokol thank you. That is what I'm looking after.
I know no matter the attribute is single underscore or dunder we can always access and modify it directly, so there is not much reasons to write getter and setter.
The only reason I can think about is using python as a tool of rapid development, and then port the working code to other languages which are fully implement encapsulation. This way we have a blueprint for reference.
I write the code in this way because I'm practicing classes, which I didn't try before.
The code just shows the essence of my problem and nothing related to what I'm coding currently.
Yet I learned a lot from the examples and answers.
+ 2
BroFar
That was the first thing comes to my mind
However, If-elif is what I'm trying to avoid.
One of the OOP concept is an object can have method. Method, similar to function, can accept arguments to perform differently.
That's why I want a change_score method, receive subject and new score as the arguments, to change the corresponding score.
If an universal setter can interact with different setters, there is no need to write lots of if-elif and simply the code.
+ 2
With setattr() method mentioned I imagined there will be a getattr() method.
My hunch was right and also discovered hasattr() and delattr().
I think it may become useful if we want to add / remove an object’s property on-the-fly.
The most relevant example I can think of right now is "Nameless One" from a PC game "Planescape: Torment". With a correct character builds he learn new ability and able to switch between three classes.
My assumption is that Nameless One inherits methods from corresponding class or sub-class when he learned new ability. When he changing class, the program run a series of hasattr() and setattr() to change the class attribute, and implement some sort of error handling like method to prevent Nameless One performs action which are not allowed at given status.
+ 2
Wong Hei Ming
very late for the topic, but I was playing around with immutable dictionaries and here is something that can be considered:
https://code.sololearn.com/cAEXoFIuOHYa/?ref=app
+ 1
Wong Hei Ming in my view, setattr and other similar tools, are for surgical modification of an instance. They are very similar to Java runtime reflection. I would avoid using them if at all possible.
I am quite sure that the Nameless One use case could be implemented much more transparently with other object oriented techniques and design patterns, as with inheritance, dependency injection and so on. :)
+ 1
Bob_Li
Woah. It is like you are implementing your own set and get method for a dict type.
0
Wong Hei Ming an immutable dict type.
I extended your idea of an identifier to include aliases or alternative strings to call the setter.