Can I ask the attributes of a class in a sub-definition? - python

Merry Christmas!
I was trying to generate some code which would make a sort of database using the information provided by the user.
Can I use input() method to define my instance variables?
class Compound:
def __init__(self, name, state, molecular_mass, concentration, concentration_measure):
self.nome = name
self.state = state
self.mol_mass = molecular_mass
self.conc = concentration
self.measure = concentration_measure
def summary(self):
return ('Your compound is {} it has a state of {} it has a molecular mass of {} g/mol and a concentration of {} and a measure of {}'
.format(self.name, self.state, self.mol_mass, self.conc, self.measure))
def ask_compounds():
self.nome = input("Name?")
self.state = input('Solid or Liquid')
self.mas_mol = input('Absolute number for molecular weight?')
self.conc = input('Concentration?')
self.measure = str(input('In M? In g/ml?'))
ask_compounds()
Thank you for your help!

Of course you can. Either return the inputted values and initialize a Compound class with them:
def ask_compounds():
nome = input("Name?")
state = input('Solid or Liquid')
mas_mol = input('Absolute number for molecular weight?')
conc = input('Concentration?')
measure = input('In M? In g/ml?')
return nome, state, mas_mol, conc, measure
inst = Compound(*ask_compounds())
or, even better, make ask_compounds a classmethod that creates instances for you:
class Compound:
def __init__(self, name, state, molecular_mass, concentration, concentration_measure):
# snipped for brevity
def summary(self):
# snipped for brevity
#classmethod
def ask_compounds(cls):
nome = input("Name?")
state = input('Solid or Liquid')
mas_mol = input('Absolute number for molecular weight?')
conc = input('Concentration?')
measure = input('In M? In g/ml?')
return cls(nome, state, mas_mol, conc, measure)
inst = Compound.ask_compounds()
As an aside, you're using nome in __init__ and ask_components but name in summary, change one of the two to the other.

Related

How to print my class and not get memory reference

I have a class called Pension, with attributes like a person's name, age, savings and a growth rate.
I have a class method which calculates the person's total savings at retirement year.
Under my main function, I want to print the class to see if my code is working as intended, but I don't know how to do as I only get the memory reference when printing.
How can I print the class instance, so that it goes through all its attributes and runs the function result, and prints the result? Worth to note; to run the function 'result' which calculates the total pension, the growth rate is user inputted and in a function of its own (and is run in main())
For example, if I try to print the 2nd last line: print(pensions) I only get the memory reference. So in this case, if a person (the data for which I read in from a file) has saved up 1000 dollars (using my result method), I would like that fact to be printed into a list.
This is my code:
class Pension:
def __init__(self, name,age,savings,growth):
self.name = name
self.age = age
self.savings = savings
self.growth = growth
def result(self):
amount=self.savings
rate=1+(self.growth/100)
years=65-self.age
return (amount * (1 - pow(rate, years))) / (1 - rate)
def convert(elem: str):
if not elem.isdigit():
return elem
return float(elem)
def convert_row(r: list) -> list:
return [convert(e) for e in r]
def get_growth(msg: str = "Enter growth rate: "):
return float((input(msg).strip()))
def main():
with open('personer.txt') as f:
raw_data = f.readlines()
data = [row.split("/") for row in raw_data]
data = [convert_row(row) for row in data]
pensions = [Pension(*i, get_growth()) for i in data]
main()
From the Pension class object's perspective it doesn't actually matter how is the growth provided. Also in this case maybe it's worth to make the result a property, then there's no need to call it as a function (just access like any other property, but the values will be calculated "dynamically").
You can customize the __str__ method to return any str representation of your object.
class Pension:
def __init__(self, name,age,savings,growth):
self.name = name
self.age = age
self.savings = savings
self.growth = growth
self._result = result
#property
def result(self):
amount=self.savings
rate=1+(self.growth/100)
years=65-self.age
return (amount * (1 - pow(rate, years))) / (1 - rate)
def __str__(self):
return f"Pension:\n{self.amount=}\n{self.age=}\n{self.savings}\n{self.growth=}\n{self.result}"
And then just:
for p in pensions:
print(p)

