Error importing class to another file with python - python

I am learning python at the moment
the task is this;
Write a program that reads pet information (name, type and age) from a file (called animals.txt) and creates Pet objects (using the information stored in the animals.txt file). Store Pet objects in a list called animals.
animal.txt
ralph, dog, 3
buster, cat, 8
sammy, bird, 5
mac, dog, 1
coco, cat, 6
My class file i created is called
pet.py
class Pet:
# The __init__ method initializes the data attributes of the Profile class
def __init__(self, name ='', animal_type = '', age = ''):
self.__name = name
self.__animal_type = animal_type
self.age = 0
def __str__(self):
string = self.__name + ' ' + self.__animal_type + ' ' + self.age
return string
def set_name(self, name):
self.__name = name
def get_name(self):
return self.__name
def set_animal_type(self, breed):
self.__animal_type = breed
def get_animal_type(self):
return self.__animal_type
def set_age(self, old):
self.age = old
def get_age(self):
return self.age
I then want to use this class in a file
animals.py
import pet
animals = [] // create a list
infile = open("animals.txt", "r") // open the file
lines = infile.readlines() // read all lines into list
## add each pet object
for line in lines:
data = line.split(",")
animals.append(pet.set_name(data[0]))
animals.append(pet.set_animal_type(data[1]))
animals.append(pet.set_age(data[2]))
infile.close()
I am getting an error
pet.set_name [pylint] E1101 : module 'pet' has no 'set_name' member.
If i do this code below in the class file pet.py I don't get the error
pet = Pet()
name = "thing"
breed = "dog"
pet.set_name(name)
pet.set_animal_type(breed)
pet.set_age(10)
print(pet)
and it returns as expected
thing dog 10
Why wont the animals.py file allow me to use the class i have imported?
I have tried pet=Pet() but it has
error E0602: undefined variable 'Pet'

In your animals.py file pet represents a module. You need to extract the class located within that module like this:
import pet
myPet = pet.Pet()

Right now you're importing the entire pet module's contents. You can gain access to the Pet class in one of two ways.
The first requires you to use the object's entire dotted path
import pet
pet.Pet(...)
The second requires you to import the Pet class
from pet import Pet
Pet(...)
One gotcha here is that depending on your folder structure, Python may not be able to identify your file as importable, so you may need to create a blank file named __init__.py at the same position in your directory structure as pet.py.

Related

Can method operating on array of class object use array methods?

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())

Python3 Class method inputs; clean solution

I'am using more class based programs, however in some cases it's not handy to provide all self.paramets into a class.
In those cases I want to use a regular input into a function in a class. I figured out a way to achieve both inputs, let me show this in following script:
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def myfunc(a):
if (type(a) == str):
name = a
else:
name = a.name
print("Hello my name is " + name)
p1 = Person("John", 36)
p1.myfunc()
print("---------------------")
Person.myfunc("Harry")
Output:
Hello my name is John
---------------------
Hello my name is Harry
First, the name is initialized by the classes self.params.
Second, the name is provided in the method within the class as a string.
So a type check is necessary.
However I don't think this is a clean approach, because when I have >30 methods I need to implement these type checks again, including upcoming type-error results.
Does anyone know a better approach?
The simplest solution is to implement a __str__ method for your class. This method will be called whenever something tries to convert an instance of the class to a string.
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def __str__(self):
return self.name
p = Person('Jane', 25)
print('Hello', p)
'Hello Jane'

How to assign from input to object from a class

