Understanding class method in python - 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

Related

What does Django's #property do?

What is #property in Django?
Here is how I understand it: #property is a decorator for methods in a class that gets the value in the method.
But, as I understand it, I can just call the method like normal and it will get it. So I am not sure what exactly it does.
Example from the docs:
from django.db import models
class Person(models.Model):
first_name = models.CharField(max_length=50)
last_name = models.CharField(max_length=50)
birth_date = models.DateField()
def baby_boomer_status(self):
"Returns the person's baby-boomer status."
import datetime
if self.birth_date < datetime.date(1945, 8, 1):
return "Pre-boomer"
elif self.birth_date < datetime.date(1965, 1, 1):
return "Baby boomer"
else:
return "Post-boomer"
#property
def full_name(self):
"Returns the person's full name."
return '%s %s' % (self.first_name, self.last_name)
What is the difference of if it is there vs if it isn't?
As you see, the function full_name returns a string with the persons first and last name.
What the #property decorator does, is declare that it can be accessed like it's a regular property.
This means you can call full_name as if it were a member variable instead of a function, so like this:
name = person.full_name
instead of
name = person.full_name()
You could also define a setter method like this:
#full_name.setter
def full_name(self, value):
names = value.split(' ')
self.first_name = names[0]
self.last_name = names[1]
Using this method, you can set a persons full name like this:
person.full_name = 'John Doe'
instead of
person.set_full_name('John Doe')
P.S. the setter above is just an example, as it only works for names that consist of two words separated by a whitespace. In real life, you'd use a more robust function.
In some languages users are encouraged to make attributes private and create public getter and setter methods, e.g. in some made up Python-like language with private and public:
class Foo:
private bar
public get_bar(bar):
return self.bar # or look it up in a database
# or compute it on the fly from other values
# or anything else
public set_bar(new_bar):
self.bar = new_bar
The argument is about providing a stable interface. If you want to change the inner workings of your class, e.g. to look it up from a database or compute it, users of the class won't have to change anything; they just keep calling the getter and setter.
In Python we don't really have private attributes, and we want simple syntax. So we flip it: programmers often directly access an object's attributes. But what if you want to change the internal behaviour? We don't want to change the class' interface.
#property lets you change how bar works internally without changing the external interface. Users of the class can still access foo.bar, but your internal logic can be completely different:
class Foo:
def __init__(self, bar):
self.bar = bar
def main():
f = Foo()
print(f.bar)
# Later we can change to something like this without breaking other code
class Foo:
def __init__(self, bar):
self.save_bar_to_database(bar) # Or anything else
#property
def bar(self):
return self.load_bar_from_database()
It is a simple way, where you can get variables in the table and provide another variable which can be used directly as it was a variable.
#property
def total(self):
total_price = self.products.price_each * self.quantity_prt
return total_price
such as abouve function you can get number of products and price and ue a property and make a variable of total price.

invoking a class method inside the class itself

Hi everyone i wanna use a calculated value from a method of the class itself for the rest of the class methods but it must calculate once for all and i need to invoke method inside the class itself i write an example:
class something():
def __init__():
pass
def __sum(self, variable_1, variable_2):
self.summation = sum(variable_1, variable_2)
# I need to calculate summation here once for all:
# how does the syntax look likes, which one of these are correct:
something.__sum(1, 2)
self.__sum(1, 2)
# If none of these are correct so what the correct form is?
# For example print calculated value here in this method:
def do_something_with_summation(self):
print(self.summation)
Something like this seems to be what you're looking for:
class Something:
def __init__(self):
self.__sum(1, 2)
def __sum(self, variable_1, variable_2):
self.summation = sum(variable_1, variable_2)
Not saying this is the ideal approach or anything, but you haven't really given us much to go off of.
In general, make sure self is the first argument in all class methods, and you can call that class method at any time using either self.method_name() if you are using it from within another class method or instance.method_name() if you're using it externally (where instance = Something()).
Assuming that you would receive variable1 and variable2 when you instantiate the class one solution could be:
class something():
def __init__(self, variable1, variable2):
self.summation = variable1 + variable2
def do_something_with_summation(self):
print(self.summation)
If instead you're creating variable1 and variable2 inside other methods, then you could make them class variables:
class Something():
def __init__(self):
#Put some initialization code here
def some_other_method(self):
self.variable1 = something
self.variable2 = something
def sum(self):
try:
self.summation = self.variable1 + self.variable2
except:
#Catch your exception here, for example in case some_other_method was not called yet
def do_something_with_summation(self):
print(self.summation)

