preferred way to modify attributes - python

I'm using a helper method in my class to modify an attribute, and can see several ways to do this. Are any of the following helper and associated methods preferred or avoided for good reason?
class Test(object):
def __init__(self, x, y):
self.x = x
self.y = y
def _x_helper1(self):
self.x += self.y
def method1(self):
# some other code...
self._x_helper1()
def _x_helper2(self, y):
# some other code...
self.x += y
def method2(self):
# some other code...
self._x_helper2(self.y)
def _x_helper3(self, y):
# some other code...
return y
def method3(self):
# some other code...
self.x += self._x_helper3(self.y)

This example is way too abstract.
Nothing is wrong with just adding obj.x + obj.y. If you need to mutate object's state, and you mutate based on attributes only, use
def mutate(self):
self.x += self.y

Related

Do all variables in a class have to start with self. or class.?

If I have intermediate variables that just help with the multiple steps within a method and won't ever be used outside the method, do I still need to prepend self. to the variable? For instance:
class apples:
def __init__(self, x, y):
self.x = x
self.y = y
def add(self):
self.z = str(self.x + self.y) + " apples"
return self.z
foo = apples(3, 5).add
Does self.z need to start with self. or can it just be defined as z?
No. self. is for variables you'd like to persist on the instance and cls. is for variables you'd like to persist on the class. Variables that should be destroyed when the method ends are just like variables in a function.
In your example, you could just do
def add(self):
z = str(self.x + self.y) + " apples"
return z
But since z is only there to hold the return value, you shouldn't use it at all. This avoids a store followed by a load before return.
class apples:
def __init__(self, x, y):
self.x = x
self.y = y
def add(self):
return str(self.x + self.y) + " apples"
foo = apples(3, 5).add()

Function missing 1 required positional argument [duplicate]

This question already has an answer here:
Missing 1 required positional argument
(1 answer)
Closed last year.
I'm getting this error :
Traceback (most recent call last):
File "C:/Users/mali03/Desktop/Python/Practice/p2.py", line 18, in <module>
first.subtraction(1, 2)
TypeError: subtraction() missing 1 required positional argument: 'y'
Here is my calculator class
class calculator:
def __init__(self, x, y):
self.x = x
self.y = y
def addition(self, x, y):
return self.x + self.y
def subtraction(self, x, y):
if self.x > self.y:
return self.y - self.x
else:
return self.x - self.y
I then call subtraction with the following:
first = calculator
first.subtraction(1, 2)
Like stated previously, you don't have to include parameters in your addition or subtraction functions if you already gather that information in the __init__ function.
Like so:
class calculator:
def __init__(self, x, y):
self.x = x
self.y = y
def addition(self):
return self.x + self.y
def subtraction(self):
if self.x > self.y:
return self.y - self.x
else:
return self.x - self.y
first = calculator
print(first(5,10).addition())
Alternatively, if you do want to have x and y parameters in your addition and subtraction functions, you can adjust your code like so:
class calculator:
def addition(self, x, y):
return x + y
def subtraction(self, x, y):
if x > y:
return y - x
else:
return x - y
first = calculator
print(first().addition(5, 10))
Where parameters of individual functions are used instead to the parameters given to the class object.
Either ways work, it depends on how you want to use the class.
Alternatively you could do:
class calculator():
def addition(self, x, y):
return x + y
def subtraction(self, x, y):
if x > y:
return y - x
else:
return x - y
first = calculator()
print(first.subtraction(1, 2))
Also not entirely sure if x > y: was your intention or if you really wanted if x < y:
You don't need to specify x and y in subtraction or addition:
class calculator:
def __init__(self, x, y):
self.x = x
self.y = y
def addition(self):
return self.x + self.y
def subtraction(self):
if self.x > self.y:
return self.y - self.x
else:
return self.x - self.y
self will cover retrieving x and y for you, since you are referencing those instance variables. Otherwise, you will need to specify them on call:
# Yields 2-1 rather than 4-3
result = calculator(1,2).subtraction(3,4)
You do, however, need to specify them when instantiating your class
myinst = calculator(1,2)
first = calculator makes first refer to the class. But first = calculator(1, 2) makes first an object of the class calculator. This initializes self for all other functions called on first. This also sets the values for self.x and self.y because __init__ is called as soon as object is created. Hence, when first = calculator(x, y) is used, self has a value along with self.x and self.y, and when parentheses are not used, they do not have a value. That gives a missing argument error.
Next, as others have already referred, once __init__ is called, x and y are initialized for the object. And so, you don't need them while declaring other functions. self.x and self.y can directly be used there which will now refer to 1 and 2 respectively in this case.
Hope it helps.

