I am playing around with classes in Python and do not understand how to add extra 'attributes'. For example my simple code that I have come up with below:
class Bird():
def __init__(self, name, age):
self.name = name
self.age=age
def birdsit(self):
print(self.name + ' is a bird that is sitting')
def birdfly(self):
print(self.name + ' is a bird that is flying')
def birdwalk(self):
print(self.name + ' is a bird that is walking')
myBird=Bird('Blue',4)
print(myBird.name)
myBird.birdsit()
myBird.birdfly()
myBird.birdwalk()
I am trying to simply add an attribute eg. the Type or Gender of the bird. I am self studying and the textbook I am using is so confusing and overwhelming and I can't really find a clear explanation.
Here you go. It's the same syntax for setting name or age. Also, watch out for your indents in the original post - the methods (i.e. def birdsit, def birdfly) all need to be indented once more than the class.
class Bird():
def __init__(self, name, age, type, gender):
self.name = name
self.age = age
self.type = type
self.gender= gender
def birdsit(self):
print(self.name + ' is a bird that is sitting')
def birdfly(self):
print(self.name + ' is a bird that is flying')
def birdwalk(self):
print(self.name + ' is a bird that is walking')
myBird = Bird('Blue', 4, 'swallow', 'do birds have genders?')
print(myBird.name, myBird.gender, myBird.type)
myBird.birdsit()
myBird.birdfly()
myBird.birdwalk()
Exactly are you trying to add? You already know how to create a new data attribute: simply assign to it. For instance, if you want a movement attribute for your bird, just do this:
def birdsit(self):
self.movement = "sit"
print(self.name + ' is a bird that is sitting')
def birdfly(self):
self.movement = "fly"
print(self.name + ' is a bird that is flying')
def birdwalk(self):
self.movement = "walk"
print(self.name + ' is a bird that is walking')
If the attribute doesn't exist, then it's created when you first hit one of these assignments. If it already exists, the assignment merely changes its value.
In this respect, it's just like a regular Python variable.
Attributes can be defined in the init() function which is automatically run when an instance of a class is created. To add a species attribute you can add it in the init function.
def __init__(self, name, age, species):
self.name = name
self.age = age
self.species = species
Related
I'm trying to write a program where I am trying to pass **kwargs in init() method. After that
when I m trying to make a instance variable inside the constructor(init() method ) , I cant able to make . How can I do this ?
Here is my code :
class Student:
def __init__(self,**kwargs):
self.name = name
self.age = age
self.salary = salary
def show_name(self):
print("Name is : " + self.name)
def show_age(self):
print("Age is : " + str(self.age))
def show_salary(self):
print(f"Salary of {self.name} is : " + str(self.salary))
st = Student('John',25,15000)
st2 = Student('Doe',25,1500000)
st.show_salary()
st2.show_salary()
**kwargs expects arguments to be passed by keyword, not by position. Once you do that, you can access the individual kwargs like you would in any other dictionary:
class Student:
def __init__(self, **kwargs):
self.name = kwargs.get('name')
self.age = kwargs.get('age')
self.salary = kwargs.get('salary')
def show_name(self):
print("Name is : " + self.name)
def show_age(self):
print("Age is : " + str(self.age))
def show_salary(self):
print(f"Salary of {self.name} is : " + str(self.salary))
st = Student(name='John', age=25, salary=15000)
st2 = Student(name='Doe', age=25, salary=1500000)
st.show_salary()
st2.show_salary()
If you want to pass these arguments by position, you should use *args instead.
kwargs is created as a dictionary inside the scope of the function. You need to pass a keyword which uses them as keys in the dictionary. (Try running the print statement below)
class Student:
def __init__(self, **kwargs):
#print(kwargs)
self.name = kwargs["name"]
self.age = kwargs["age"]
self.salary = kwargs["salary"]
def show_name(self):
print("Name is : " + self.name)
def show_age(self):
print("Age is : " + str(self.age))
def show_salary(self):
print(f"Salary of {self.name} is : " + str(self.salary))
st = Student(name = 'John',age = 25, salary = 15000)
st2 = Student(name = 'Doe',age = 25,salary = 1500000)
st.show_salary()
st2.show_salary()
Though you can do this as some of the answers here have shown, this is not really a great idea (at least not for the code you are showing here). So I am not going to answer the subject line question you have asked, but show you what the code you seem to be trying to write should be doing (and that is not using kwargs). There are plenty of places where using kwargs is the best solution to a coding problem, but the constructor of a class is usually not one of those. This is attempting to be teaching, not preaching. I just do not want others coming along later, seeing this question and thinking this is a good idea for a constructor.
The constructor for your class, the __init__(), generally should be defining the parameters that it needs and expects to set up the class. It is unlikely that you really want it to take an arbitrary dictionary to use as its parameter list. It would be relatively rare that this is actually what you want in your constructor, especially when there is no inheritance involved that might suggest you do not know what the parameters are for some reason.
In your __init__() itself you clearly want the parameters name, age and salary, yet without them in the parameter list it is not clear to the caller that you do. Also, your usage of it does not seem to imply that is how you expect to use it. You call it like this:
st = Student('John',25,15000)
and so you do not even seem to want named parameters.
To handle the call structure you have shown the __init__() would look like this:
def __init__(self, name, age, salary):
self.name = name
self.age = age
self.salary = salary
If you want to be be able to call it without some parameters such that it uses defaults for the ones left out, then it should be like this:
def __init__(self, name=None, age=None, salary=None):
self.name = name
self.age = age
self.salary = salary
It seems very unlikely that the kwargs approach is really what you want here, though obviously you can code it that way as other answers have shown.
Perhaps you are just trying to figure out how to use kwargs, and that is fine, but a different example would be better if that is the case.
I'm new here, and new in Python. I had some C/C++ in colleague. I'm doing course from udemy and I'm wonderig if there is some better idea of the issiue of finding element of an array of class object based on one value. The course task was to find "the oldest cat". Solution there is just using no Lists/arrays but I wanna know how to operate on arrays of objects and if there is better option than my static method getoldest, becouse for me it seems like I'm trying to "cheat" python.
class Cat:
def getoldest(Cat=[]):
age_table=[]
for one in Cat:
age_table.append(one.age)
return Cat[age_table.index(max(age_table))]
def __init__(self, name, age):
self.name = name
self.age = age
# 1 Instantiate the Cat object with few cats
kotki3=[]
kotki3.append(Cat("zimka", 5))
kotki3.append(Cat("korek", 9))
kotki3.append(Cat("oczko", 10))
kotki3.append(Cat("kotek", 1))
kotki3.append(Cat("edward", 4))
# 2 Create a function that finds the oldest cat
oldest = Cat.getoldest(kotki3)
# 3 Print out: "The oldest cat is x years old.". x will be the oldest cat age by using the function in #2
print(f'The oldest cat is {oldest.name} and it\'s {oldest.age} years old')
Thanks a lot.
I think this example could help you see a better way of doing that
class Cat:
def __init__(self, name, age):
self.name = name
self.age = age
def get_details(self):
return self.name, self.age
cats = [Cat("zimka", 5),
Cat("oczko", 10),
Cat("kotek", 1),
Cat("edward", 4) ]
results = []
for cat in cats:
(name, age) = cat.get_details()
results.append((name,age))
print(sorted(results, key = lambda x: -x[1]))
You can use the #classmethod thus the function will be static and will get the class as a first argument default, as well the _Instances variable made static here.
When a new Cat is instantiated it will be added to the _Instances list.
class Cat:
_Instances=[]
#classmethod
def getoldest(cls):
_Instance = max(cls._Instances,key=lambda Instance: Instance.age)
return ("Oldest {} is {}, and {} years old.".format(cls.__name__,_Instance.name,_Instance.age))
def __init__(self, name, age):
self.name = name
self.age = age
self.__class__._Instances.append(self)
Cat("a",1)
Cat("b",2)
Cat("c",3)
Cat("d",4)
print(Cat.getoldest())
I am a beginner in python and I am having trouble understanding classes. I have a task that requires me to create a class that should return a students information e.g. name, id, age and marks. I have made a class but am having trouble with the output and keep on getting an attribute error:
print("Student: " + self.name + " ID: " + self.ID + " Age: " + self.age + " Mark: " + self.mark)
AttributeError: 'Student' object has no attribute 'age'
I was wondering if someone could explain what I am doing wrong here as I am quite lost.
Rest of the code:
import random
class Student:
def __init__(self, name, ID):
self.name = name
self.ID = ID
def setAge(self, age):
self.age = age
self.age = random.randint(0, 100)
def setMarks(self, marks):
self.marks = marks
self.marks = random.randint(0, 100)
def Display(self):
print("Student: " + self.name + " ID: " + self.ID + " Age: " + self.age + " Mark: " + self.mark)
student = Student("John", "ID123")
student.Display()
You didn't call student.setMarks() and student.setAge() , so marks and age attributes are not created in object yet.
The solution is to call these two methods before calling student.Display()
Python objects are a container that has attributes you can set. If you don't set an attribute but try to read it, you get an AttributeError, meaning that the attribute you are looking for does not exist.
Currently, student = Student(...) calls Student.__init__, which assigns the name and ID attribute of the object. You never call student.setAge or student.setMarks, so your object's age and marks attributes are never set and can not be accessed.
It is traditional to assign default values in the __init__ method if you want to generally avoid unexpected crashes like that.
Another thing is that rather having getter and setter methods, as Java would, for example, Python encourages the use of properties. Properties are objects in the class template that can be accessed like a normal attribute, but allow you to run arbitrary code in place of the access and assignment operators.
Putting all that together, you could write something like
class Student:
def __init__(self, name, ID, age=None, marks=None):
self.name = name
self.ID = ID
self.age = random.randint(0, 100) if age is None else age
self.marks = random.randint(0, 100) if marks is None else marks
#property
def marks(self):
return self._marks
#marks.setter
def marks(self, value):
# Example of a check you could do
if not isinstance(value, int):
raise TypeError('Marks must be an integer')
In your example, you try to access the variable, before the assignment. You would actually have to call student.setAge and student.setMarks with arguments.
On the other note, in your function setAge you instantly overwrite the value, so consider removing either first or second assignment:
def setAge(self, age):
self.age = age # first assignment
self.age = random.randint(0, 100) # second assignment
The age attribute is not set because it was never assigned:
student = Student("John", "ID123")
student.setAge(30) # John is 30 years old.
student.Display()
def __init__() works like a constructor. Try to include age attribute inside the __init__() function, call setAge() from __init__(), or setAge() explicitly before calling Display().
Good luck :)
A simpler version for your code:
import random
class Student:
def __init__(self, name, ID):
self.name = name
self.ID = ID
self.age = random.randint(0, 100)
self.marks = random.randint(0, 100)
def Display(self):
print("Student: " + str(self.name) + " ID: " + str(self.ID) + " Age: " + str(self.age) + " Mark: " + str(self.marks))
student = Student("John", "ID123")
student.Display()
This question already has answers here:
Inheritance of private and protected methods in Python
(6 answers)
Closed 6 years ago.
When inheriting in python, i got following error with private variables:
AttributeError: 'dog' object has no attribute '_dog__name'
I searched a lot but didn't understand where my problem is;
class animal(object):
__name = ""
__height = ""
__weight = ""
__sound = ""
def __init__(self, name, height, weight, sound):
self.__name = name
self.__height = height
self.__weight = weight
self.__sound = sound
def toString(self):
return "{} is {} cm and {} weight and say {}.".format(self.__name, self.__height, self.__weight, self.__sound)
class dog(animal):
__owner = ""
def __init__(self, name, height, weight, sound, owner):
self.__owner = owner
super(dog, self).__init__(name, height, weight, sound)
def toString(self):
return "{} is {} cm and {} weight and say {} and belongs to {}.".format(self.__name, self.__height,
self.__weight, self.__sound,
self.__owner)
puppy = dog('puppy', 45, 15, 'bark', 'alex')
puppy.toString()
when you create var with double underscore, its just a notation use to indicate it as private variable, python do name mangling on the variable name itself to prevent normal way access to it.
However, its still not the real private variable like C/C++. You can still access the so called python "private var" with syntax below
var = __myvar
# access with _<class name>__myvar
From PEP,
_single_leading_underscore : weak "internal use" indicator. E.g. from M import * does not import objects whose name starts with an
underscore.
__double_leading_underscore : when naming a class attribute, invokes name mangling (inside class FooBar, __boo becomes _FooBar__boo
For your case, change your dog class toString method to below then it should works
def toString(self):
return "{} is {} cm and {} weight and say {} and belongs to {}.".format(self._animal__name, self._animal__height,
self._animal__weight, self._animal__sound,
self.__owner) # __owner remains because its not inherit from class animal
another option is to change your animal class variable to single underscore _ if you don't really need double underscore __
I have written some python code:
class key(object):
def __init__(self,name):
object.__init__(self,age)
this.name = name
this.age = age
def somefunction(self):
print "yay the name is %d" % self.name
baby = key('radan',20)
baby.somefunction()
When I create an instance of key with baby = key('radan',20), I got a TypeError. I don't know why I am getting this error. Is it because of object.__init__(self,age)?
If yes, please help me in explaining why we use object.__init__(self,age) and what the purpose of that is and help me solve this code.
Some pointers:
class Key(object): # in Python, classes are usually named with a starting capital
def __init__(self, name, age): # name all your arguments beside self
self.name = name # use self.name, not this.name
self.age = age
def somefunction(self):
print "yay the name is %s" % self.name
baby = Key('radan',20)
baby.somefunction()
# output: yay the name is radan
Actually, you can can name the self instance parameter whatever you like in Python (even this), but it makes the code harder to read for other people, so just use self.
You don't have to use object.__init__(self, name, age) here. If you remove that line and implement the changes above, your code will work just fine.
Your code contains several errors:
class key(object):
def __init__(self, name, age): # where's your age?
self.name = name # no need to call object.__init__
self.age = age # there is no such thing called "this", use self
def somefunction(self):
print "yay the name is %s" % self.name # use %s as the comment says
baby = key('radan', 20)
baby.somefunction()
output:
>>> baby = key('radan', 20)
>>> baby.somefunction()
yay the name is radan
When you do baby = key('radar', 20) you are actually passing three arguments: the instance, the name and the age. However your initialiser is defined to take exactly two arguments so you get a TypeError.
self is the argument implicitly passed when referring to an instance of an object.
For your __init__ function, I would just do:
def __init__(self, name, age):
self.name = name
self.age = age
So we can assign the arguments passed as attributes to the current instance, conventionally called self.
It makes no sense here to call object.__init__ at all, just remove that line.
Apart from that, everything works fine (except use %s instead of %d).
Testing:
>>> baby = key('radan', 20)
>>> baby.somefunction()
yay the name is radan