How to use __str__ function to return a string representation of a class

I have been tasked with creating an inventory manager in python, and one of the required is to define the following function within the class:
__str__ - This function returns a string representation of a
class.
The class refers to a file (inventory.txt) which has the following format:
Country,Code,Product,Cost,Quantity
my code thus far is as follows:
# Creating the class:
class Shoes():
# Constructor:
def __init__(self,country,code,product,cost,quantity):
self.country = country
self.code = code
self.product = product
self.cost = cost
self.quantity = quantity
# Methods:
def get_cost():
inventory = open('inventory.txt','r')
inventory_list = inventory.readlines()
code = input("What is the code of the product:")
for line in inventory_list:
split_lines = line.split(",")
if code == split_lines[1]:
print("This product costs R{}".format(split_lines[3]))
inventory.close()
def get_quantity():
inventory = open('inventory.txt','r')
inventory_list = inventory.readlines()
code = input("What is the code of the product:")
for line in inventory_list:
split_lines = line.split(",")
if code == split_lines[1]:
print("There are {} units in inventory".format(split_lines[4]))
inventory.close()
def __str__(self):
pass
I haven't come across the str so I really am not sure how it works, and how to use it. Any advice would be greatly appreciated.
Here is an example:
def __str__(self):
return f'{self.self.country},{self.self.code},{self.self.product}, {self.cost},{self.quantity })'
This way, when you assign values to a class, you can print its string representation
print(new_shoe)
More info here
https://www.pythontutorial.net/python-oop/python-str/

How do you get value from another class?

I am starting to learn about object-oriented programming and I'm having a rough time with it.
I have some questions about it:
class Record:
"""Represent a record."""
def __init__(self, category, name, value):
self._category = category
self._name = name
self._value = value
# 1. Define the formal parameters so that a Record can be instantiated
# by calling Record('meal', 'breakfast', -50).
# 2. Initialize the attributes from the parameters. The attribute
# names should start with an underscore (e.g. self._amount)
#property
def amount (self):
return self._value
# Define getter methods for each attribute with #property decorator.
# Example usage:
# >>> record = Record('meal', 'breakfast', -50)
# >>> record.amount
# -50
class Records:
"""Maintain a list of all the 'Record's and the initial amount of money."""
def __init__(self):
# 1. Read from 'records.txt' or prompt for initial amount of money.
# 2. Initialize the attributes (self._records and self._initial_money)
# from the file or user input.
self._records =[]
self._money = 0
fh = open(file='records.txt', mode='r')
if ',' not in i:
self._money = int(i.strip())
else:
raw_line = i.strip()
category, activity, value = raw_line.split(',')
x = Record(category, activity, value)
self._records.append(x)
print("Welcome back!")
fh.close()
#property
def view(self):
for i in self._records:
print(Record._category)
#1. Print all the records and report the balance.
x = Records()
Records.view()
I wanted to print out value from my newly acquired list but I don't know how to pass my data from class Records to class Record for processing. How should I approach this?

How to write in a csv file and know that a rental is active?

