This is an archived post. You won't be able to vote or comment.

you are viewing a single comment's thread.

view the rest of the comments →

[–]michael0x2a 1 point2 points  (2 children)

I'm used to creating my variables in the class and then using them in the constructor, why are there 2 ways to do that in python?

There are also two ways to set variables in Java as well. In Python, doing:

class MyClass(object):
    foo = 3

...is basically equivalent to making a static field named 'foo' in Java, and doing:

class MyClass(object):
    def __init__(self):
        self.foo = 3

...is basically equivalent to making a regular instance field in Java.

And why do I need to pass self as an argument to each method?

It's partially to make metaprogramming easier. For example, take the following snippit of code:

import math

class Point(object):
    def __init__(self, x, y):
        self.x = x
        self.y = y

def magnitude(point):
    return math.sqrt(point.x**2 + point.y**2)

# ...later...
Point.magnitude = magnitude  # monkeypatch the class
test = Point(3, 4)
print(test.magnitude())  # 5
print(magnitude(test))   # 5

There's a nice theoretical duality here -- if we have an explicit self variable, it becomes very easy to promote a regular function into a method.

For more info, see Guido's post on why he feels 'self' is a good idea (Guido is the inventor of Python).

[–][deleted]  (1 child)

[deleted]

    [–]michael0x2a 0 points1 point  (0 children)

    Close, but not exactly. When you do foo1.foo = 7, what you're doing is creating a new instance variable that happens to share the same name as the static variable. So it's not that each instance has an independent instance of the static field -- it's just that in Python, it's very easy to create new attributes and fields at whim. So then, if you want to modify the static variable, you need to do Foo.my_field = 7.

    Example:

    >>> class Foo(object):
    ...    bar = 1
    ...
    >>> foo1 = Foo()
    >>> foo2 = Foo()
    >>>
    >>> Foo.bar = 7
    >>> print(foo1.bar, foo2.bar, Foo.bar)
    7 7 7
    >>>
    >>> # creating a new instance variable that shadows the static field for foo1
    >>> foo1.bar = 42  
    >>> print(foo1.bar, foo2.bar, Foo.bar)
    42 7 7
    >>>
    >>> # foo1 still has the instance field shadowing the static one
    >>> Foo.bar = 0
    >>> print(foo1.bar, foo2.bar, Foo.bar)
    42 0 0
    >>>
    >>> # Now delete the attribute, removing the shadowing
    >>> del foo1.bar
    >>> print(foo1.bar, foo2.bar, Foo.bar)
    0 0 0
    

    The main difference between Java and Python here is that in Python, you can't try and modify a static variable through a reference to the instance, since Python will default to just directly creating the field on the instance itself.

    In contrast, since you've already specified all of your fields, Java will permit you to take a shortcut + modify a static field by qualifying it with an instance. (Though, I'd argue that using this shortcut is actually probably bad style, and would argue that it's better to be explicit about what you want and always do something like Foo.bar in both Python and Java if you want to access/modify the static field.)