How can I create a method in a class with a user input?
What argument should I pass when I am calling the method ?
class Student:
def __init__(self):
self._name = ''
def getName(self):
return self._name
def setName(self, newName):
newName = input ('Inserire nome:')
self._name = newName
studente = Student()
studente.setName(newName)
This should work:
class Student:
def __init__(self):
self._name = ''
def getName(self):
return self._name
def setName(self, newName):
self._name = newName
studente = Student()
newName = input('Inserire nome:')
studente.setName(newName)
You were defining the input inside the method itself but passing the variable outside. So the variable newName wasn't defined outside. Let me know if it doesn't work. I haven't tested it, but seems like the conspicuous error here.
If I understood what you want correctly,
why dont you try to ask for an input when initialsing class instance?
class MyClass(object):
def __init__(self):
self.name = input('Enter name> ')
X = MyClass() # when executing that line, you'll be asked for a name to input
Then you'll be able to acces name attribute by X.name and set it to whatever you'd like to by X.name = foo
You could also play with the builtin setattr and dismiss the explicit setters/getters:
class Student:
pass
student = Student()
newName = input('Inserire nome:')
setattr(student, 'name', newName)
Related
If a class is created with the attributes: name and list and the name attribute has a default value and the list is appending the name. Is it possible in somehow when I create an object "a" and type
"a.name = 'x' " that this 'x' will appear in the list given that the list is appending in the constructor?
class Person:
list = []
def __init__(self, name="Zed"):
self.name = name
self.list.append(name)
def printList(self):
print(self.list)
a = Person()
a.name = "Yasuo"
a.printList() #outputs Zed but Yasuo is expected.
You can make name a property, and implement a setter that updates the list.
class Person:
list = []
def __init__(self, name="Zed"):
self._name = name
self.list.append(name)
#property
def name(self):
return self._name
#name.setter
def name(self, name):
if self._name in self.list:
# remove the old name
index = self.list.index(self.name)
self.list[index] = name
else:
self.list.append(name)
self._name = name
def printList(self):
print(self.list)
a = Person()
a.name = "Yasuo"
a.printList() # prints ['Yasuo']
Here is a MRE:
class Dog():
def __init__(self, action, name):
self.action = action
self.name = name
def name_dog(self):
my_name = input("give me a name: ")
return self.name(my_name)
def act_like_dog(self):
order = input("Tell me to do something: ")
msg = self.name + " is " + order
return self.action(msg)
def main(self):
self.name_dog()
self.act_like_dog()
Dog.main()
The main objective for calling the dog class in this case is for the user to input their own values (name, action) for the class. So the variables for the class I specified (Dog class) are obtained from a function call (self.name_dog and self.act_like_dog) in the main() function, which prompts the user to give his/her input. However when I tried calling the main() function without self, I got an error saying a positional argument is needed, while if I called the function self(), an error says that self is not defined. How do I fix this?
You seem to be confused about a few elements.
You need to create an actual instance of the class to be able to class its methods - Dog(...). Apart from that, there is a logical problem where you expect to create an instance with name and action but then take them as inputs from the user. I think what you should do is simply set the attributes with user input in the __init__. Something like:
class Dog():
def __init__(self):
self.name = self.name_dog()
self.action = self.act_like_dog()
def name_dog(self):
my_name = input("give me a name: ")
return my_name
def act_like_dog(self):
order = input("Tell me to do something: ")
msg = self.name + " is " + order
return msg
dog = Dog()
If you want to be able to change the name and action later, you can use your main idea:
class Dog():
def __init__(self):
main()
...
def main():
self.name = self.name_dog()
self.action = self.act_like_dog()
dog = Dog()
You might be looking for something like so:
class Dog:
def __init__(self, action=None, name=None):
if name:
self.name = name
else:
self.name = input("Dog's name: ")
if action:
self.action = action
else:
self.action = input("Dog's action: ")
d = Dog()
# ... or ...
d = Dog("Max", "Bark")
# ... or ...
d = Dog("Max")
d = Dog(name="Max")
# ... or ...
d = Dog(action="Bark")
[This is in Python 3.6.8] So my impression was that a subclass inheriting from a superclass would be able to access the superclass' attributes freely, even if the attribute was "private". For example:
class A():
def __init__(self, name):
self.__name = name
def __str__(self):
return f'my name is {self.__name}'
class B(A):
def __init__(self, name, number):
A.__init__(self, name)
self.__number = number
def __str__(self):
return f'my name is {self.__name}\nmy number is {self.__number}'
def main():
name = input('name: ')
number = input('number: ')
obj = B(name, number)
print(obj)
main()
Apparently, when I try to use self.__name in the __str__ function of the subclass B, it throws an AttributeError exception, stating: AttributeError: 'B' object has no attribute '_B__name'. However, the program works as intended when I use a accessor (getter) method for getting the name instead of self.__name. So was my initial impression wrong, or am I making a misunderstanding somewhere?
I am trying to print a string variable returned by name() function, which in this case should print "Jim, but Python is printing
`<bound method Human.name of <__main__.Human object at 0x7f9a18e2aed0>>`
Below is the code.
class Human:
def __init__(self):
name = None
def setName(self, _name):
name = _name
def name(self):
return self.name
jim = Human()
jim.setName("Jim")
print(jim.name())
UPDATE:
After reading the answers, i updated the code as shown below, but, now i am getting a new error TypeError: 'str' object is not callable
class Human:
def __init__(self):
self.name = None
def setName(self, _name):
self.name = _name
def name(self):
return self.name
jim = Human()
jim.setName("Jim")
print(jim.name())
self.name is the method itself. You have no attributes storing the name. Nowhere do you actually set the name as an attribute. The following works:
class Human:
def __init__(self):
self.name = None
def setName(self, _name):
self.name = _name
# NOTE: There is no more name method here!
Now you have an actual attribute, and you don't need to call the method here:
jim = Human()
jim.setName("Jim")
print(jim.name) # directly using the attribute
You could even just set the attribute directly:
jim = Human()
jim.name = "Jim"
print(jim.name)
Alternatively, use self._name to store the name on the instance:
class Human:
_name = None
def setName(self, _name):
self._name = _name
def name(self):
return self._name
Here we used a class attribute Human._name as a default, and only set self._name on the instance in the Human.setName() method.
The problem is that name is the name of the internal variable in your object and also the name of the method.
The namespace for variables and methods is the same. Change the name of your method to something other than name. This will fix your getter. On first glance I thought that that would be all you have to do, but the recommendation in Martijn's answer also applies -- you need to assign to self.name and not just name in order to get your setter to work as well.
As an aside, this getter/setter pattern is not usually appropriate for Python. You should ask yourself why you want to use a getter/setter pattern over simply accessing the object's variable directly. See the section on getters and setters in this article for more detail.
You can use setter and getter properties instead of your custom defined methods.
class Human():
def __init__(self):
self._name = None
#property
def name(self):
return self._name
#name.setter
def name(self, name):
self._name = name
And then, use them:
jim = Human()
jim.name = "Jim"
print(jim.name)
I'm considering the following approaches for class initialisation:
class Foo():
def __init__(self):
self.name = self.get_name()
def get_name(self):
return raw_input("Name: ")
class Foo():
def __init__(self):
self.name = ""
self.get_name()
def get_name(self):
self.name = raw_input("Name: ")
class Foo():
def __init__(self):
self.name = raw_input("Name: ")
Is there any practical reason to opt for one over the others?
If not, which might be considered most Pythonic?
If possible, input() the name outside of the class and pass it as a parameter to its __init__().
If this is not an option, I would go for the second alternative
I would rename get_name() to something like query_name() or input_name(). get_name() sounds like a getter (that gets the value of name) not like a setter or a routine that gets data from the user.
I don't like the idea of doing a raw input in the constructor, but after all, why not...
I would prefer:
class Foo():
def __init__(self):
self.name = ""
def prompt_name(self):
self.name = raw_input("Name: ")
if __name__ == "__main__":
aFoo = Foo()
aFoo.prompt_name()