I have multiple classes and I have instances from each class e.g: Student class. every instance (a student) has their own courses. Now when a user signs in (by input) I want to print their list of courses. Or even just their age to show that I have the correct object.
Is there a better way than eval() to get an object from class based on input
like the following example:
class Student:
def __init__(self, name, age):
self._name = name
self._age = age
blablue = Student('bla blue', '23')
name = input('enter your name')
name = name.split(' ')
stundent = eval(name[0] + name[1])
print(student)
print(student.age)
output:
enter your name: bla blue
<__main__.Foo object at 0x000001B2978C73C8>
23
I assume this is for educational purpose (production code would use a SQL database and some ORM):
try:
# python 2.x
input = raw_input
except NameError:
# python 3.x
pass
class AlreadyExists(ValueError):
pass
class DoesNotExist(LookupError):
pass
class FooCollection(object):
def __init__(self):
self._foos = {}
def add(self, foo):
if foo.name in self._foos:
raise AlreadyExists("Foo with name '{}' already exists".format(foo.name))
self.update(foo)
def update(self, foo):
self._foos[foo.name] = foo
def get(self, name):
try:
return self._foos[name]
except KeyError:
raise DoesNotExist("no Foo named '{}'".format(name))
class Foo(object):
def __init__(self, name, age):
self._name = name
self._age = age
# we at least need to be able to read the name
#property
def name(self):
return self._name
def __repr__(self):
return "Foo({}, {})".format(self._name, self._age)
def main():
foos = FooCollection()
blablue = Foo('bla blue', '23')
foos.add(blablue)
name = input('enter your name: ').strip()
try:
print("found {}".format(foos.get(name)))
except DoesNotExist as e:
print(e)
if ___name__ == "__main__":
main()
The principle here is to have a storage for your instances. I chose a dict for fast lookup with the Foo.name as key, in real life you'd probably want an opaque unique identifier for each instance and multiple indexes (i.e. one by id, one by name etc) - but actually in real life you would use a SQL database that already provide all those features in a much more optimized way ;-)
Also, I wrapped the dict in a dedicated class with its own interface. This allows to decouple the interface from the implementation (if you later decide you want more indexes than just name for example), and encapsulate domain logic too (i.e. checking you don't accidentally overwrite an existing Foo).

Python 3.x error with methods asking for input error is TypeError: __init__() takes 0 positional arguments but 1 was given

I'm attempting utilizing TeamTreehouse learning subscription & this Starting Out With Programming Logic And Design (3rd Ed) book to attempt learning programming & Python. Please don't shoot to kill me I'm learning.
Goal: I'm attempting to set a Pet class with 3 fields/attributes/properties. The class will have 2 methods, set & get, for each field/attribute/property. I'm trying to figure out how to get each method (which is still a function at it's roots) to ask user's for input to then set the internal attributes to the input values.
Researching & Troubleshooting: I can get it to run error free when I don't ask users to input data as part of class methods. http://repl.it/oIr/3
I've referred to a "cheat sheet" for what OOP could look like. http://www.newthinktank.com/2014/11/python-programming/
Here is a doc that I flipped through that appears to be a 2.x python version reference on OOP though it didn't do much for relieving or causing a change on my headache.
I found this document right before posting which is starting to make sense of my cloudy head. Likely I need to clean/scrub all my passing by value/reference coding then rewrite?
How to get user input within a Method (python)
Error:
Traceback (most recent call last):
File "python", line 43, in <module>
TypeError: __init__() takes 0 positional arguments but 1 was given
CODE:
http://repl.it/oIr/5
# Create class for Pet
class Pet:
__name = ""
__species = ""
__age = ""
# Object constructor
def __init__():
self.__name = name
self.__species = species
self.__age = age
#Methods
def setName(self):
self.__name =input("What is your pet's name?\n")
def setSpecies(self, species):
self.__species=input("What type of pet is it?\n")
def setAge(self, age):
self.__age=input("How old is your pet?\n")
def getName(self):
return self.__name
def getSpecies(self):
return self.__species
def getAge(self):
return self.__age
def get_type(self):
print("Pet")
def toString(self):
return"{} is a {} and is {} years old".format(self.__name,self.__species,self.__age)
#name=input("What is your pet's name?\n")
#species=input("What type of pet is it?\n")
#age=input("How old is your pet?\n")
myPet=Pet()
myPet.setName()
#myPet=Pet(name,species,age)
print(myPet.toString())
All methods in Python take a self argument. Your __init__ method doesn't:
def __init__():
but Python is still trying to supply one:
TypeError: __init__() takes 0 positional arguments but 1 was given
Add the self argument:
def __init__(self):
Your next problem is that your __init__ method expects the variables name, species and age to be available, but you never set those:
def __init__(self):
self.__name = name
self.__species = species
self.__age = age
Perhaps you meant to make those method arguments:
def __init__(self, name, species, age):
self.__name = name
self.__species = species
self.__age = age
which means you can only create a new Pet() instance by including those values:
name = input("What is your pet's name?\n")
species = input("What type of pet is it?\n")
age = input("How old is your pet?\n")
myPet = Pet(name, species, age)

Object with __init__ in python

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

Categories

Resources