I am getting <__main__.Money object at 0x0000019A33F6F6A0> when i run the program - python-3.9

class Money:
def __init__(self, value, colour):
self.value = value
self.colour = colour
def color(self):
print(
f"The Money is {self} , Value is {self.value} , Color is {self.colour}")
Dollar = Money(1000, "Green")
Dollar.color()
I am getting the output as "The Money is <main.Money object at 0x0000019A33F6F6A0> , Value is 1000 , Color is Green" . Instead i want the output as "The Money is Dollar , Value is 1000 , Color is Green" . Please help me out

You can't access the variable's name from the class, and if you can, it is bad practice. You can just specify the type in the constructor:
class Money:
def __init__(self, value, colour, currency):
self.value = value
self.colour = colour
self.currency = currency
def color(self):
print(
f"The Money is {self.currency} , Value is {self.value} , Color is {self.colour}")
Dollar = Money(1000, "Green", "Dollar")
Dollar.color()

class Money:
def __init__(self, value, colour):
self.value = value
self.colour = colour
def color(self):
print(f"The Money is {self} , Value is {self.value} , Color is {self.colour}")
def __repr__(self):
return "Dollar"
repr method is used for object representation.

Related

Ruby / cup sorting algorithm wont check if string is an integer

I have (almost) made a cup sorting algorithm that takes colour and radius parameters then spits out the cups names ranked by the radius length. Example input
2
blue 7
10 red
Example output
red
blue
The problem is that I want to create a filter that checks if the first value is a number when split. Then this number is divided by 2 and both values are reversed. I have tried is_a? Integer but get an expecting end of input error in the irb console. I tried == int.
Here is the code:
class Cup
attr_accessor :colour, :radius
def initialize(colour, radius)
#colour = colour
#radius = radius
end
end
cups = []
puts "How many cups are there?"
gets.to_i.times do |n|
puts "Enter Cup-#{n+1} colour & radius:"
value = gets.split " "
if
value.first.to_i == int?
then
value.first / 2
value.reverse
cups << Cup.new(value[0], value[1])
end
cups << Cup.new(value[0], value[1])
end
print cups.colour.sort_by { |cup| cup.radius }
Any other feedback about the algorithm is very much welcomed.
Whatever input is provided by user in console will be string so you can do as below,
puts "How many cups are there?"
gets.to_i.times do |n|
puts "Enter Cup-#{n+1} colour & radius:"
value = gets.chomp.split(" ")
order = Integer(value[0]) rescue false # order will have value if it is proper integer, else false
cups << (order ? Cup.new(value[1], value[0].to_i) : Cup.new(value[0], value[1].to_i))
end
cups.sort_by { |cup| cup.radius }.each { |cup| puts cup.colour } if cups.present?
Use of to_i is not valid here, as it will return 0 for string 'red'
And also it is also assumed user is putting integer for sure, otherwise code will not work as it is supposed to.

Not displaying it's corresponding values with it's key for Hash

Ok i am not here to ask for an answer. But to be honest i am not really good in class variable. So i would appreciate you can guide me along with this piece of code.
I have read on class variable at those docs. I some what kind of understand it. But it comes to applying it for my own use. I would get confused.
class Square
##sqArray = {}
#attr_accessor :length
def initialize
if defined?(##length)
randno = "%s" % [rand(20)]
##length = randno.to_i
##sqArray = ##length
else
randno = "%s" % [rand(20)]
##length = randno.to_i
##sqArray = ##length
end
end
def Area
##area = ##length * ##length
return ##area
##sqArray[##length.to_sym] = ##area
puts ##sqArray
end
end
s1 = Square.new
puts s1.Area
Let me explain this piece of code. Basically every time i create a Square object it would go to initialize method. A random number will be generated and pass it to ##length, and ##length will be assigned to hash ##sqArray as it's key. But now the problem is when i create a new object s1. When i want to display the Area i want to test out to print the hash ##sqArray with it's length as it's key and area as it's value. But now the problem is only returning it's area only. e.g 114 only.
suppose to be e.g [ 24 => 114]
When defining the object's property (i.e. it's length), the correct approach is to use an instance variable, not a class variable. This is because (in your particular example), length is an attribute of a specific square and not something that applies to all squares. Your code should look something like this:
class Square
def initialize(length = rand(20))
#length = length
end
def area
#length * #length
end
end
s1 = Square.new
puts s1.area
Now, I am a little unclear what exactly you aim to achieve by use of that class variable ##sqArray - but for example, you could use this store a list of all defined Squares:
class Square
##squares_list = []
def self.all_known
##squares_list
end
def initialize(length = rand(20))
#length = length
##squares_list << self
end
def area
#length * #length
end
end
This would allow you to write code like:
s1 = Square.new #=> #<Square:0x0000000132dbc8 #length=9>
s2 = Square.new(20) #=> #<Square:0x000000012a1038 #length=20>
s1.area #=> 81
s2.area #=> 400
Square.all_known #=> [#<Square:0x0000000132dbc8 #length=9>, #<Square:0x000000012a1038 #length=20>]
Class variables have some odd behaviour and limited use cases however; I would generally advise that you avoid them when starting out learning Ruby. Have a read through a ruby style guide to see some common conventions regarding best practice - including variable/method naming (use snake_case not camelCase or PascalCase), whitespace, etc.

