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())
Related
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'
I'm completely new to Python so I may not be asking this in the right way and I have tried to find an answer (unsuccessfully, obviously).
I am trying to set up a class and then to find all instances of the class that meet a certain criterion. I don't know if a class is the right way to go about this so open to all advice (even if it takes me away from classes).
For a simple example (see code below) if I wanted to find all Employee's who are over 30 would the right approach be to make a class method? In reality you'd have DOB rather than age but for simplicity I've gone with age. I'd also want some sort of variable so that I could change 30 to let's say 50.
class Employee:
def __init__(self, name, age):
self.name = name
self.age = age
e1 = Employee("John", 36)
e2 = Employee("Sally", 21)
e3 = Employee("Jamie", 53)
What is the "right" way or efficient way to achieve this? For this example above for ages above 30 I'd want the e1 and e3 instances. Any help would be appreciated!
You would typically have your instances in some sort of collection like a list rather than individual variables. You could then filter your list or use a list comprehension to get the elements in the list you want. Here's an example with a list comprehension:
class Employee:
def __init__(self, name, age):
self.name = name
self.age = age
employees = [
Employee("John", 36),
Employee("Sally", 21),
Employee("Jamie", 53)
]
over_thirty = [e for e in employees if e.age > 30]
for e in over_thirty:
print(e.name)
prints:
John
Jamie
You can avoid the extra list over_thirty and iterate directly over the filter results for the same result:
for e in filter(lambda e: e.age > 30, employees):
print(e.name)
Or also modify the class:
class Employee:
def __init__(self, name, age):
self.name = name
self.age = age
self.age_over_30 = self.age > 30
l = [Employee("John", 36), Employee("Sally", 21), Employee("Jamie", 53)]
print([i.name for i in l if i.age_over_30])
Or if you would modify the age attribute, make the class:
class Employee:
def __init__(self, name, age):
self.name = name
self.age = age
#property
def age_over_30(self):
return self.age > 30
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).
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.
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