I have to do a basic program for vehicle rent.
I have a class Aluguer that receives the following atrributes:
start of renting
nickname of user
vehicle name
hourly price for rental
import time
now = time.time()
class Aluguer:
def __init__(self, inicio, nickname, nome, preco_base):
self.__inicio = inicio
self.__nickname = nickname
self.__nome = nome
self.__preco_base = preco_base
#property
def inicio(self):
self.__inicio = now
return self.__inicio
#property
def nickname(self):
return self.__nickname
#property
def nome(self):
return self.__nome
#property
def preco_base(self):
return self.__preco_base
To calculate the initial time of renting can I just do what I just did at:
#property
def inicio(self):
self.__inicio = now
return self.__inicio
Then, I have to do an update method that adds or updates (if they already exist) two new attributes to the Aluguer object: elapsed time and price.
I had written the following:
def update(self):
tempo_fim = time.time()
elapsed_seconds = tempo_fim - self.__inicio
price = self.__preco_base
valor = (elapsed_seconds / 3600) * price
When the user returns the vehicle, the update method will be executed and the information will be written in a csv file. After the registry in the file, the object will be deleted from the memory system.
How can I do it and how can I know if a rental is active?
As it looks like a long living process, I would use a structure as such:
import csv
import Aluguer
class Rentals:
def __init__(self):
self.rentals = {}
def start_rental(self, inicio, nickname, nome, preco_base):
new_rental = Aluguer(inicio, nickname, nome, preco_base, rental_id)
rental_id = str(id(new_rental))
self.rentals[rental_id] = new_rental
rental.inicio()
return rental_id
def return_rental(self, rental_id):
rental = self.rentals[rental_id]
rental.update()
file_name = "Dummy.csv"
with open(file_name, 'w') as f:
writer = csv.DictWriter(f, fieldnames=rental.__dict__.keys())
writer.writeheader()
for data in rental.__dict__:
writer.writerow(data)
You define a class rentals that holds all active rentals with a start_rental function that defines the rental and initializes it, and a return_rental function that updates it and writes it to csv. Therefore all active ones are the ones in the rentals.rentals list.
**Code above not functional and complete, just indicator

Class instances overwrite attributes

I've written a class in Python for calculations, it looks like:
default = {…}
class Case(object):
def __init__(self, name, wt, wd, ft, bc, burnup, cr_state):
self.name = name
self.burnup = burnup
self.infn = 'fa-'+faType+'-'+str(self.burnup)+'-'+self.name
self.data = default
self.data['caseName'] = name
self.data['water-temp'] = str(wt)
self.data['water-den'] = str(wd)
self.data['fuel-temp'] = str(ft)
self.data['boron-con'] = str(bc)
self.cr_state = cr_state
self.data['cr_state'] = cr_state
self.data['burnup'] = str(burnup)
Actually it implements more methods, but this should be enough just to illustrate.
The problem is that when I'm trying to create different instances of this class they turn out to have same attributes, like:
basis = Case('basis', 578.0, 0.71614, 578.0, 0.00105, 0, 'empty')
wt450 = Case('wt450', 450.0, 0.71614, 578.0, 0.00105, 0, 'empty')
and after this if I check:
print basis.data == wt450.data
it returns True. Where can the root of the problem be?
Like the comment from jonrsharpe states, you could copy the content of the default dict with the `dict.copy method.
class Case(object):
def __init__(self, name, wt, wd, ft, bc, burnup, cr_state):
self.name = name
self.burnup = burnup
self.infn = 'fa-'+faType+'-'+str(self.burnup)+'-'+self.name
# Copy the content of the dict
self.data = default.copy()
# Overwrite data's default values
self.data['caseName'] = name
self.data['water-temp'] = str(wt)
self.data['water-den'] = str(wd)
self.data['fuel-temp'] = str(ft)
self.data['boron-con'] = str(bc)
self.cr_state = cr_state
self.data['cr_state'] = cr_state
self.data['burnup'] = str(burnup)
Or, if you want to keep the values synchronized with the default ones, you could create a method that would take the value from the instance and if it can't find the value, then use the one on the default dict. It would look something like this:
class Case(object):
def __init__(self, name, wt, wd, ft, bc, burnup, cr_state):
self.name = name
self.burnup = burnup
self.infn = 'fa-'+faType+'-'+str(self.burnup)+'-'+self.name
# We create a NEW dictionary to hold the overwritten values
self.data = {}
# Write data to OUR OWN dict
self.data['caseName'] = name
self.data['water-temp'] = str(wt)
self.data['water-den'] = str(wd)
self.data['fuel-temp'] = str(ft)
self.data['boron-con'] = str(bc)
self.cr_state = cr_state
self.data['cr_state'] = cr_state
self.data['burnup'] = str(burnup)
def property(name):
"""
Return the value of `name`, if name wasn't defined, then use the
value from default.
"""
# Return the property from our own dict. If it can't find the property
# then get it from the default dict. If the property doesn't exists
# returns None.
return self.data.get(name, default.get(name))
# Then
print basis.property('caseName') == wt450.property('caseName')
> False

Categories