Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Should I use "self" to define variables / objects of class instanced which I will not need to reach from the outside?

I am not a complete beginner but fairly new to Python. Whilst working on a project today I just had an idea and wondered regarding the usage of "self"; about which I've been reading for the past some while and I still can not figure out if it's always necessary or not. My question solely concerns instances of classes and instance parameters/variables. This question is not about Class Variables which affect all instances.

Example:

class C:
    def __init__(self, parent = None):
        super(C, self).__init__(parent)
        self.some_temp_var = AnotherClass()
        self.important_property = self.some_temp_var.bring_the_jewels()

ins_c = C()
print ins_c.important_property 

In the above code, I use self before both variable declarations (some_temp_var and important_property).

I will need to access **important_property** later from the outside (where instance's been created) and maybe even modify it.

But I will not need access to the instance of AnotherClass() and/or variable pointing to it (some_temp_var). I just need an instance of it class once, and I need to execute its method bring_the_jewels only once to populate value of important_property.

Should I still use self before declaring that variable as well?

self.some_temp_var = ....
self.important_property = ....

or can it be:

some_temp_var = ....
self.important_property = ....

Thank you for your help.

Ps. I did my research in a length way. Due to lack of my English and/or CS knowledge, I may not have found a currently existing duplicate however I did search and I did search a lot. Before calling this question "duplicate" or "not constructive" please read it throughly. This is a question with clear answer and it's very important, and complicated matter. Thank you for your understanding.

like image 606
Phil Avatar asked Dec 30 '12 20:12

Phil


People also ask

Do class variables need self?

The value of the instance variable will be unique to the instance objects of the class that might be declared. However, if you want the variables to be shared by all instances of the class, you need to declare the instance variables without self.

What is the purpose of self in Python?

The self parameter is a reference to the current instance of the class, and is used to access variables that belongs to the class.

What does self __ class __ do?

self. __class__ is a reference to the type of the current instance. Throwing an exception here is like using an assert statement elsewhere in your code, it protects you from making silly mistakes. type() should be preferred over self.

What would you call a variable defined outside a constructor?

Instance variables are generally defined/initialized within the constructor. But instance variables can also be defined/initialized outside the constructor, e.g. in the other methods of the same class.


3 Answers

If you dont use self.some_temp_var, then you are defining a local variable which will be garbage collected after the constructor.

So yes you need self if you want to define an instance attribute that should persist with the instance. Whether you need it to be public or private is a matter of naming. Prefix it with an _ for protected or __ for private.

If some_temp_var is just a temp for the constructor and you never need it again then no, you dont need self. It is about persistence and member attributes. You do not need self for the pure fact of working with a variable within a single method.

Consider this... What if some_temp_var were some huge data structure that you build up to arrive at the real result value? You dont want to use self to store a temp variable because it wont free memory until you delete it or the instance. You want it to be cleaned up when it is no longer needed.

like image 62
jdi Avatar answered Oct 05 '22 02:10

jdi


Looks like you don't need the variable at all then:

class C:
    def __init__(self, parent=None):
        super(C, self).__init__(parent)
        self.important_property = AnotherClass().bring_the_jewels()

In response to your comment:

do I need to put self. infront of it if it's gonna be created, referenced and used once during __init__.

No, you don't. Use a regular variable then, and the object will be garbage-collected after __init__ exits.

class C:
    def __init__(self, parent = None):
        super(C, self).__init__(parent)
        some_temp_var = AnotherClass()
        self.important_property = some_temp_var.bring_the_jewels()
like image 40
Lev Levitsky Avatar answered Oct 05 '22 02:10

Lev Levitsky


Python does not really distinguish "public" from "private" variables. Anything you assign to a name in self using 'self.something = value' will be an instance variable for that instance.

Python does have two conventions that are relevant here:

1) Python fields or methods are prefixed with underscores('_') to tell users 'this is not a concern outside this class'. A single underscore is a conventional way of identifying more or less what a language like C# would call a 'protected' variable: it's internal to the implementation and should be left alone except by this class and derived classes. A double underscore is like a C# 'private' variable: it's internal and should be left alone even by derived classes, it can't be overridden

class Example(object):
    def __init__(self)
       self._protected= "protected"
       self.__private = "private"
       self.public = "public"

class Derived(Example):
    pass

d = Derived()
print d._protected
>> protected
print d.__private
>> AttributeError: 'Derived' object has no attribute '__private'

Strictly speaking the single underscore is just a typographical convention. The double underscore does actually mangle the name inside the class to prevent inheritance.

2) You example is potentially case for using the property decorator if AnotherClass is actually going to hang around, and if manipulating the AnotherClass instance affects the state of AnotherClass.

class C:
    def __init__(self, parent = None):
        super(C, self).__init__(parent)
        self._private = AnotherClass()

    @property
    def public(self):
       return self._private.some_method_on_AnotherClass()

    @public.setter
    def set_pub(self, val)
       self._private.set_value_on_AnotherClass(val)
like image 26
theodox Avatar answered Oct 05 '22 02:10

theodox