Calling method from previous class - python

I'm trying to call a method from a previous Class for the Class I'm currently working on. It's a mock GPS system using classes for different things. The class I'm trying to get the method from looks like the following :
class GPS_POI:
def __init__(self, location, name , kind):
self.location= location
self.name = str(name)
self.kind = str(kind)
def __str__ (self):
return (str(self.location) + ": "+ self.name +", " + self.kind )
The current class and method I am working on:
class GPS :
def __init__ (self, current, map = None):
self.current = current
self.map= map
self.route= []
def display_map(self):
for i in self.route:
display= GPS_POI()
return (display.__str__ + "\n")
When I run it, I just end up getting the result of "None" when the output I want (example) would be :
"(3,1): kmart, clothes \n(2,3): burger king, food\n" etc.
Would I need to include my parameter self.map from the class GPS into the display_map function for it work properly? What am I not understanding about calling a method from a previous class?

You aren't calling display.__str__; you are just referencing it. You shouldn't call __str__ explicitly anyway. Its purpose is to provide a hook for when you try to treat the object as a string, such as when passing it to str as an argument:
return str(display) + "\n"

Related

Understanding class method in python

I have a three question to ask
in python I have written a class method inside a class and have written basic functionality When I try to call that method from class itself and when I try to print I get the output as "None"
Also if someone can please explain in class methods only class variables can be accessed? and also can instance variables can also be accessed in class methods
Also if remove the class variables and declare my own variables in the class method would the code will work when i pass the arguments in the method while calling it from class
Below is the code
class Item():
discount_price = 0.8
quantity1 = 10
quantity2 = 10
def __init__(self,name,price,quantity):
self.name = name
self.price = price
self.quantity = quantity
#classmethod
def year2020(cls,val1,val2):
cls.value2020 = cls.quantity1 + cls.quantity2 + cls.discount_price
print(Item.year2020(10,10))
The functoin year2020 does not return anything, so the print statement is told to print out nothing. To get it to print the output of the function, make sure to include a return statement inside.
For example, here is a fixed function which returns the output:
def year2020(cls,val1,val2):
cls.value2020 = cls.quantity1 + cls.quantity2 + cls.discount_price
return cls.value2020

Python coding best practices