method= with multiple parameters

if I have a method with the equal sign at the end:
class A
def property= name, value
...
end
end
how do I invoke the method property= and pass arguments to it?
Ruby already has a special setter syntax for key-value pairs. You can see it in use with Hash:
phone_numbers = { Bob: "555-555-1234", Francine: "555-555-5678"}
phone_numbers[:Jenny] = "555-867-5309"
To get this syntax for your own class, you just do
def []=(key, value)
# set the value however you like
end
here is what I ended up with (thanks to #LeeJarvis for his/her comment):
class A
def property= value
x, y = value
p [x, y]
end
end
A.new.property = 1, 2

Using Strings as Variable/Object Names in Ruby

I am dealing with fractals. You start with a rectangle, and that shape is decreased by a given decay rate. I have it set up to do the first 10 iterations of the given scenario, and each scenario looks like this:
y_1 = dec_y(y_1)
y_2 = dec_y(y_2)
a_y = [y_1, y_2]
rect_1 = TkcRectangle.new(canvas, [0,0], a_y)
where dec_y is defined as the following:
def dec_y(y)
to_ret = y / $rate
return to_ret
end
I want to turn the first snippet into a function/method (not exactly sure what the Ruby term is...), so that each iteration will just be a single line referencing a method, which makes the problem more extensible. But, I need each TkcRectangle to have a different name. The way I want to set it up, each TkcRectangle will have the same name. But, if I can set the name of the object to a string passed as an argument, then I should not have a problem.
How do I define the name of an object with a given string?
Edit : Code has not been tested, but will give you the idea.
Instead of naming each element, you can use an array and use the index instead
rectangles_array = Array.new
for each loop
rectangles_array << create_rectangle_object(y_1, y_2, canvas)
end for each loop
def dec_y(y)
to_ret = y / $rate
return to_ret
end
def create_rectangle_object(y_1, y_2, canvas)
return TkcRectangle.new(canvas, [0,0], [dec_y(y_1), dec_y(y_2)])
end
If you really want to name it read about structs.. Something like
MyRectangleStruct = Struct.new(:obj_name, :x1, :y1, :x2, :y2)
puts MyRectangleStruct.new(:obj_name => 'First_rec', .....)
define_method(method_name, &block)
with method_name being any string and &block being a block of ruby code; usually it looks something like this:
define_method(method_name) do
your code goes here
end

Creating objects from YAML, already initialized constant

Two problems, that probably are related:
I'm retreiving a number of 'persons' from a YAML-file to an array, and now i'm trying to create classes from that array.
These objects are then to placed in a new array.
It actually works out fine, if you dont consider the fact that the object added last replaces all the previously added.
In my case i get five identical copies of object #5, where i rather like to see five different ones.
My guess is that the error results somewhere in my iterator to get all the 'persons' from the YAML.
I'm getting a cuople of warnings, regarding the 're-use' of constants:
NEWSTR and NEWAL.
getPost = 0
loopa = 0
while loopa < personsInYAML
NEWSTR = TEST.fetch(getPost)
NEWAL = NEWSTR.split(' ')
getPost+=1
puts "*****************************************"
nyloop = loopa+1
puts "PERSON: " + nyloop.to_s + " name: " + NEWAL.fetch(1)
nameToArray = Person.new
outputArray.insert(loopa, nameToArray)
loopa+=1
end
Persons-class
class Person
def initialize
#name
#age
#length
#weight
#misc
end
def name
name = NEWAL.fetch(1)
return name
end
if NEWAL.include?("age:")
def age
x = NEWAL.index("age:")+1
age = NEWAL.fetch(x)
return age
end
end
if NEWAL.include?("length:")
def length
x = NEWAL.index("length:")+1
length = NEWAL.fetch(x)
return length
end
end
if NEWAL.include?("weight:")
def weight
x = NEWAL.index("weight:")+1
weight = NEWAL.fetch(x)
return weight
end
end
if NEWAL.include?("misc:")
def misc
x = NEWAL.index("misc:")+1
misc = NEWAL.fetch(x)
return misc
end
end
end
You're taking the wrong approach to populating your Person class. The only thing your loop is doing is to create brand new Person classes and stick them in an array. It isn't actually initializing the person class at all.
It looks like what you are trying to do is to use a constant (which you don't hold constant) to pass information to the Person class. However, the code that you have in your Person class that is outside of the methods is only going to be run once - when the class loads for the first time, NOT at the time that you make a new Person.
You'd be better off changing your initialize method to take some arguments, and to create the class with appropriate arguments within the loop.
def initialize(name, age = nil, length = nil, weight = nil, misc = nil)
# assign instance variables here
#name = name
...
end
You appear to be trying to create dynamic accessors to the instance variables. This doesn't make a whole lot of sense. Just define accessors on all of them, and handle the case where the instance variables are nil in whatever code is calling the Person class.

Resources