Calling method from previous class

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"

How to call a variable defined in one function in another function within same class in python

I have my code as follows -
class utils :
def __init__(self) :
self.Name = 'Helen'
self.count = 0
self.idcount = 0
self.date = datetime.datetime.now().strftime("%Y%m%d")
def getNextId(self) :
self.idcount += 1
id = (self.Name+str(self.idcount)+self.date)
return(id)
def getCount(self) :
self.count += 1
count = str(self.count)
return(count)
Now I want to use the id and count variable in another function within the same class utils. I tried doing it as follows -
def formatField(self) :
self.Id = getNextId().id
self.cnt = getCount().count
return(self.cnt+','+self.Id+' ')
But this doesn't seem to work and gives the error getNextId and getCount are not defined.
How to go about it?
Thanks in advance!
self.Id = self.getNextId();
self.cnt = self.getCount();
But if it's within the same class you can access the member variables directly without using getters.
You don't need to bother with getters generally, but I see you are trying to increment them each time. To call a class method from within a class, you have to use self which is a reference to the class itself.
def formatField(self) :
self.Id = self.getNextId()
self.cnt = self.getCount()
return(self.cnt+','+self.Id+' ')
One thing I'll say is to stop using str() as it isn't normally required. The cast of numbers to string when building a new string is handled automatically by Python.

Communicating between objects in Python

I have something like this:
class exampleClass(object):
def doSomething(self,number):
return number + 1
class exampleClass2(exampleClass):
def callDefDoSomething(self):
print exampleClass.doSomething(5)
exampleClass2.callDefDoSomething()
-
TypeError: unbound method callDefDoSomething() must be called
with exampleClass2 instance as first argument (got nothing instead)
I started to learn about objects in Python but i cant find solution for this :(
You need to create an instance of the class, i.e., an active object, to make things work:
class exampleClass(object):
def doSomething(self,number):
return number + 1
class exampleClass2(exampleClass):
def __init__(self):
self.member1 = exampleClass()
def callDefDoSomething(self):
print self.member1.doSomething(5)
object2 = exampleClass2()
object2.callDefDoSomething()
doSomething is a method of exampleClass. Therefore, it has to be called for an instance of this class.
In callDefDoSomething, you use
exampleClass.doSomething(5)
exampleClass, however, is not an instance of this class but the class itself. What you want to use here is
self.doSomething(5)
self refers to the instance of exampleClass2, for whichcallDefDoSomethingsis invoked, which, due to inheritance, is an instance ofexampleClass`.
Regular class methods can only be called for instances not for classes. So if you want to call callDefDoSomething you have to first instantiate exampleClass2. You also have to instantiate exampleClass inside the call to callDefDoSomething.
class exampleClass(object):
def doSomething(self,number):
return number + 1
class exampleClass2(exampleClass):
def callDefDoSomething(self):
exampleClassInstance = exampleClass()
print exampleClassInstance.doSomething(5)
exampleClass2Instance = exampleClass2()
exampleClass2Instance.callDefDoSomething()
If you want to call methods on classes you should try classmethods. Check the documentation on classes in the python tutorial.
You can use this:
class exampleClass(object):
def doSomething(self,number):
return number + 1
class exampleClass2(exampleClass):
def callDefDoSomething(self):
print super(exampleClass2,self).doSomething(5)
example = exampleClass2()
example.callDefDoSomething()

Categories