1

so for my code, the code should print out two statements, calculating the vectors individually and writing both down. Using my code as an example, the program should print out

Vector: x=4, y=4
Vector: x=3, y=7 

However, I am having trouble with creating the class using private attributes, and making a limit of x must be greater than 3 and y cannot be greater than seven. Is the double underscore correct in making it private?

class Vector:
    def __init__(self):
        self.__x = 4
        self.__y =4


v1=Vector(4,4)
print(v1)
v2=Vector(v1.get_x()/2,v1.get_y()*2)
print(v2)
  • I think the convention is a single underscore, but it's been a while. It's just a convention as none of the attributes are truly private. – Deepstop Jun 15 '19 at 02:24
  • You __init__ function does not make sense as it needs arguments if you are going to instantiate the class with v1=Vector(4,4). It should be __init__(self, x, y) – Deepstop Jun 15 '19 at 02:25
  • Yeah, missed that haha thanks for the reminder. I think it is two underscores for it to be private, only accessible in the class itself. – Wilgens Metelus Jun 15 '19 at 02:28
  • 2
    Python does not do private.... – Stephen Rauch Jun 15 '19 at 02:29
  • A single underscore (or more) will exclude the variable or function from the tooltip drop down and remove it from `import *` calls, but nothing is that private in python. https://stackoverflow.com/a/1301369/4777984 – tgikal Jun 15 '19 at 02:30
  • Ah, I see, that makes sense, sorry I am new to Python and thought that's what it meant haha. – Wilgens Metelus Jun 15 '19 at 02:33

3 Answers3

2

The idiomatic way to do this in Python is something like this:

class Vector:
    def __init__(self, x, y):
        self._x = x
        self._y = y

    @property
    def x(self):
        return self._x

    @x.setter
    def x(self, value):
        if value < 3:
            raise ValueError('x must be greater than 3')

        self._x = value

    @property
    def y(self):
        return self._y

    @y.setter
    def y(self, value):
        if value > 7:
            raise ValueError('y must be less than 7')

        self._y = value

    def __repr__(self):
        return f'Vector(x = {self.x}, y = {self.y})'

v1 = Vector(4, 4)
print(v1)
v2 = Vector(v1.x / 2, v1.y * 2)
print(v2)

Notes on your original code:

  • A single underscore is the typical mark for a "private" variable. Python does not truly have private variables, so this is purely a convention. Anyone who reads the source code will know that they can access the underlying value of x like v1._x. Double-underscores does have a meaning, but it's for a different purpose. See https://docs.python.org/3/tutorial/classes.html#private-variables for more details.
  • It is not idiomatic to write get_foo methods. Instead, you should use the @property decorator (see https://docs.python.org/3/library/functions.html?highlight=property#property). @property lets you customize "attribute access".
  • You need to pass some inputs into your __init__.
  • You print(v1), but since you didn't define __str__ or __repr__, this would just print something like <__main__.Vector object at 0x0000019CA15D36A0>, which isn't very useful.
Josh Karpel
  • 2,110
  • 2
  • 10
  • 21
1

You need to make get and set method in Vector class.

class Vector:
    def __init__(self, x, y):
        self.__set_x(x)
        self.__set_y(y)

    def __str__ (self):
        return 'vector : '+str(self.__x)+' '+str(self.__y)

    def __set_x(self, x):
        if x < 3: x = 3
        self.__x = x

    def __set_y(self, y):
        if y >= 7: y = 7
        self.__y = y

    def get_x(self):
        return self.__x

    def get_y(self):
        return self.__y


v1=Vector(4,4)
print(v1)
v2=Vector(v1.get_x()/2,v1.get_y()*2)
print(v2)

I added some methods to complete implementation.

  1. __str__ returns string object to be displayed class as the string by print(v1) what you coded.
  2. get_x and get_y return private attribute value when you run v1.get_x() and v1.get_y().
  3. And, Finally, I made __set_x(x) and __set_y(y) as private to be initialized in constructor only.
yaho cho
  • 1,779
  • 1
  • 7
  • 19
0

Regarding the double-underscore. It seems that it works to make it private. I tried it as a test. Maybe it was an update in some newer version of Python than the one I originally studied.

class test_priv():
    def __init__(self, x, y):
        self.__x = x
        self.__y = y

    def showvars(self):
        print(self.__x, self.__y)

p = test_priv(1,2)

p.showvars()
print(p.__x)


$ python test.py
1 2
Traceback (most recent call last):
  File "acid.py", line 12, in <module>
    print(p.__x)
AttributeError: 'test_priv' object has no attribute '__x'
Deepstop
  • 3,627
  • 2
  • 8
  • 21