14

Or can they be declared otherwise?

The code below does not work:

class BinaryNode():
    self.parent = None
    self.left_child = None

Do they need to be declared in __init__?

2
  • 8
    What you are attempting to do appears at first glance to misguided. Perhaps you could explain what problem you are trying to solve? Commented Sep 5, 2012 at 3:42
  • +1 on the above comment. What is the problem you are trying to solve? @Oddthinking: is correct. You are likely going about solving the wrong problem, or at least, in the wrong way. Commented Sep 5, 2012 at 3:57

4 Answers 4

13

They do not have to be declared in __init__, but in order to set an instance variable using self, there needs to be a reference to self, and the place you are defining the variables does not.

However,

class BinaryNode():
    parent = None
    left_child = None

    def run(self):
        self.parent = "Foo"
        print self.parent
        print self.left_child

The output will be

Foo
None

To answer your question in the comment, yes. You can, in my example say:

bn = BinaryNode()
bn.new_variable = "Bar"

Or, as I showed, you can set a class level variable. All new instances of the class will get a copy of the class level variables at instantiation.

Perhaps you are not aware that you can pass arguments to the constructor:

class BinaryNode(object):

    def __init__(self, parent=None, left_child=None):
        self.parent = parent
        self.left_child = left_child



bn = BinaryNode(node_parent, node_to_the_left)
Sign up to request clarification or add additional context in comments.

5 Comments

Is there a way to set an instance variable without using self?
But the class level variable will be shared among all instances of the class correct?
I can't quite imagine how such a parent member shared between all instances of a class would be useful.
@GregHewgill: To be clear, I am not suggesting that a parent member be shared across all instances. I was just using the same names as given by the OP.
once you call self.xxx = yy instead of SomeClass.xxx = yyyyou are turning it into an instance variable... (or at least its value is unique to that value) at least i think so in my py2.6
3

Must all Python instance variables be declared in def __init__? Short answer: no. But it really depends on how/where to use them.

Or can they be declared otherwise? Yes they can be declared otherwise (not an instance variable). Since you're referring to variables inside a class, yes you can declare a local variable (for example) inside of it if you don't want to use __init__ constructor function that uses the keyword self.

The code below does not work:

class BinaryNode():
    self.parent = None
    self.left_child = None

What do you mean by not working? if you're referring to how most developers use a class, then you are right, it does not work in the sense that you can not create a class object (it's also called class instance) and then call one of its instance variables assuming they are declared properly (ie: declared INSIDE the init method that plays the role of the constructor method.)

In other words: if you declare a variable outside the constructor method init then it's called a class variable and not an instance variable. To initiate an instance variable, it needs to be inside the init method that will actually construct (instantiate) the class instance (class object) along with its associated instance variables (instance attributes.)

for example:

if you have parent = None instead of self.parent = None you just created a local variable inside your class.

So the word self is there to hold the place for when you call the class instance is called, it's passed-in in lieu of self. Therefor the word self is just there as a parameter to hold a place for passing whatever instance variable we want to call in its place. So the word self is just doing a favor service here.

Similarly , when creating a class object and say you want to create an instance variable, you must use the attribute word self (it does not have to be self but since most python developers use it, using it became a convention and a good practice in python) that will work as a reference (a holder) to complete the work of the constructor function __init__ which will assign the argument value passed-in the class instance (object) created to be the new value of the instance variable copy that belongs to the class instance created.

Now, let's try another scenario to better solidify the concept:

What if we use the __init__ function but not the keyword self? if you create a class object named object_x and then you want to call one of its instance variables named instance_y from the , then you execute the program, it will throw an error saying that the class object created does not have an attribute (instance variable).

It will be just a local variable with whatever value you assigned to it when you defined it.

The error occurs because it doesn't recognize it as one of the instance variables defined inside the class when it's missing the reference word self.

Comments

2

Nope. I love the @property variable for just this thing:

class Data(object):
    """give me some data, and I'll give you more"""
    def __init__(self, some, others):
        self.some   = some
        self.others = others

    @property
    def more(self):
        """you don't instantiate this with __init__, per say..."""
        return zip(self.some, self.others)


>>> mydata = Data([1, 2, 3], ['a', 'b', 'c'])
>>> mydata.more
[(1, 'a'), (2, 'b'), (3, 'c')]

4 Comments

You are missing a self in your __init__.
@property is a "decorator". Properties are outside of the scope of the original question, though, as they don't have anything to do with declaring of attributes. Effectively, it's the same as more = property(fget=lambda self: zip(self.some, self.others); that is, it's a standard attribute assignment that just happens to hold a wrapper for specialised behaviour.
@MatthewTrevor as far as a user of the Data class is concerned, more will not appear as a function that returns a "getter", but as a simple property (with validation, assignment, exceptions, and the like). I'm not saying you aren't correct...
But we're not talking appearances here, we're talking actuality of assignment. It just confuses the issue a little as it's effectively irrelevant.
0

Also, you can have class level variables, but I call them class constants.

class Connection(object):
    """helps you connect to the server at work"""
    YOUR_IP = '10.0.9.99'

    def __init__(self, username, password):
        self.ip = Connection.YOUR_IP
        self.un = username
        self.pw = password

    #...and so on

1 Comment

The correct term is "class attribute". Calling them "constants" when they're not is a recipe for confusion :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.