to change the value of instance variable - python

I want to print name as tanya but since self.name = None has been assigned in constructor it is printing None. So how to get tanya printed when the check function gets called:
class A:
def __init__(self):
self.name = None
def price(self):
self.name = "tanya"
def check(self):
print(self.price())
a=A()
a.check()

The constructor isn't the problem
print(self.price()) is going to print None because you are printing the result of the function.
It then sets self.name="tanya" after printing, but you are ignoring it
Instead, I think you want
a=A()
a.price()
print(a.name)
and forget the check function

class A:
def __init__(self):
self.name=None
def price(self):
self.name="tanya"
return self.name
def check(self):
print(self.price())
a=A()
a.check()
You just have to add the return statement in the price function, and you're done!

Related

how can i reference to an object variable without passing it as parameter in python classes

I am try to reference an object variable inside the class without passing it in parameters but it is throwing error
class Sample:
def __init__(self):
v = []
v.append(name)
v.append(email)
s = Sample()
s.name = "xxxx"
s.email = "ss#ss.com"
print s.v
error:
NameError: global name 'name' is not defined
I am assigning the variable name in the object now how can i call it inside the class without adding parameters to function
if you absolutely must avoid attributes:
class Sample:
def __init__(self):
self.v = []
def addName(self, name):
self.v.append(name)
def addEmail(self, email):
self.v.append(email)
s = Sample()
s.addName("xxxx")
s.addEmail("abc#def.com")
print(s.v)
Yet another way to do this is to use decorators and #property:
class Sample(object):
def __init__(self):
self.v = [None, None]
#property
def name(self):
return self.v[0]
#property
def email(self):
return self.v[1]
#name.setter
def name(self, value):
self.v[0] = value
#email.setter
def email(self, value):
self.v[1] = value
s = Sample()
s.name = "xxxx"
s.email = "ss#ss.com"
print s.v
Notes:
Your class must be extending object explicitly in python 2 for this to work
#property decorated methods are working as "getters" and return a value
#<name>.setter is a setter method responsible for setting <name> member, so #email.setter sets the email and is being invoked when x.email = ... is called
The above may be a bit long-winded but allows for a clean API which hides the details from the user... Some people do prefer to add get/set_name methods to be more explicit but the above is more pythonic
If your requirements are dynamic, you can create attributes at run time like,
class Sample:
pass
s = Sample()
setattr(s,"name","chanda")
setattr(s,"email","xyz#gmail.com")
setattr(s,"v",[s.name,s.email])
print(s.name) #chanda
print(s.email) #xyz#gmail.com
print(s.v) #['chanda', 'xyz#gmail.com']
print(s.__dict__) #{'email': 'xyz#gmail.com', 'v': ['chanda', 'xyz#gmail.com'], 'name': 'chanda'}

How to use setter in python constructor

the python gurus, i got this task i was given to complete, i have ended up writing the code, but i keep getting this error "Oops! Don't forget to use the setters in your constructor, and print "<attribute name> changed" whenever a setter is called (regardless of whether the correct type was supplied)" my code has one constructor and six methods. the first three methods are getters while the last three are setters. My problem is how do i resolve this error Oops! Don't forget to use the setters in your constructor, and print "<attribute name> changed" whenever a setter is called (regardless of whether the correct type was supplied) Because it seems am using the setters already but don't know why this error persist thanks. Here is my full code:
class TodoItem:
def __init__(self, title, description, completed=False):
self.title = title
self.description = description
self.completed = completed
def getTitle(self):
print ("title accessed")
return self.title
def getDescription(self):
print ("description accessed")
return self.description
def getCompleted(self):
print ("completed accessed")
return self.completed
def setTitle(self, newtitle):
print ("title changed")
if type(newtitle) == str:
self.title = newtitle
else:
print ("invalid value title changed")
self.title = None
def setDescription(self, newdescription):
print ("description changed")
if type(newdescription) == str:
self.description = newdescription
else:
print ("invalid value description changed")
self.description = None
def setCompleted(self, newbool):
print ("completed changed")
if type(newbool) == bool:
self.completed = newbool
else:
print ("invalid value completed changed")
self.completed = None
This is my code to test the code above:
mytodo = TodoItem(99,"make a list and go to the store")
mytodo.setTitle(99)
print (mytodo.getTitle())
Generally in python we don't use getter and setter, anyway, if you really need them there is two good ways to do it (illustrates with var1 and var2):
class Example(object):
def __init__(self, var1, var2):
self.__var1 = var1
self.__var2 = var2
#property
def var1(self):
return self.__var1
#var1.setter
def var1(self, value):
self.__var1 = value
def get_var2(self):
return self.__var2
def set_var2(self, value):
self.__var2 = value
var2 = property(get_var2, set_var2)
if __name__ == "__main__":
# With those implementations you can call the getter and setter as if
# you directly call and modify the variable (which is what we want in
# python).
e = Example()
e.var1 = 1 # will call the method with the #var1.setter decorator
print(e.var1) # will call the method with the #property decorator
e.var2 = 1 # will call the method set_var2()
print(e.var2) # will call the method get_var2()
Also, in python to indicate that variable are private we add "__" before them and "_" means protected.

