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")
Related
So in python, there's the getattr function to automate getting attributes of a particular class, fair enough.
What I am trying to do is create a class from a user input, similar to how I could loop through class attributes using getattr.
Here's the process that I am sort of thinking of:
# Define classes that the user could chose
class Person():
def __init__(self):
self.prop1 = 'hi'
# Define other classes
className = input() # The user would then type a class name like Person
newObj = className() # I would want this to evaluate like Person()
Basically, I'm trying to not make my code look like a bunch of
if className == "Person":
newObj = Person()
elif className == "Dog":
newObj = Dog()
Basically, is there any built in function where I can refer to a class through a string?
If both classes' __init__ take the same arguments, the simplest way is with a mapping dict. My example below involves a cheeky error handling, which you can avoid if you split the second line into several.
mapping_dict = {'Person': Person, 'Dog': Dog}
instance = mapping_dict.get(user_input, lambda: print('Invalid class name'))()
# instance is None if an invalid input was provided
Without the cheeky error handling:
mapping_dict = {'Person': Person, 'Dog': Dog}
class_obj = mapping_dict.get(user_input)
if class_obj:
instance = class_obj()
else:
print('Invalid class name')
You can use factory design pattern:
class CAR(object):
def __str__(self):
return "This is a car"
class BUS(object):
def __str__(self):
return "This is a bus"
class TRAIN(object):
def __str__(self):
return "This is a train"
def create_vehicle(vehicle_type):
target_class = vehicle_type.upper()
return globals()[target_class]()
vehicles = ['bus', 'car', 'train']
for v in vehicles:
print (create_vehicle(v))
Output would be :
This is a bus
This is a car
This is a train
There is another metaclass based solution, though, it might be overkill for this simple requirement.
_registry = {}
class MetaClass(type):
def __init__(cls, clsname, bases, methods):
super().__init__(clsname, bases, methods)
_registry[cls.__name__] = cls
class CAR(metaclass=MetaClass):
def __str__(self):
return "This is a car"
class BUS(metaclass=MetaClass):
def __str__(self):
return "This is a bus"
class TRAIN(metaclass=MetaClass):
def __str__(self):
return "This is a train"
def create_vehicle(vehicle_type):
target_class = vehicle_type.upper()
return _registry[target_class]()
vehicles = ['bus', 'car', 'train']
for v in vehicles:
print (create_vehicle(v))
A dynamic approach below
import sys, inspect
def get_classes():
return {name: obj for name, obj in inspect.getmembers(sys.modules[__name__]) if inspect.isclass(obj)}
class Person():
def __init__(self):
print('Person ..')
self.prop1 = 'hi 0'
class Student():
def __init__(self):
print('Student ..')
self.prop1 = 'hi 1'
classes_mapping = get_classes()
user_input = input('Type class name:')
clazz = classes_mapping.get(user_input)
if clazz:
obj = clazz()
else:
print(f'Unknown class {user_input}')
My simplified code is below: it creates an animal, and places it inside a zoo. I want to print the list of animals within the zoo. Going round in circles with this!
class Animal(object):
def __init__(self, name):
self.name = name
class Zoo(object):
def __init__(self):
self.animals = []
def __str__(self):
rep = ", ".join(self.animals)
return rep
def add(self, name):
self.animals.append(Animal(name))
def main():
while True:
zoo = Zoo()
animal = input("add an animal: ")
zoo.add(animal)
print(zoo)
main()
The added __repr__ Method to the Animal returns us the name.
The zoo = Zoo() has to be outside of the loop, this makes sure that we do not create a new zoo with every iteration.
Then we print the list (zoo.animals).
class Animal(object):
def __init__(self, name):
self.name = name
def __repr__(self):
return self.name
class Zoo(object):
def __init__(self):
self.animals = []
def __str__(self):
rep = ", ".join(self.animals)
return rep
def add(self, name):
self.animals.append(Animal(name))
def main():
zoo = Zoo()
while True:
animal = input("add an animal: ")
zoo.add(animal)
print(zoo.animals)
main()
You can simply refer to the name property of Animal in your Zoo.__str__(), e.g.:
def __str__(self):
return ', '.join(animal.name for animal in self.animals)
Now print(zoo) should work correctly.
However this doesn't provide a lot of encapsulation if say you wanted to change what it means to print an animal, e.g. height, size, etc. So perhaps a more encapsulated form would be:
class Animal(object):
...
def __str__(self):
return self.name
class Zoo(object):
...
def __str__(self):
return ", ".join(str(animal) for animal in self.animals)
Now when you print(zoo) the Animal class is responsible for its own string presentation.
Just as a note: you probably should create the Animal instance outside of Zoo, what happens if you decide to create a class hierarchy of Animals (e.g. Mammal) that has different behaviours, your Zoo class would only know about Animals.
class Animal(object):
def __init__(self, name):
self.name = name
def __str__(self):
return self.name
class Zoo(object):
def __init__(self):
self.animals = []
def __str__(self):
return ", ".join(str(animal) for animal in self.animals)
def add(self, animal):
self.animals.append(animal)
def main():
zoo = Zoo()
while True:
animal = Animal(input("add an animal: "))
zoo.add(animal)
print(zoo)
main()
This would still behave properly if you create a Mammal class:
class Mammal(Animal):
...
zoo.add(Mammal(...))
print(zoo)
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)
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()
I am working on an assignment for Python Programming 157 at my school.
I need to write a class called Pet that has the following data attributes:
__name (for the name of the pet)
__animal_type (Examples: "Cat", "Dog", and "Hamster" )
__age (for the pet's age)
__height (for the pet's height)
It needs to include
set_name
get_name
I have tried like 4 times and cannot seem to get it right... any clues on getting it started?
# The Pet Program.
class PetProgram:
# The __init__ method accepts an argument for the program
# and adds it to the __pets attribute.
def __init__(self, pet):
self.__pets = pet
# The name will add to the pet attribute.
def name(self, name):
self.__pets = name
def age(self, age):
self.__pets = age
def animal(self, animal):
self.__pets = animal
def height(self, height):
self.__pets = height
# The pets_return will show you the list.
def pets_return(self):
return self.__pets
# The Pet Program.
import petsprogram
def main():
# Enter the name.
petname = input('What is the name of the pet: ')
print 'This will be added to the record.'
savings.name(petname)
# Display the list.
print petsprogram
main()
Above is my latest try...no such luck...any help? Thanks in advance...
A class is not a program, a class should model a thing, like a pet. Therefore, to start off, you should name your class appropriately.
class Pet(object): # Pet derives from the object class, always do this
Now I think you want a constructor that takes the name of the pet, and perhaps the type of pet as well, so we'll define that.
def __init__(self, pet_name, pet_type):
self.pet_name = pet_name
self.pet_type = pet_type
You also need a get and set for the name:
def get_name(self):
return self.pet_name
def set_name(self, pet_name):
self.pet_name = pet_name
To use this class, you instantiate it into an instance of the class:
puppy = Pet('Rover', 'Dog')
puppy.get_name() # prints Rover
I hope that's enough to get you going. You should read up on OOP in Python as mentioned in the comments.
First, why are you using "private" __attributes? That doesn't seem warranted.
Second, you're assigning all your properties to the same instance variable:
self.__pets = pet
self.__pets = name
self.__pets = age
self.__pets = animal
self.__pets = height
You should be using something like
def __init__(self, pet, name, age, animal, height):
self.pet = pet
self.name = name
self.age = age
self.animal = animal
self.height = height
and you should definitely read the tutorial on classes before venturing any further.
I'm not sure where the __pets binding comes into play. Your initial description doesn't say anything about that. I would not have expected an object that represents a pet, as in, a singular pet, to have an attribute that was a list of pets. I would expect something like:
class PetProgram:
def __init__(self, name ='', age=0, type='Unknown', height=0):
self.__name = name
self.__age = age
self.__animal_type = type
self.__height = height
def get_name(self):
return self.__name
def set_name(self, name):
self.__name = name
I'm also not sure where the imports petprogram comes from... is that perchance what your supposed to call your module, and then the instructor has provided that as something you're supposed to run to test it?
(also, what's with all the __under_scores? is this something your teacher is encouraging?)
How does something like this look?
>>> class Pets:
def set_Name(self,name):
self.name=name
def get_Name(self):
return self.name
def set_Atype(self,atype):
self.atype=atype
def get_Atype(self):
return self.atype
def set_Age(self,age):
self.age=age
def get_Age(self):
return self.age
def set_Height(self,height):
self.height=height
def get_Height(self):
return self.height