adding two value in a class in python

I am knew at this and not sure the exact syntax to use to add x,y in python using this class definition
class Add(values):
def __init__(self, x, y):
values.__init__(self, [x, y])
def forward(self):
return self.values[x] + values[1]
I am not able to figure out how to access x,y to add them together. I have tried all the possibilities that I can think of. Thank you.
I think you want a function and not a class.
def add(x, y):
return x+y
If you're sure that this really has to be a class for whatever you're doing, it can look like this:
class Add:
def __init__(self, x, y):
self.x = x
self.y = y
def forward(self):
return self.x+self.y
Then
>>>add(5, 6)
11
>>>a = Add(5, 6)
>>>a.forward()
11
i think that is what you need
class Values():
def __init__(self, x = 0, y=0):
self.x_value = x
self.y_value = y
class Add(Values):
def __init__(self, x = 0, y=0):
Values.__init__(self, x, y)
def forward(self):
return (self.x_value + self.y_value)
add = Add(x = 20, y=20)
print (add.forward())
To add something to other answers, I would say that :
class Add(values):
means that you create class 'Add' who inherits from the class 'values'. Class 'values' must be defined somewhere otherwise you will have the NameError.
More info about inheritance here :
https://docs.python.org/3.6/tutorial/classes.html#inheritance
Actually the answer I was looking for is :
self.x =[0]
self.y = [1]
Thanks for the tries.

How to use property()

I'm having trouble on how to implement property to protect attributes.
class Point:
def __init__(self, x, y):
self.x = x
self.y = y
def set_x(self, x):
if '_x' in dir(self):
raise NotImplementedError("Cannot change x coordinate")
else:
self._x = x
def get_x(self):
return self._x
#I beleive my mistake is here. I'm not sure if I'm implementing this correctly
x = property(get_x, set_x, None, None)
So I want to prevent any user from changing the x-coordinate. My question is, how do I get python to redirect the user to the set_x() and get_x() methods? I've tried running this code in terminal and whenever I apply the following, the point changes.
p = point(3, 4)
p.x = 5 #x is now 5
You only need this much:
class Point:
def __init__(self, x, y):
self._x = x
self.y = y
def get_x(self):
return self._x
x = property(get_x)
You can set the hidden field self._x in your init, then you don't need a setter for x at all. And have get_x return self._x rather than self.x so it doesn't try and call itself.
You can use the #property decorator to do this even more succinctly.
class Point:
def __init__(self, x, y):
self._x = x
self.y = y
#property
def x(self):
return self._x
The following code works on both python2.x and python3.x:
class Point(object):
def __init__(self, x, y):
self.x = x
self.y = y
def set_x(self, x):
if '_x' in dir(self):
raise NotImplementedError("Cannot change x coordinate")
else:
self._x = x
def get_x(self):
return self._x
x = property(get_x, set_x, None, None)
p = Point(2, 3)
print(p.x) # 2
p.x = 6 # NotImplementedError
Pretty much all I did was inherit from object (to get it to work on python2.x) and use the name Point rather than point (which would have been a NameError before).
There are other things you can do to clean it up a bit (e.g. khelwood's suggestion of just writing the getter -- or DSM's suggestion of using hasattr instead of '_x' in dir(self)).
Note, if you really just want a type that takes an x and y arguments that you want to be immutable -- Maybe you should consider using a colledctions.namedtuple
from collections import namedtuple
Point = namedtuple('Point', 'x,y')
p = Point(2, 3)
p.x # 2
p.y # 3
p.x = 6 # AttributeError: can't set attribute

Redirect class variable to class function

Let's take a simple class as an example:
class Vector:
def __init__(self):
self.x = 1
self.y = 1
self.z = 1
What I would like is to give this class a variable called sum such that when I do
v = Vector()
v.sum
I am given the sum x+y+z (in this case 3). Of course I can easily just make a class method that does this, but then I would have to write v.sum() instead of v.sum. Is there any way to hide the fact that the class actually calls a function when asking for a variable?
Thanks in advance.
class Vector(object): # subclass object for new style class
def __init__(self):
self.x = 1
self.y = 1
self.z = 1
#property
def sum(self):
return self.x + self.y + self.z
>>> v = Vector()
>>> v.sum
3
http://docs.python.org/2/library/functions.html#property

Categories

Resources