How to convert all elements automatically in a list to a given object in Python

I want to create a list child class that can convert all elements automatically in it to an object no matter the element is create by init or append or extend. So by using both for loop or getitem. Here's a simple example code. What kind of magic method should I use?
class A():
def __init__(self, name):
self.name = name
def __repr__(self):
return 'Object A with name {}'.format(self.name)
class CustomerList(list):
def __init__(self, *args):
super(CustomerList, self).__init__(*args)
c = CustomerList('a')
c.append('b')
c[0] # Object A with name a
c[1] # Object A with name b
for ele in c:
print(c)
# Object A with name a
# Object A with name b
are you asking how to override __append__?
class A():
def __init__(self, name):
self.name = name
def __repr__(self):
return 'Object A with name {}'.format(self.name)
class CustomerList(list):
def __init__(self, *args):
super(CustomerList, self).__init__(*args)
def append(self,letter):
super(CustomerList, self).append(A(letter))
I guess???.. but as mentioned in the comments if you want
my_custom_list.extend(["A","B","V"])
my_custom_list[2] = "A"
to work you will need to override
def __setitem__(self,key,value): # cover a[2]='A'
super(CustomerList,self).__setitem__(key,A(value))
def extend(self,other):
super(CustomerList,self).extend([A(val) for val in other])
of coarse you probably then need to override both __add__,__iadd__ at a minimum as well
I think what you're trying to do is: When you append a new item into the list, it is an object of class A. What you can do is override list.append function:
class A():
def __init__(self, name):
self.name = name
def __repr__(self):
return 'Object A with name {}'.format(self.name)
class CustomerList(list):
def __init__(self, *args):
super(CustomerList, self).__init__(*args)
def append(self, arg):
new_obj = A(arg)
self.insert(len(self), new_obj)

Passing a function object to __init__ placed the default value instead of the explicit parameter into the class member

I have the following problem (stripped-down code):
class T(object):
def __init__(self):
pass
def default():
return 0
def foo():
return 2
class A(T):
def infl_(): pass
def __init__(self, infl = default):
super(A, self).__init__()
self.infl_ = infl
a = A(infl = foo)
Now I would expect that when I call a.infl_() that foo gets called. However, somehow default() is called, and I have no idea why this is happeneing. Do I do something wrong here or should I look for a mistake somewhere else in my code?
Edit: Edited the mistakes from the comments.

Returning variable vs. Setting variable

I'm considering the following approaches for class initialisation:
class Foo():
def __init__(self):
self.name = self.get_name()
def get_name(self):
return raw_input("Name: ")
class Foo():
def __init__(self):
self.name = ""
self.get_name()
def get_name(self):
self.name = raw_input("Name: ")
class Foo():
def __init__(self):
self.name = raw_input("Name: ")
Is there any practical reason to opt for one over the others?
If not, which might be considered most Pythonic?
If possible, input() the name outside of the class and pass it as a parameter to its __init__().
If this is not an option, I would go for the second alternative
I would rename get_name() to something like query_name() or input_name(). get_name() sounds like a getter (that gets the value of name) not like a setter or a routine that gets data from the user.
I don't like the idea of doing a raw input in the constructor, but after all, why not...
I would prefer:
class Foo():
def __init__(self):
self.name = ""
def prompt_name(self):
self.name = raw_input("Name: ")
if __name__ == "__main__":
aFoo = Foo()
aFoo.prompt_name()

Categories