So I keep getting the
error: " AttributeError: 'Dog' object has no attribute '_Dog__name'"
The thing is print(spot.get_name()) works fine. Also when I tried spot.multiple_sounds() that fails similarly. I think the issue is when I try to call object attributes from the super class in functions in object definition. I can't understand why though. I'm doing all this from a tutorial and the code is identical to his. I think it may be because he's using python2.x and I'm using spyder python3.x but I have no idea. Any help is greatly appreciated.
import random
import os
import sys
class Animal:
__name = ""
__height = 0
__weight = 0
__sound = 0
def __init__(self,name,height,weight,sound):
self.__name = name
self.__height = height
self.__weight = weight
self.__sound = sound
def set_name(self, name):
self.__name = name
def get_name(self):
return(self.__name)
def set_height(self, height):
self.__height = height
def get_height(self):
return(self.__height)
def set_weight(self, weight):
self.__weight = weight
def get_weight(self):
return(self.__weight)
def set_sound(self, sound):
self.__sound = sound
def get_sound(self):
return(self.__sound)
def get_type(self):
print("animal")
def toString(self):
return("{} is {} cm tall and {} kilograms and says {}".format(self.__name,
self.__height,
self.__weight,
self.__sound))
cat = Animal('Whiskers', 33, 10,'Meow')
print(cat.toString())
class Dog(Animal):
__owner = ""
def __init__(self, name, height, weight, sound, owner):
self.__owner = owner
super().__init__(name, height, weight, sound)
def set_owner(self,owner):
self.__owner = owner
def get_owner(self):
return self.__owner
def get_type(self):
print("Dog")
def toString(self):
return "{} is {} cm tall and {} kilograms says {} and his owner is {}".format(self.__name, self.__height, self.__weight, self.__sound, self.__owner)
def multiple_sounds(self, how_many=None):
if how_many is None:
print(self.getsound())
else:
print(self.getsound()*how_many)
spot = Dog("Spot", 53, 27, "Ruff", "Some Guy")
print(spot.get_name())
print(spot.toString())
In python, __fieldName emulates the private field, means two underscores that in field name. So such fields can not be reached from derived classes, but you still can get them using getter.
Any attribute or method that begins with '__' is only accessible by that name from functions in that same class. Not from other classes, not even from subclasses.
class A:
def __init__(self, name):
self.__name = name
def get_name(self):
return self.__name
class B(A):
def get_name_capitalized(self):
return self.__name.upper()
b = B('Bob')
print(b.get_name()) # prints 'Bob'
print(b.get_name_capitalized()) # fails
In the code above, calling A.get_name() accesses the A instance's __name attribute successfully. But B.get_name_capitalized() fails with the error "AttributeError: 'B' object has no attribute '_B__name'
". "__" names get mangled by the compiler so that they are not accessible as-is. If the code in get_name_capitalized is changed to:
return self._A__name.upper()
then it would work, so these attributes are accessible, but you have to use the mangled name to get at them.
That is how Python has been since 1.x, and is nothing new with Python 3.
Names that begin with double-underscores and end with zero or 1 underscore are python's answer to private variables. Python munges them to be __Class_name to make them private to the class and not its inherited subclasses. The idea is to let you have intra-class names without subclasses messing with them. Obviously this is easily subverted by using the well-known munged name, but then, python is a dynamic language.
See Private Variables
Related
In my program I have the following question. How can I define a method in the class 'Mouse' 'Keyboard' and 'Screen' so that they return the room and the computer they belong to + the associated attribute of the class (so for the keyboard class this would be: 'The computer {} is located in the room {} and has the language {} ') Can someone tell me how I can define such a method for these 3 classes without changing the program itself? The method should be defined for each class seperated. The exact task is "Extend the output of maus, screen and tastatur so that the user knows which computer in which room they belong".
I've tried to define the following method:
def as_text(self):
return "{} an {} in {}".format(self.__name, self.__computer, self.__computer.__room)
In my three classes I have build in a reference to computer. My Class Computer has a reference to room, so I've tried to call it with self.__computer.__room but that doesn't work and I'm not sure how to call this attribute.
Here is my code:
class Room:
__name = "unknown"
def __init__(self, name):
self.__name = name
def get_name(self):
return self.__name
class Device:
__name = "Device"
def __init__(self, name):
self.__name = name
def as_text(self):
return "%s" % (self.__name)
class Computer(Device):
__ip = "unknown"
def __init__(self, name, ip, room):
super().__init__(name)
self.__ip = ip
self.__room = room
def as_text(self):
return "%s with ip=%s" % (super().as_text(), self.__ip)
class Laptop(Computer):
def __init__(self, name, room, ip, with_case = True):
super().__init__(name, room, ip)
self.__with_case = with_case
def as_text(self):
if (self.__with_case):
return "%s with case" % super().as_text()
else:
return super().as_text()
class Screen(Device):
__width = "1920"
__height = "1080"
def __init__(self, name, width, height, computer):
super().__init__(name)
self.__width = width
self.__height = height
self.__computer = computer
def as_text(self):
return "{} an {}".format(self.__name, self.__computer)
class Tastatur(Device):
__language = 'English'
def __init__(self, name, language, computer):
super().__init__(name)
self.__language = language
self.__computer = computer
class Maus(Device):
__type = 'Gaming Mouse'
def __init__(self, name, type, computer):
super().__init__(name)
self.__type = type
self.__computer = computer
Your request is not particularly clear, here what I got.
This is my method for the Screen Class:
def as_text(self):
return "{} an {} in {}".format(super().as_text(), self.__computer.as_text(), self.__computer.display_room())
super().as_text()
This calls the method as_text from the parent class Device.
self.__computer.as_text()
This calls the as_text() method from an instance of the Computer class, which is an attribute of your class Screen.
self.__computer.display_room()
This calls the method display_room() from the Computer class, I created it and returns the Room's name.
def display_room(self):
return self.__room.get_name()
Now you should be able to write methods for Tastur and Maus yourself.
I'm new to python and just trying to test the syntax and get to know it.
The code below works fine except for when I get to inheritance. The final command "toString" function is not working and I can't for the life of me figure out why.
I'm sure I'm not doing something the most efficient way, but even if there's a more efficient way I'd first like to understand why what I'm doing is wrong. thanks a lot. Please let me know if I need to clarify anything
#!/bin/python
class Animal:
__name = ""
__height = 0
__weight = 0
__sound = 0
def __init__(self, name, height, weight, sound):
self.__name = name
self.__height = height
self.__weight = weight
self.__sound = sound
def set_name(self,name):
self.__name = name
def get_name(self):
return self.__name
def set_height(self,height):
self.__height = height
def get_height(self):
return self.__heiight
def set_weight(self,weight):
self.__weight=weight
def get_weight(self):
return self.__weight
def set_sound(self,sound):
self.__sound = sound
def get_sound(self):
return self.__sound
def get_type(self):
print("Animal")
def toString(self):
return("{} is {} inches tall, {} lbs, and says {}".format(self.__name, self.__height,self.__weight,self.__sound))
objCat = Animal('Whiskers', 33, 10, 'Meow')
print (objCat.toString())
# Attempt Inheritance
class cDog(Animal):
__owner=""
def __init__(self,name,height,weight,sound,owner):
self.__owner=owner
Animal.__init__(self,name,height,weight,sound)
def __str__(self):
return ("{}".format(self.__height))
def set_owner(self,owner):
self.__owner=owner
def get_owner(self):
return self.__owner
def get_type(self):
print("Dog")
def toString(self):
return ("{} is {} inches tall, {} lbs, says {}, and is owned by, {}".format(self.__name,self.__height,self.__weight,self.__sound,self.__owner))
objDog = cDog('Brewsky', 20, 75, 'Ruff', 'Jared')
print (objDog.toString())
In your Animal class, the double underscore before the name of the attributes has made them (sort of) private.
Just delete the double underscore (or change it to one underscore, if you want to keep a weak indicator) and it will be fixed.
See this question for more information.
Given that I need to operate a machine, I need a
VendingMachine class:
Property is a stock(list) that stores Food items.
Methods:
Constructor takes in no arguments.
get_stock_names(): returns a list of strings that represents the names of
all food items in the stock.
load(food): adds the Food object to stock
and others,
#predefined
class Food(object):
def __init__(self, name, nutrition, good_until):
self.name = name
self.nutrition = nutrition
self.good_until = good_until
self.age = 0
def get_name(self):
return str(self.name)
def get_age(self):
return self.age
def get_nutrition(self):
if self.age <= self.good_until:
return self.nutrition
else:
return 0
def ripen(self, days):
self.age = self.age + days
return self.age
def is_spoiled(self):
return self.good_until < self.age
#my code below
class VendingMachine:
def __init__(self):
Property = Food.get_name #no clue how to make a Property
self.load = Food.load #same here
def get_stock_names(self, Property):
lst = []
for i in Food:
i = str(i)
lst.append(i)
return lst
def has_stock(self, name):
return name in Property
def load(self, food):
Property.append(food)
return Property
def sell(self, name):
if name in Property:
Property.remove(name)
return name
else:
return None
What I get is
AttributeError: 'VendingMachine' object has no attribute 'load' (a variable)
I'm pretty sure you've misunderstood the line of your instructions telling you about the stock property. I suspect it is just telling you to make an instance variable named self.stock which holds a list of Food instances. Since the constructor takes no arguments, it presumably starts empty. Using the term "property" seems like a red herring, since property has a specific meaning in Python (a wrapper around a method to make it look like an attribute), which doesn't make much sense in this situation.
Anyway, here's what I think you want your constructor to look like:
def VendingMachine(object):
def __init__(self):
self.stock = [] # initially empty
Your later methods can inspect or manipulate self.stock as necessary.
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 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