Is it a good idea to handle all the arguments in the constructor? instead of handling them in the particular methods where the arguments are actually needed?
Method 1:
def __init__(self,name,rollno,dob,city,state,zip):
self.name=name
..
..
self.zip = zip
def address(self):
return self.city+self.state+self.zip
def unique_identifier(self):
return self.name+self.rollno
test.py
example = Example("Programming","941","1997-09-07","Nashville","TN","37311")
print(example.address())
print(example.unique_identifier())
Method 2:
Class Example:
def address(self,city,state,zip):
return self.city+self.state+self.zip
def unique_identifier(self,name,rollno):
return self.name+self.rollno
test.py
example = Example()
print(example.address("ab","cd","111")
print(example.unique_identifier("Programmer","123")
Any explanation/reasoning to help understand Which method is more preferable for best practices.
Either is fine, it just depends on if the data belongs to the object (method 1) or if the data comes from outside the object (method 2). It can also be a mix of both. A short example:
class Person:
# store data specific to the instance
def __init__(self, name, birthdate, hometown):
self.name = name
self.birthdate = birthdate
self.hometown = hometown
# here I only need data from the instance
def introduce(self):
print("Hello, I am", self.name,
", I come from", self.hometown,
" and was born on ", self.birthdate,
".")
# food shouldn't be part of the Person,
# so it is passed in as an argument
def order_food(self, food):
print("I am ", self.name,
" and would like some ", food, " please.")

Calling a method returns <__main__ XYZ object at 0x01234567>

I'm going through a web-based python tutorial and the code below executes in the web environment the class has provided.
However, when I try to run the code locally in Anaconda I get the following result:
I'm Fido. I feel <bound method Pet.mood of <__main__.Pet object at 0x00000223BD4B74E0>>.
I see how using class and superclass can make my code better, and trying to figure out how to get the web based examples to work locally.
Here's the code:
class Pet:
def __init__(self, name = 'Kitty'):
self.name = name
def mood(self):
#code simplified for SO example
return 'happy'
def __str__(self):
state = " I'm {}. I feel {}.".format(self.name, self.mood)
return state
class Cat(Pet):
def chasing_rats(self):
return "I'll get you!"
p1 = Pet("Fido")
print(p1)
self.mood is an instance method of the class Pet. So you need to call it as a method by including the parentheses as self.mood()
class Pet:
def __init__(self, name = 'Kitty'):
self.name = name
def mood(self):
#code simplified for SO example
return 'happy'
def __str__(self):
state = " I'm {}. I feel {}.".format(self.name, self.mood())#updated this line
return state
class Cat(Pet):
def chasing_rats(self):
return "I'll get you!"
p1 = Pet("Fido")
print(p1)
OUTPUT
I'm Fido. I feel happy.

Using a print function in parent class, about definition of 'inherited' variables

Let's suppose I have a parent class called figure:
class Figure:
def __init__(self):
self.name = " "
self.description = " "
self.data = []
def myprint(self):
# Print all variables in a special way
I want to create several childs of this class (Circle, rectangle...) and I want to use as much inheritance as possible. That's why I want to create a myprint function that outputs all the data which is common to all childs, i.e. this one:
self.name = " "
self.description = " "
self.data = []
What is the correct way to do it?
Should I include those lines in class Figure and then modify them in every child using
Figure.name = 'Circle'
... Or should I create them in every child? How would I use a common myprint function then? This way:
class Figure:
def __init__(self):
def myprint(self):
# Print all variables in a special way
class Cricle(Figure):
def __init__(self, radius):
name='Circle'
pass
class Figure:
name = 'Figure'
description = "I'm a figure"
def __init__(self):
self.data = []
def myprint(self):
print(self.name, self.description, self.data)
class Circle(Figure):
name = 'Circle'
description = "I'm a circle"
This is all you need. If the properties aren't specific to an instance, but are the same for all class instances, just define them on the class (here name and description). Only data is defined within the constructor because [] is mutable and you probably want that to be unique for each instance.
The child class then redefines name and description with different values. myprint of Figure instances will print "Figure", while myprint of Circle instances will print "Circle". That's because self.name refers to the name attribute of the current object, and that value will differ based on whether it's a Figure or Circle.
Everything you define in __init__ are instance variables.
I suppose you are looking for class variables, or rather constants which are exactly the same, but written with all capitals by convention.
Also, take a look on the __str__ method here.
The correct way therefore would be:
class Figure:
NAME = "Figure"
def __str__(self):
""" override me """
return "I am a {name} and have the default __str__".format(name=self.NAME)
class Circle(Figure):
NAME = "Circle"
def __init__(self, x, y, r):
self.x, self.y, self.r = x, y, r
def __str__(self):
return "I am a {name} at ({x}, {y}) with radius {r}".format(
name=NAME, x=self.x, y=self.y, r=self.r)
Now all you need to do to get a correct output is to run
f = Figure()
c = Circle(1, 2, 3)
print(f)
print(c)
Which will output
I am a Figure and have my __str__ not overwritten
I am a Circle at (1, 2) with radius 3

Accessing a full chain of attribute calls in python

is there a way to intercept chains of attribute calls?
What I mean is the following:
myobj.attr1.attr2.{...}.attrN
Can I somehow intercept the whole chain within myobj?
What I have in mind is a function that gets access to the full chain 'attr1.{...}.attrN' at once, for example as a string. Is there a way to establish this?
So far, I have a rather hacky solution where getatrr creates novel objects whose getattr also creates novel objects and thereby the whole attribute chain is recorded as a string (below in fullname). But I don't like this solution at all since this has several drawbacks especially when it comes to pickling and error handling.
class NameCollector(object):
''' A helper class that resolves natural naming
'''
def __init__(self,myobj,name='',parent_name=''):
self._myobj=myobj
if name == '':
self._fullname = ''
elif parent_name == '':
self._fullname = name
else:
self._fullname = parent_name + '.' + name
def __getattr__(self,name):
new_collector = NameCollector(self._myobj,name,self._fullname, self._regexp)
if name in self._myobj._leaves:
return self._myobj._do_stuff_with_chained_attribute_names(new_collector)
return new_collector
Cheers and thanks a lot,
Robert
One solution could be to create a new object on the first access a.b, and then every subsequent access, just update the object's internal structure (eg. a list of values), and add a __str__ and __repr__ method.
class NameCollector(object):
def __init__(self, parent, attr):
self.parent = parent
self.structure = [attr]
def __getattr__(self, attr):
if attr in self.__dict__: return attr
self.structure.append(attr)
return self
def __str__(self):
retval = ""
for item in self.structure:
retval += str(getattr(self.parent, item)) + "."
return retval[:-1] # Remove the last '.'
class Foo(object):
def __getattr__(self, attr): return NameCollector(self, attr)

Categories