Why do you not have to return objects in Python?











up vote
6
down vote

favorite
2












I am a newbie to Python and programming in general and I have just gotten into OOP. In Python, whatever is defined in a function's namespace is only valid while inside that namespace; once outside that space things like variables are forgotten:



def foo():
a = 3

print(a)

NameError: name 'a' is not defined


As far as I know, besides returning data from functions, any information inside the function is lost at the end of the function call, and therein lies my question. Take the following code:



class Example:

def __init__(self, name):
self.name = name

def foo(self):
self.name = 'John'

bar = Example('Jake')
bar.foo()
print(bar.name)

'John'


My question is: why don't you have to return objects after methods? In normal functions any variables are forgotten, but in methods it seems data is actually appended to the object itself, such as the foo() method being able to reference self.name despite self.name first being referenced in another method. Is this correct? Or is there a better technical explanation?










share|improve this question


















  • 2




    It’s called ‘scope’
    – Cole
    Nov 25 at 7:05










  • This is a really good question! My guess would be that, you are calling the methods of an object, and not changing the object directly. What you are changing is the internal data items of the object. Another question would be, then how do the internal data items get updated then? That is a mystery to me, but I guess that all would be answered if we take a look at Python's internal mechanism
    – MaJoR
    Nov 25 at 7:05















up vote
6
down vote

favorite
2












I am a newbie to Python and programming in general and I have just gotten into OOP. In Python, whatever is defined in a function's namespace is only valid while inside that namespace; once outside that space things like variables are forgotten:



def foo():
a = 3

print(a)

NameError: name 'a' is not defined


As far as I know, besides returning data from functions, any information inside the function is lost at the end of the function call, and therein lies my question. Take the following code:



class Example:

def __init__(self, name):
self.name = name

def foo(self):
self.name = 'John'

bar = Example('Jake')
bar.foo()
print(bar.name)

'John'


My question is: why don't you have to return objects after methods? In normal functions any variables are forgotten, but in methods it seems data is actually appended to the object itself, such as the foo() method being able to reference self.name despite self.name first being referenced in another method. Is this correct? Or is there a better technical explanation?










share|improve this question


















  • 2




    It’s called ‘scope’
    – Cole
    Nov 25 at 7:05










  • This is a really good question! My guess would be that, you are calling the methods of an object, and not changing the object directly. What you are changing is the internal data items of the object. Another question would be, then how do the internal data items get updated then? That is a mystery to me, but I guess that all would be answered if we take a look at Python's internal mechanism
    – MaJoR
    Nov 25 at 7:05













up vote
6
down vote

favorite
2









up vote
6
down vote

favorite
2






2





I am a newbie to Python and programming in general and I have just gotten into OOP. In Python, whatever is defined in a function's namespace is only valid while inside that namespace; once outside that space things like variables are forgotten:



def foo():
a = 3

print(a)

NameError: name 'a' is not defined


As far as I know, besides returning data from functions, any information inside the function is lost at the end of the function call, and therein lies my question. Take the following code:



class Example:

def __init__(self, name):
self.name = name

def foo(self):
self.name = 'John'

bar = Example('Jake')
bar.foo()
print(bar.name)

'John'


My question is: why don't you have to return objects after methods? In normal functions any variables are forgotten, but in methods it seems data is actually appended to the object itself, such as the foo() method being able to reference self.name despite self.name first being referenced in another method. Is this correct? Or is there a better technical explanation?










share|improve this question













I am a newbie to Python and programming in general and I have just gotten into OOP. In Python, whatever is defined in a function's namespace is only valid while inside that namespace; once outside that space things like variables are forgotten:



def foo():
a = 3

print(a)

NameError: name 'a' is not defined


As far as I know, besides returning data from functions, any information inside the function is lost at the end of the function call, and therein lies my question. Take the following code:



class Example:

def __init__(self, name):
self.name = name

def foo(self):
self.name = 'John'

bar = Example('Jake')
bar.foo()
print(bar.name)

'John'


My question is: why don't you have to return objects after methods? In normal functions any variables are forgotten, but in methods it seems data is actually appended to the object itself, such as the foo() method being able to reference self.name despite self.name first being referenced in another method. Is this correct? Or is there a better technical explanation?







python python-3.x






share|improve this question













share|improve this question











share|improve this question




share|improve this question










asked Nov 25 at 6:39









Matt

393




393








  • 2




    It’s called ‘scope’
    – Cole
    Nov 25 at 7:05










  • This is a really good question! My guess would be that, you are calling the methods of an object, and not changing the object directly. What you are changing is the internal data items of the object. Another question would be, then how do the internal data items get updated then? That is a mystery to me, but I guess that all would be answered if we take a look at Python's internal mechanism
    – MaJoR
    Nov 25 at 7:05














  • 2




    It’s called ‘scope’
    – Cole
    Nov 25 at 7:05










  • This is a really good question! My guess would be that, you are calling the methods of an object, and not changing the object directly. What you are changing is the internal data items of the object. Another question would be, then how do the internal data items get updated then? That is a mystery to me, but I guess that all would be answered if we take a look at Python's internal mechanism
    – MaJoR
    Nov 25 at 7:05








2




2




It’s called ‘scope’
– Cole
Nov 25 at 7:05




It’s called ‘scope’
– Cole
Nov 25 at 7:05












This is a really good question! My guess would be that, you are calling the methods of an object, and not changing the object directly. What you are changing is the internal data items of the object. Another question would be, then how do the internal data items get updated then? That is a mystery to me, but I guess that all would be answered if we take a look at Python's internal mechanism
– MaJoR
Nov 25 at 7:05




This is a really good question! My guess would be that, you are calling the methods of an object, and not changing the object directly. What you are changing is the internal data items of the object. Another question would be, then how do the internal data items get updated then? That is a mystery to me, but I guess that all would be answered if we take a look at Python's internal mechanism
– MaJoR
Nov 25 at 7:05












5 Answers
5






active

oldest

votes

















up vote
4
down vote



accepted










To understand this you will need to understand how self works. You can learn more here:
Understanding self in python



In a nutshell, self refers to the calling object. Invoking self.variable refers to the variable associated with the calling object. Python is smart enough to create one if it doesn't exist.



Calling self.variable inside a class is the same as calling object.variable with your object reference



Consider the following example to prove this:



class Example:
def print_x(self):
print(self.x)

obj = Example()
obj.x = 5; # Create a new attribute of the object and assign it a value 5
print(obj.x) # Outputs 5
obj.print_x() # Outputs 5


In your example, I've added a couple of print statements to help you understand the state of the program during the execution:



    class Example:
def __init__(self, name):
print(dir(self)) # Printing object contents before initializing name
self.name = name # New attribute 'name' created
print(dir(self)) # Printing object contents after initializing name

def foo(self):
print("Before foo, self.name = "+ self.name)
self.name = 'John'
print("After foo, self.name = "+ self.name)


bar = Example('Jake')
bar.foo()
print(bar.name)


The output of the above code is



['__doc__', '__init__', '__module__', 'foo']
['__doc__', '__init__', '__module__', 'foo', 'name']
Before foo, self.name = Jake
After foo, self.name = John
John


I will walk you through this code. When we first create bar, the __init__() method is called. Here we print the contents of the object using dir(self). The output ['__doc__', '__init__', '__module__', 'foo'] indicates that the object has only one member, the 'foo' method.



Now we create a new attribute called 'name' and assign it the value 'Jake'. Thus the object now has another member, the 'name' attribute as seen by the output of the next dir(self) ['__doc__', '__init__', '__module__', 'foo', 'name']



Now we call the foo method and print the value before and after the method. Before the name is changed in foo, the value of name associated with the object is "Jake". However, after the name is changed, the value of self.name is "John". This is indicated by



Before foo, self.name = Jake
After foo, self.name = John`


We next verify that the change made by changing self.name has indeed changed the value of name in bar by printing bar.name which gives us the expected output, John



Now coming back to your question, self.name is not an ordinary variable inside some method that is lost when we are out of scope. self can be used essentially anywhere inside the class to refer to the calling object (bar in this case). It is used to manipulate this calling object. Now since bar is within the scope, we are able to print its name attribute.




In normal functions any variables are forgotten but in methods it
seems data is actually appended to the object itself




self manipulates the attributes in the object and is not limited to the scope of the method.






share|improve this answer

















  • 1




    Thank you very much for the detailed answer. I look forward to reading through the article about understanding self. Your point of self.variable being the same as object.variable also clicked in my head, as did the extremely detailed code breakdown. I was not familiar with the using the dir() function with objects, but I will be using it frequently now. Also your point of: self.name is not an ordinary variable, self.name can be used essentially anywhere inside the class to refer to the calling object. That sentence was extremely helpful in understanding this, thank you.
    – Matt
    Nov 25 at 8:48


















up vote
5
down vote













First, you don't have to return a value in a method, not in python, and not in many other programming languages. for example:



def append_a(lst):
lst.append('a')

bob =
append_a(bob)
print(bob)
['a']


Above we do not return anything in the function, but we use it to modify an existing data structure, this is very common almost anywhere.



Secondly, in your second example, you created an instance of the class Example, when you look at self.something you are looking at a member of the class, unlike other languages, where often members are only declared once, in python you can dynamically add members.

Thus when looking at bar.name you are looking at a member of the class, its value on the instance bar. If you would look at a different instance, the value will be different.



class Example:

def __init__(self, name):
self.name = name

def foo(self):
self.name = 'John'

bar = Example('Jake')
bob = Example('Bob')
bar.foo()
print(bar.name)
print(bob.name)

John
Bob





share|improve this answer





















  • Thank you for your answer. You are right, I forgot about functions being able to do things outside of their namespace, like appending lists. Also that is a good point about instances being unique and 'self' referencing the instance of the class, it helped clear things up in my head.
    – Matt
    Nov 25 at 8:39


















up vote
3
down vote













There isn't a lot of difference between methods and functions (See this thread for details)



Though one important distinction, that you might have immediately noticed, is that methods have self as their first argument and we say that method foo is "bound" to instance bar of class Example, meaning simply that foo will be called with its first argument (self) as the instance (bar) itself



With this knowledge lets see what the following function does:



class Example:

def __init__(self, name):
self.name = name

def foo(self):
self.name = 'John'

bar = Example('Jake')


In method init, you assign name to self. But what is self? It is bar itself, so calling init can be thought of as doing



bar.name = 'Jake'


Then when you called method foo



bar.foo()


You equivalently did



bar.name = 'John'


So, it should not be surprising when finally the output of the following was 'John'



print(bar.name)  # John


About your query regarding methods not having to return anything, it is not quite so. Methods and functions may or may not return anything as (See this answer). But in this context, what is happening is an object passed to a method is being manipulated (self, which is bar, is being assigned a name) and because the object is alive after the method call completes, we can observe the changes done by the method (ie, we can see that bar.name is changed to 'John')



This works works with functions as well:



def another_foo(self):
self.name = 'Mark'
baz = Example('Jake')
another_foo(baz)
print(baz.name) # Mark


You see, this function did not return anything either. It worked just like the method foo by manipulating its argument. In fact, you could add it to the Example class and use it like a method



Example.another_foo = another_foo
new_bar = Example('Jake')
print(new_bar.name) # Jake
new_bar.another_foo()
print(new_bar.name) # Mark





share|improve this answer




























    up vote
    2
    down vote













    Welcome to Stack Overflow. You are thinking in the right direction. I'll start at a more basic level so that other beginner viewers can understand what is going on.



    Think of Example as a template for creating new objects of a certain kind -- meaning the objects will all have the same attributes (also known as properties) and functionalities. For example, by drawing an analogy with real-life objects, all cars have the attribute "speed" and the functionality "accelerate".



    The attribute values will be specific to the objects. For example, one car will have 0 mph speed and another 70 mph.



    The attribute values at any point describe the state of an object. Methods, which you can think of as the object's functionalities, allow the ability to change an object's state.



    bar is an object that you created using the template (that is, class) Example. If you have to describe this object's state, you'd tell us the values of its attributes. In this case, the object has only one attribute: name.



    Now, this is the important part: name is not just any variable, it's an attribute of any object you make from the class Example. Think of name as always attached to the object. That's why you wrote self.name = 'John' and not name = 'John'. In the latter case, name would not be a part of the object bar, and no other method in the class would have access to the name variable.



    So, to summarize, when you have created an object out of a class, think of the object as having various attributes. All the methods, or functionalities, of the object will have access to all those attributes. The values of the attributes would describe, at any point, the object's state at that moment. It is through that object's methods that one would change its state.



    Finally, here's a great tool to visualize what happens at each line of your code: pythontutor.com






    share|improve this answer



















    • 1




      Thank you very much for your answer, it was extremely helpful. Your point of objects having a 'state' and methods being able to change this state (aka values) really clicked in my head. Also the distinction between self.name = 'John" and name = 'John' was also helpful in understanding the difference and use of self. Again thank you very much for your reply, I will definitely reference it again in the future.
      – Matt
      Nov 25 at 8:37


















    up vote
    1
    down vote













    Well, this is what is called as 'scoping' in OOP. And though the difference between classes and functions might seem subtle, it makes a big difference.



    Simply said, functions rely on global and local variables. Global variables are objects that you define in the global workspace. This is like having a workbench and getting to use a common object across your functions and classes that you define. And so, for example, if you modify your function foo() to include an argument, like so:



    a = 3 # This is globally defined

    def foo(a):
    a = 3 * a
    return a

    print(foo(a))
    9


    Changing the global value of a to something like 2 will give you 6 as the answer. We 'return' an object because it is locally defined within the scope of a function. In this example above, foo() performs the local operation 3 * a and defines it locally to a itself and returns it. And so you can also skip the global variable a when executing foo() and define it locally within the function scope:



    print(foo(6)) # Locally defined
    18

    print(a)
    3 # Returns global variable


    Classes on the other hand need to be declared and that has been very nicely explained by members (see above).






    share|improve this answer























    • Thank you for your answer, your point about global variables being like a workbench available across all functions and classes really helped clarify this, as did about variables being locally defined versus globally defined. This was very helpful.
      – Matt
      Nov 25 at 8:54










    • Thank you. And welcome to SO. Your question was very good and will hopefully stay as a very nice tutorial to classes and methods!
      – Shiv_90
      Nov 25 at 13:24













    Your Answer






    StackExchange.ifUsing("editor", function () {
    StackExchange.using("externalEditor", function () {
    StackExchange.using("snippets", function () {
    StackExchange.snippets.init();
    });
    });
    }, "code-snippets");

    StackExchange.ready(function() {
    var channelOptions = {
    tags: "".split(" "),
    id: "1"
    };
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function() {
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled) {
    StackExchange.using("snippets", function() {
    createEditor();
    });
    }
    else {
    createEditor();
    }
    });

    function createEditor() {
    StackExchange.prepareEditor({
    heartbeatType: 'answer',
    convertImagesToLinks: true,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    imageUploader: {
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    },
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    });


    }
    });














    draft saved

    draft discarded


















    StackExchange.ready(
    function () {
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53465251%2fwhy-do-you-not-have-to-return-objects-in-python%23new-answer', 'question_page');
    }
    );

    Post as a guest















    Required, but never shown

























    5 Answers
    5






    active

    oldest

    votes








    5 Answers
    5






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes








    up vote
    4
    down vote



    accepted










    To understand this you will need to understand how self works. You can learn more here:
    Understanding self in python



    In a nutshell, self refers to the calling object. Invoking self.variable refers to the variable associated with the calling object. Python is smart enough to create one if it doesn't exist.



    Calling self.variable inside a class is the same as calling object.variable with your object reference



    Consider the following example to prove this:



    class Example:
    def print_x(self):
    print(self.x)

    obj = Example()
    obj.x = 5; # Create a new attribute of the object and assign it a value 5
    print(obj.x) # Outputs 5
    obj.print_x() # Outputs 5


    In your example, I've added a couple of print statements to help you understand the state of the program during the execution:



        class Example:
    def __init__(self, name):
    print(dir(self)) # Printing object contents before initializing name
    self.name = name # New attribute 'name' created
    print(dir(self)) # Printing object contents after initializing name

    def foo(self):
    print("Before foo, self.name = "+ self.name)
    self.name = 'John'
    print("After foo, self.name = "+ self.name)


    bar = Example('Jake')
    bar.foo()
    print(bar.name)


    The output of the above code is



    ['__doc__', '__init__', '__module__', 'foo']
    ['__doc__', '__init__', '__module__', 'foo', 'name']
    Before foo, self.name = Jake
    After foo, self.name = John
    John


    I will walk you through this code. When we first create bar, the __init__() method is called. Here we print the contents of the object using dir(self). The output ['__doc__', '__init__', '__module__', 'foo'] indicates that the object has only one member, the 'foo' method.



    Now we create a new attribute called 'name' and assign it the value 'Jake'. Thus the object now has another member, the 'name' attribute as seen by the output of the next dir(self) ['__doc__', '__init__', '__module__', 'foo', 'name']



    Now we call the foo method and print the value before and after the method. Before the name is changed in foo, the value of name associated with the object is "Jake". However, after the name is changed, the value of self.name is "John". This is indicated by



    Before foo, self.name = Jake
    After foo, self.name = John`


    We next verify that the change made by changing self.name has indeed changed the value of name in bar by printing bar.name which gives us the expected output, John



    Now coming back to your question, self.name is not an ordinary variable inside some method that is lost when we are out of scope. self can be used essentially anywhere inside the class to refer to the calling object (bar in this case). It is used to manipulate this calling object. Now since bar is within the scope, we are able to print its name attribute.




    In normal functions any variables are forgotten but in methods it
    seems data is actually appended to the object itself




    self manipulates the attributes in the object and is not limited to the scope of the method.






    share|improve this answer

















    • 1




      Thank you very much for the detailed answer. I look forward to reading through the article about understanding self. Your point of self.variable being the same as object.variable also clicked in my head, as did the extremely detailed code breakdown. I was not familiar with the using the dir() function with objects, but I will be using it frequently now. Also your point of: self.name is not an ordinary variable, self.name can be used essentially anywhere inside the class to refer to the calling object. That sentence was extremely helpful in understanding this, thank you.
      – Matt
      Nov 25 at 8:48















    up vote
    4
    down vote



    accepted










    To understand this you will need to understand how self works. You can learn more here:
    Understanding self in python



    In a nutshell, self refers to the calling object. Invoking self.variable refers to the variable associated with the calling object. Python is smart enough to create one if it doesn't exist.



    Calling self.variable inside a class is the same as calling object.variable with your object reference



    Consider the following example to prove this:



    class Example:
    def print_x(self):
    print(self.x)

    obj = Example()
    obj.x = 5; # Create a new attribute of the object and assign it a value 5
    print(obj.x) # Outputs 5
    obj.print_x() # Outputs 5


    In your example, I've added a couple of print statements to help you understand the state of the program during the execution:



        class Example:
    def __init__(self, name):
    print(dir(self)) # Printing object contents before initializing name
    self.name = name # New attribute 'name' created
    print(dir(self)) # Printing object contents after initializing name

    def foo(self):
    print("Before foo, self.name = "+ self.name)
    self.name = 'John'
    print("After foo, self.name = "+ self.name)


    bar = Example('Jake')
    bar.foo()
    print(bar.name)


    The output of the above code is



    ['__doc__', '__init__', '__module__', 'foo']
    ['__doc__', '__init__', '__module__', 'foo', 'name']
    Before foo, self.name = Jake
    After foo, self.name = John
    John


    I will walk you through this code. When we first create bar, the __init__() method is called. Here we print the contents of the object using dir(self). The output ['__doc__', '__init__', '__module__', 'foo'] indicates that the object has only one member, the 'foo' method.



    Now we create a new attribute called 'name' and assign it the value 'Jake'. Thus the object now has another member, the 'name' attribute as seen by the output of the next dir(self) ['__doc__', '__init__', '__module__', 'foo', 'name']



    Now we call the foo method and print the value before and after the method. Before the name is changed in foo, the value of name associated with the object is "Jake". However, after the name is changed, the value of self.name is "John". This is indicated by



    Before foo, self.name = Jake
    After foo, self.name = John`


    We next verify that the change made by changing self.name has indeed changed the value of name in bar by printing bar.name which gives us the expected output, John



    Now coming back to your question, self.name is not an ordinary variable inside some method that is lost when we are out of scope. self can be used essentially anywhere inside the class to refer to the calling object (bar in this case). It is used to manipulate this calling object. Now since bar is within the scope, we are able to print its name attribute.




    In normal functions any variables are forgotten but in methods it
    seems data is actually appended to the object itself




    self manipulates the attributes in the object and is not limited to the scope of the method.






    share|improve this answer

















    • 1




      Thank you very much for the detailed answer. I look forward to reading through the article about understanding self. Your point of self.variable being the same as object.variable also clicked in my head, as did the extremely detailed code breakdown. I was not familiar with the using the dir() function with objects, but I will be using it frequently now. Also your point of: self.name is not an ordinary variable, self.name can be used essentially anywhere inside the class to refer to the calling object. That sentence was extremely helpful in understanding this, thank you.
      – Matt
      Nov 25 at 8:48













    up vote
    4
    down vote



    accepted







    up vote
    4
    down vote



    accepted






    To understand this you will need to understand how self works. You can learn more here:
    Understanding self in python



    In a nutshell, self refers to the calling object. Invoking self.variable refers to the variable associated with the calling object. Python is smart enough to create one if it doesn't exist.



    Calling self.variable inside a class is the same as calling object.variable with your object reference



    Consider the following example to prove this:



    class Example:
    def print_x(self):
    print(self.x)

    obj = Example()
    obj.x = 5; # Create a new attribute of the object and assign it a value 5
    print(obj.x) # Outputs 5
    obj.print_x() # Outputs 5


    In your example, I've added a couple of print statements to help you understand the state of the program during the execution:



        class Example:
    def __init__(self, name):
    print(dir(self)) # Printing object contents before initializing name
    self.name = name # New attribute 'name' created
    print(dir(self)) # Printing object contents after initializing name

    def foo(self):
    print("Before foo, self.name = "+ self.name)
    self.name = 'John'
    print("After foo, self.name = "+ self.name)


    bar = Example('Jake')
    bar.foo()
    print(bar.name)


    The output of the above code is



    ['__doc__', '__init__', '__module__', 'foo']
    ['__doc__', '__init__', '__module__', 'foo', 'name']
    Before foo, self.name = Jake
    After foo, self.name = John
    John


    I will walk you through this code. When we first create bar, the __init__() method is called. Here we print the contents of the object using dir(self). The output ['__doc__', '__init__', '__module__', 'foo'] indicates that the object has only one member, the 'foo' method.



    Now we create a new attribute called 'name' and assign it the value 'Jake'. Thus the object now has another member, the 'name' attribute as seen by the output of the next dir(self) ['__doc__', '__init__', '__module__', 'foo', 'name']



    Now we call the foo method and print the value before and after the method. Before the name is changed in foo, the value of name associated with the object is "Jake". However, after the name is changed, the value of self.name is "John". This is indicated by



    Before foo, self.name = Jake
    After foo, self.name = John`


    We next verify that the change made by changing self.name has indeed changed the value of name in bar by printing bar.name which gives us the expected output, John



    Now coming back to your question, self.name is not an ordinary variable inside some method that is lost when we are out of scope. self can be used essentially anywhere inside the class to refer to the calling object (bar in this case). It is used to manipulate this calling object. Now since bar is within the scope, we are able to print its name attribute.




    In normal functions any variables are forgotten but in methods it
    seems data is actually appended to the object itself




    self manipulates the attributes in the object and is not limited to the scope of the method.






    share|improve this answer












    To understand this you will need to understand how self works. You can learn more here:
    Understanding self in python



    In a nutshell, self refers to the calling object. Invoking self.variable refers to the variable associated with the calling object. Python is smart enough to create one if it doesn't exist.



    Calling self.variable inside a class is the same as calling object.variable with your object reference



    Consider the following example to prove this:



    class Example:
    def print_x(self):
    print(self.x)

    obj = Example()
    obj.x = 5; # Create a new attribute of the object and assign it a value 5
    print(obj.x) # Outputs 5
    obj.print_x() # Outputs 5


    In your example, I've added a couple of print statements to help you understand the state of the program during the execution:



        class Example:
    def __init__(self, name):
    print(dir(self)) # Printing object contents before initializing name
    self.name = name # New attribute 'name' created
    print(dir(self)) # Printing object contents after initializing name

    def foo(self):
    print("Before foo, self.name = "+ self.name)
    self.name = 'John'
    print("After foo, self.name = "+ self.name)


    bar = Example('Jake')
    bar.foo()
    print(bar.name)


    The output of the above code is



    ['__doc__', '__init__', '__module__', 'foo']
    ['__doc__', '__init__', '__module__', 'foo', 'name']
    Before foo, self.name = Jake
    After foo, self.name = John
    John


    I will walk you through this code. When we first create bar, the __init__() method is called. Here we print the contents of the object using dir(self). The output ['__doc__', '__init__', '__module__', 'foo'] indicates that the object has only one member, the 'foo' method.



    Now we create a new attribute called 'name' and assign it the value 'Jake'. Thus the object now has another member, the 'name' attribute as seen by the output of the next dir(self) ['__doc__', '__init__', '__module__', 'foo', 'name']



    Now we call the foo method and print the value before and after the method. Before the name is changed in foo, the value of name associated with the object is "Jake". However, after the name is changed, the value of self.name is "John". This is indicated by



    Before foo, self.name = Jake
    After foo, self.name = John`


    We next verify that the change made by changing self.name has indeed changed the value of name in bar by printing bar.name which gives us the expected output, John



    Now coming back to your question, self.name is not an ordinary variable inside some method that is lost when we are out of scope. self can be used essentially anywhere inside the class to refer to the calling object (bar in this case). It is used to manipulate this calling object. Now since bar is within the scope, we are able to print its name attribute.




    In normal functions any variables are forgotten but in methods it
    seems data is actually appended to the object itself




    self manipulates the attributes in the object and is not limited to the scope of the method.







    share|improve this answer












    share|improve this answer



    share|improve this answer










    answered Nov 25 at 8:04









    Piyush Saravagi

    1596




    1596








    • 1




      Thank you very much for the detailed answer. I look forward to reading through the article about understanding self. Your point of self.variable being the same as object.variable also clicked in my head, as did the extremely detailed code breakdown. I was not familiar with the using the dir() function with objects, but I will be using it frequently now. Also your point of: self.name is not an ordinary variable, self.name can be used essentially anywhere inside the class to refer to the calling object. That sentence was extremely helpful in understanding this, thank you.
      – Matt
      Nov 25 at 8:48














    • 1




      Thank you very much for the detailed answer. I look forward to reading through the article about understanding self. Your point of self.variable being the same as object.variable also clicked in my head, as did the extremely detailed code breakdown. I was not familiar with the using the dir() function with objects, but I will be using it frequently now. Also your point of: self.name is not an ordinary variable, self.name can be used essentially anywhere inside the class to refer to the calling object. That sentence was extremely helpful in understanding this, thank you.
      – Matt
      Nov 25 at 8:48








    1




    1




    Thank you very much for the detailed answer. I look forward to reading through the article about understanding self. Your point of self.variable being the same as object.variable also clicked in my head, as did the extremely detailed code breakdown. I was not familiar with the using the dir() function with objects, but I will be using it frequently now. Also your point of: self.name is not an ordinary variable, self.name can be used essentially anywhere inside the class to refer to the calling object. That sentence was extremely helpful in understanding this, thank you.
    – Matt
    Nov 25 at 8:48




    Thank you very much for the detailed answer. I look forward to reading through the article about understanding self. Your point of self.variable being the same as object.variable also clicked in my head, as did the extremely detailed code breakdown. I was not familiar with the using the dir() function with objects, but I will be using it frequently now. Also your point of: self.name is not an ordinary variable, self.name can be used essentially anywhere inside the class to refer to the calling object. That sentence was extremely helpful in understanding this, thank you.
    – Matt
    Nov 25 at 8:48












    up vote
    5
    down vote













    First, you don't have to return a value in a method, not in python, and not in many other programming languages. for example:



    def append_a(lst):
    lst.append('a')

    bob =
    append_a(bob)
    print(bob)
    ['a']


    Above we do not return anything in the function, but we use it to modify an existing data structure, this is very common almost anywhere.



    Secondly, in your second example, you created an instance of the class Example, when you look at self.something you are looking at a member of the class, unlike other languages, where often members are only declared once, in python you can dynamically add members.

    Thus when looking at bar.name you are looking at a member of the class, its value on the instance bar. If you would look at a different instance, the value will be different.



    class Example:

    def __init__(self, name):
    self.name = name

    def foo(self):
    self.name = 'John'

    bar = Example('Jake')
    bob = Example('Bob')
    bar.foo()
    print(bar.name)
    print(bob.name)

    John
    Bob





    share|improve this answer





















    • Thank you for your answer. You are right, I forgot about functions being able to do things outside of their namespace, like appending lists. Also that is a good point about instances being unique and 'self' referencing the instance of the class, it helped clear things up in my head.
      – Matt
      Nov 25 at 8:39















    up vote
    5
    down vote













    First, you don't have to return a value in a method, not in python, and not in many other programming languages. for example:



    def append_a(lst):
    lst.append('a')

    bob =
    append_a(bob)
    print(bob)
    ['a']


    Above we do not return anything in the function, but we use it to modify an existing data structure, this is very common almost anywhere.



    Secondly, in your second example, you created an instance of the class Example, when you look at self.something you are looking at a member of the class, unlike other languages, where often members are only declared once, in python you can dynamically add members.

    Thus when looking at bar.name you are looking at a member of the class, its value on the instance bar. If you would look at a different instance, the value will be different.



    class Example:

    def __init__(self, name):
    self.name = name

    def foo(self):
    self.name = 'John'

    bar = Example('Jake')
    bob = Example('Bob')
    bar.foo()
    print(bar.name)
    print(bob.name)

    John
    Bob





    share|improve this answer





















    • Thank you for your answer. You are right, I forgot about functions being able to do things outside of their namespace, like appending lists. Also that is a good point about instances being unique and 'self' referencing the instance of the class, it helped clear things up in my head.
      – Matt
      Nov 25 at 8:39













    up vote
    5
    down vote










    up vote
    5
    down vote









    First, you don't have to return a value in a method, not in python, and not in many other programming languages. for example:



    def append_a(lst):
    lst.append('a')

    bob =
    append_a(bob)
    print(bob)
    ['a']


    Above we do not return anything in the function, but we use it to modify an existing data structure, this is very common almost anywhere.



    Secondly, in your second example, you created an instance of the class Example, when you look at self.something you are looking at a member of the class, unlike other languages, where often members are only declared once, in python you can dynamically add members.

    Thus when looking at bar.name you are looking at a member of the class, its value on the instance bar. If you would look at a different instance, the value will be different.



    class Example:

    def __init__(self, name):
    self.name = name

    def foo(self):
    self.name = 'John'

    bar = Example('Jake')
    bob = Example('Bob')
    bar.foo()
    print(bar.name)
    print(bob.name)

    John
    Bob





    share|improve this answer












    First, you don't have to return a value in a method, not in python, and not in many other programming languages. for example:



    def append_a(lst):
    lst.append('a')

    bob =
    append_a(bob)
    print(bob)
    ['a']


    Above we do not return anything in the function, but we use it to modify an existing data structure, this is very common almost anywhere.



    Secondly, in your second example, you created an instance of the class Example, when you look at self.something you are looking at a member of the class, unlike other languages, where often members are only declared once, in python you can dynamically add members.

    Thus when looking at bar.name you are looking at a member of the class, its value on the instance bar. If you would look at a different instance, the value will be different.



    class Example:

    def __init__(self, name):
    self.name = name

    def foo(self):
    self.name = 'John'

    bar = Example('Jake')
    bob = Example('Bob')
    bar.foo()
    print(bar.name)
    print(bob.name)

    John
    Bob






    share|improve this answer












    share|improve this answer



    share|improve this answer










    answered Nov 25 at 7:03









    Dinari

    1,231322




    1,231322












    • Thank you for your answer. You are right, I forgot about functions being able to do things outside of their namespace, like appending lists. Also that is a good point about instances being unique and 'self' referencing the instance of the class, it helped clear things up in my head.
      – Matt
      Nov 25 at 8:39


















    • Thank you for your answer. You are right, I forgot about functions being able to do things outside of their namespace, like appending lists. Also that is a good point about instances being unique and 'self' referencing the instance of the class, it helped clear things up in my head.
      – Matt
      Nov 25 at 8:39
















    Thank you for your answer. You are right, I forgot about functions being able to do things outside of their namespace, like appending lists. Also that is a good point about instances being unique and 'self' referencing the instance of the class, it helped clear things up in my head.
    – Matt
    Nov 25 at 8:39




    Thank you for your answer. You are right, I forgot about functions being able to do things outside of their namespace, like appending lists. Also that is a good point about instances being unique and 'self' referencing the instance of the class, it helped clear things up in my head.
    – Matt
    Nov 25 at 8:39










    up vote
    3
    down vote













    There isn't a lot of difference between methods and functions (See this thread for details)



    Though one important distinction, that you might have immediately noticed, is that methods have self as their first argument and we say that method foo is "bound" to instance bar of class Example, meaning simply that foo will be called with its first argument (self) as the instance (bar) itself



    With this knowledge lets see what the following function does:



    class Example:

    def __init__(self, name):
    self.name = name

    def foo(self):
    self.name = 'John'

    bar = Example('Jake')


    In method init, you assign name to self. But what is self? It is bar itself, so calling init can be thought of as doing



    bar.name = 'Jake'


    Then when you called method foo



    bar.foo()


    You equivalently did



    bar.name = 'John'


    So, it should not be surprising when finally the output of the following was 'John'



    print(bar.name)  # John


    About your query regarding methods not having to return anything, it is not quite so. Methods and functions may or may not return anything as (See this answer). But in this context, what is happening is an object passed to a method is being manipulated (self, which is bar, is being assigned a name) and because the object is alive after the method call completes, we can observe the changes done by the method (ie, we can see that bar.name is changed to 'John')



    This works works with functions as well:



    def another_foo(self):
    self.name = 'Mark'
    baz = Example('Jake')
    another_foo(baz)
    print(baz.name) # Mark


    You see, this function did not return anything either. It worked just like the method foo by manipulating its argument. In fact, you could add it to the Example class and use it like a method



    Example.another_foo = another_foo
    new_bar = Example('Jake')
    print(new_bar.name) # Jake
    new_bar.another_foo()
    print(new_bar.name) # Mark





    share|improve this answer

























      up vote
      3
      down vote













      There isn't a lot of difference between methods and functions (See this thread for details)



      Though one important distinction, that you might have immediately noticed, is that methods have self as their first argument and we say that method foo is "bound" to instance bar of class Example, meaning simply that foo will be called with its first argument (self) as the instance (bar) itself



      With this knowledge lets see what the following function does:



      class Example:

      def __init__(self, name):
      self.name = name

      def foo(self):
      self.name = 'John'

      bar = Example('Jake')


      In method init, you assign name to self. But what is self? It is bar itself, so calling init can be thought of as doing



      bar.name = 'Jake'


      Then when you called method foo



      bar.foo()


      You equivalently did



      bar.name = 'John'


      So, it should not be surprising when finally the output of the following was 'John'



      print(bar.name)  # John


      About your query regarding methods not having to return anything, it is not quite so. Methods and functions may or may not return anything as (See this answer). But in this context, what is happening is an object passed to a method is being manipulated (self, which is bar, is being assigned a name) and because the object is alive after the method call completes, we can observe the changes done by the method (ie, we can see that bar.name is changed to 'John')



      This works works with functions as well:



      def another_foo(self):
      self.name = 'Mark'
      baz = Example('Jake')
      another_foo(baz)
      print(baz.name) # Mark


      You see, this function did not return anything either. It worked just like the method foo by manipulating its argument. In fact, you could add it to the Example class and use it like a method



      Example.another_foo = another_foo
      new_bar = Example('Jake')
      print(new_bar.name) # Jake
      new_bar.another_foo()
      print(new_bar.name) # Mark





      share|improve this answer























        up vote
        3
        down vote










        up vote
        3
        down vote









        There isn't a lot of difference between methods and functions (See this thread for details)



        Though one important distinction, that you might have immediately noticed, is that methods have self as their first argument and we say that method foo is "bound" to instance bar of class Example, meaning simply that foo will be called with its first argument (self) as the instance (bar) itself



        With this knowledge lets see what the following function does:



        class Example:

        def __init__(self, name):
        self.name = name

        def foo(self):
        self.name = 'John'

        bar = Example('Jake')


        In method init, you assign name to self. But what is self? It is bar itself, so calling init can be thought of as doing



        bar.name = 'Jake'


        Then when you called method foo



        bar.foo()


        You equivalently did



        bar.name = 'John'


        So, it should not be surprising when finally the output of the following was 'John'



        print(bar.name)  # John


        About your query regarding methods not having to return anything, it is not quite so. Methods and functions may or may not return anything as (See this answer). But in this context, what is happening is an object passed to a method is being manipulated (self, which is bar, is being assigned a name) and because the object is alive after the method call completes, we can observe the changes done by the method (ie, we can see that bar.name is changed to 'John')



        This works works with functions as well:



        def another_foo(self):
        self.name = 'Mark'
        baz = Example('Jake')
        another_foo(baz)
        print(baz.name) # Mark


        You see, this function did not return anything either. It worked just like the method foo by manipulating its argument. In fact, you could add it to the Example class and use it like a method



        Example.another_foo = another_foo
        new_bar = Example('Jake')
        print(new_bar.name) # Jake
        new_bar.another_foo()
        print(new_bar.name) # Mark





        share|improve this answer












        There isn't a lot of difference between methods and functions (See this thread for details)



        Though one important distinction, that you might have immediately noticed, is that methods have self as their first argument and we say that method foo is "bound" to instance bar of class Example, meaning simply that foo will be called with its first argument (self) as the instance (bar) itself



        With this knowledge lets see what the following function does:



        class Example:

        def __init__(self, name):
        self.name = name

        def foo(self):
        self.name = 'John'

        bar = Example('Jake')


        In method init, you assign name to self. But what is self? It is bar itself, so calling init can be thought of as doing



        bar.name = 'Jake'


        Then when you called method foo



        bar.foo()


        You equivalently did



        bar.name = 'John'


        So, it should not be surprising when finally the output of the following was 'John'



        print(bar.name)  # John


        About your query regarding methods not having to return anything, it is not quite so. Methods and functions may or may not return anything as (See this answer). But in this context, what is happening is an object passed to a method is being manipulated (self, which is bar, is being assigned a name) and because the object is alive after the method call completes, we can observe the changes done by the method (ie, we can see that bar.name is changed to 'John')



        This works works with functions as well:



        def another_foo(self):
        self.name = 'Mark'
        baz = Example('Jake')
        another_foo(baz)
        print(baz.name) # Mark


        You see, this function did not return anything either. It worked just like the method foo by manipulating its argument. In fact, you could add it to the Example class and use it like a method



        Example.another_foo = another_foo
        new_bar = Example('Jake')
        print(new_bar.name) # Jake
        new_bar.another_foo()
        print(new_bar.name) # Mark






        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered Nov 25 at 8:22









        rhino2rhonda

        317413




        317413






















            up vote
            2
            down vote













            Welcome to Stack Overflow. You are thinking in the right direction. I'll start at a more basic level so that other beginner viewers can understand what is going on.



            Think of Example as a template for creating new objects of a certain kind -- meaning the objects will all have the same attributes (also known as properties) and functionalities. For example, by drawing an analogy with real-life objects, all cars have the attribute "speed" and the functionality "accelerate".



            The attribute values will be specific to the objects. For example, one car will have 0 mph speed and another 70 mph.



            The attribute values at any point describe the state of an object. Methods, which you can think of as the object's functionalities, allow the ability to change an object's state.



            bar is an object that you created using the template (that is, class) Example. If you have to describe this object's state, you'd tell us the values of its attributes. In this case, the object has only one attribute: name.



            Now, this is the important part: name is not just any variable, it's an attribute of any object you make from the class Example. Think of name as always attached to the object. That's why you wrote self.name = 'John' and not name = 'John'. In the latter case, name would not be a part of the object bar, and no other method in the class would have access to the name variable.



            So, to summarize, when you have created an object out of a class, think of the object as having various attributes. All the methods, or functionalities, of the object will have access to all those attributes. The values of the attributes would describe, at any point, the object's state at that moment. It is through that object's methods that one would change its state.



            Finally, here's a great tool to visualize what happens at each line of your code: pythontutor.com






            share|improve this answer



















            • 1




              Thank you very much for your answer, it was extremely helpful. Your point of objects having a 'state' and methods being able to change this state (aka values) really clicked in my head. Also the distinction between self.name = 'John" and name = 'John' was also helpful in understanding the difference and use of self. Again thank you very much for your reply, I will definitely reference it again in the future.
              – Matt
              Nov 25 at 8:37















            up vote
            2
            down vote













            Welcome to Stack Overflow. You are thinking in the right direction. I'll start at a more basic level so that other beginner viewers can understand what is going on.



            Think of Example as a template for creating new objects of a certain kind -- meaning the objects will all have the same attributes (also known as properties) and functionalities. For example, by drawing an analogy with real-life objects, all cars have the attribute "speed" and the functionality "accelerate".



            The attribute values will be specific to the objects. For example, one car will have 0 mph speed and another 70 mph.



            The attribute values at any point describe the state of an object. Methods, which you can think of as the object's functionalities, allow the ability to change an object's state.



            bar is an object that you created using the template (that is, class) Example. If you have to describe this object's state, you'd tell us the values of its attributes. In this case, the object has only one attribute: name.



            Now, this is the important part: name is not just any variable, it's an attribute of any object you make from the class Example. Think of name as always attached to the object. That's why you wrote self.name = 'John' and not name = 'John'. In the latter case, name would not be a part of the object bar, and no other method in the class would have access to the name variable.



            So, to summarize, when you have created an object out of a class, think of the object as having various attributes. All the methods, or functionalities, of the object will have access to all those attributes. The values of the attributes would describe, at any point, the object's state at that moment. It is through that object's methods that one would change its state.



            Finally, here's a great tool to visualize what happens at each line of your code: pythontutor.com






            share|improve this answer



















            • 1




              Thank you very much for your answer, it was extremely helpful. Your point of objects having a 'state' and methods being able to change this state (aka values) really clicked in my head. Also the distinction between self.name = 'John" and name = 'John' was also helpful in understanding the difference and use of self. Again thank you very much for your reply, I will definitely reference it again in the future.
              – Matt
              Nov 25 at 8:37













            up vote
            2
            down vote










            up vote
            2
            down vote









            Welcome to Stack Overflow. You are thinking in the right direction. I'll start at a more basic level so that other beginner viewers can understand what is going on.



            Think of Example as a template for creating new objects of a certain kind -- meaning the objects will all have the same attributes (also known as properties) and functionalities. For example, by drawing an analogy with real-life objects, all cars have the attribute "speed" and the functionality "accelerate".



            The attribute values will be specific to the objects. For example, one car will have 0 mph speed and another 70 mph.



            The attribute values at any point describe the state of an object. Methods, which you can think of as the object's functionalities, allow the ability to change an object's state.



            bar is an object that you created using the template (that is, class) Example. If you have to describe this object's state, you'd tell us the values of its attributes. In this case, the object has only one attribute: name.



            Now, this is the important part: name is not just any variable, it's an attribute of any object you make from the class Example. Think of name as always attached to the object. That's why you wrote self.name = 'John' and not name = 'John'. In the latter case, name would not be a part of the object bar, and no other method in the class would have access to the name variable.



            So, to summarize, when you have created an object out of a class, think of the object as having various attributes. All the methods, or functionalities, of the object will have access to all those attributes. The values of the attributes would describe, at any point, the object's state at that moment. It is through that object's methods that one would change its state.



            Finally, here's a great tool to visualize what happens at each line of your code: pythontutor.com






            share|improve this answer














            Welcome to Stack Overflow. You are thinking in the right direction. I'll start at a more basic level so that other beginner viewers can understand what is going on.



            Think of Example as a template for creating new objects of a certain kind -- meaning the objects will all have the same attributes (also known as properties) and functionalities. For example, by drawing an analogy with real-life objects, all cars have the attribute "speed" and the functionality "accelerate".



            The attribute values will be specific to the objects. For example, one car will have 0 mph speed and another 70 mph.



            The attribute values at any point describe the state of an object. Methods, which you can think of as the object's functionalities, allow the ability to change an object's state.



            bar is an object that you created using the template (that is, class) Example. If you have to describe this object's state, you'd tell us the values of its attributes. In this case, the object has only one attribute: name.



            Now, this is the important part: name is not just any variable, it's an attribute of any object you make from the class Example. Think of name as always attached to the object. That's why you wrote self.name = 'John' and not name = 'John'. In the latter case, name would not be a part of the object bar, and no other method in the class would have access to the name variable.



            So, to summarize, when you have created an object out of a class, think of the object as having various attributes. All the methods, or functionalities, of the object will have access to all those attributes. The values of the attributes would describe, at any point, the object's state at that moment. It is through that object's methods that one would change its state.



            Finally, here's a great tool to visualize what happens at each line of your code: pythontutor.com







            share|improve this answer














            share|improve this answer



            share|improve this answer








            edited Nov 25 at 10:17

























            answered Nov 25 at 7:57









            ba_ul

            61111126




            61111126








            • 1




              Thank you very much for your answer, it was extremely helpful. Your point of objects having a 'state' and methods being able to change this state (aka values) really clicked in my head. Also the distinction between self.name = 'John" and name = 'John' was also helpful in understanding the difference and use of self. Again thank you very much for your reply, I will definitely reference it again in the future.
              – Matt
              Nov 25 at 8:37














            • 1




              Thank you very much for your answer, it was extremely helpful. Your point of objects having a 'state' and methods being able to change this state (aka values) really clicked in my head. Also the distinction between self.name = 'John" and name = 'John' was also helpful in understanding the difference and use of self. Again thank you very much for your reply, I will definitely reference it again in the future.
              – Matt
              Nov 25 at 8:37








            1




            1




            Thank you very much for your answer, it was extremely helpful. Your point of objects having a 'state' and methods being able to change this state (aka values) really clicked in my head. Also the distinction between self.name = 'John" and name = 'John' was also helpful in understanding the difference and use of self. Again thank you very much for your reply, I will definitely reference it again in the future.
            – Matt
            Nov 25 at 8:37




            Thank you very much for your answer, it was extremely helpful. Your point of objects having a 'state' and methods being able to change this state (aka values) really clicked in my head. Also the distinction between self.name = 'John" and name = 'John' was also helpful in understanding the difference and use of self. Again thank you very much for your reply, I will definitely reference it again in the future.
            – Matt
            Nov 25 at 8:37










            up vote
            1
            down vote













            Well, this is what is called as 'scoping' in OOP. And though the difference between classes and functions might seem subtle, it makes a big difference.



            Simply said, functions rely on global and local variables. Global variables are objects that you define in the global workspace. This is like having a workbench and getting to use a common object across your functions and classes that you define. And so, for example, if you modify your function foo() to include an argument, like so:



            a = 3 # This is globally defined

            def foo(a):
            a = 3 * a
            return a

            print(foo(a))
            9


            Changing the global value of a to something like 2 will give you 6 as the answer. We 'return' an object because it is locally defined within the scope of a function. In this example above, foo() performs the local operation 3 * a and defines it locally to a itself and returns it. And so you can also skip the global variable a when executing foo() and define it locally within the function scope:



            print(foo(6)) # Locally defined
            18

            print(a)
            3 # Returns global variable


            Classes on the other hand need to be declared and that has been very nicely explained by members (see above).






            share|improve this answer























            • Thank you for your answer, your point about global variables being like a workbench available across all functions and classes really helped clarify this, as did about variables being locally defined versus globally defined. This was very helpful.
              – Matt
              Nov 25 at 8:54










            • Thank you. And welcome to SO. Your question was very good and will hopefully stay as a very nice tutorial to classes and methods!
              – Shiv_90
              Nov 25 at 13:24

















            up vote
            1
            down vote













            Well, this is what is called as 'scoping' in OOP. And though the difference between classes and functions might seem subtle, it makes a big difference.



            Simply said, functions rely on global and local variables. Global variables are objects that you define in the global workspace. This is like having a workbench and getting to use a common object across your functions and classes that you define. And so, for example, if you modify your function foo() to include an argument, like so:



            a = 3 # This is globally defined

            def foo(a):
            a = 3 * a
            return a

            print(foo(a))
            9


            Changing the global value of a to something like 2 will give you 6 as the answer. We 'return' an object because it is locally defined within the scope of a function. In this example above, foo() performs the local operation 3 * a and defines it locally to a itself and returns it. And so you can also skip the global variable a when executing foo() and define it locally within the function scope:



            print(foo(6)) # Locally defined
            18

            print(a)
            3 # Returns global variable


            Classes on the other hand need to be declared and that has been very nicely explained by members (see above).






            share|improve this answer























            • Thank you for your answer, your point about global variables being like a workbench available across all functions and classes really helped clarify this, as did about variables being locally defined versus globally defined. This was very helpful.
              – Matt
              Nov 25 at 8:54










            • Thank you. And welcome to SO. Your question was very good and will hopefully stay as a very nice tutorial to classes and methods!
              – Shiv_90
              Nov 25 at 13:24















            up vote
            1
            down vote










            up vote
            1
            down vote









            Well, this is what is called as 'scoping' in OOP. And though the difference between classes and functions might seem subtle, it makes a big difference.



            Simply said, functions rely on global and local variables. Global variables are objects that you define in the global workspace. This is like having a workbench and getting to use a common object across your functions and classes that you define. And so, for example, if you modify your function foo() to include an argument, like so:



            a = 3 # This is globally defined

            def foo(a):
            a = 3 * a
            return a

            print(foo(a))
            9


            Changing the global value of a to something like 2 will give you 6 as the answer. We 'return' an object because it is locally defined within the scope of a function. In this example above, foo() performs the local operation 3 * a and defines it locally to a itself and returns it. And so you can also skip the global variable a when executing foo() and define it locally within the function scope:



            print(foo(6)) # Locally defined
            18

            print(a)
            3 # Returns global variable


            Classes on the other hand need to be declared and that has been very nicely explained by members (see above).






            share|improve this answer














            Well, this is what is called as 'scoping' in OOP. And though the difference between classes and functions might seem subtle, it makes a big difference.



            Simply said, functions rely on global and local variables. Global variables are objects that you define in the global workspace. This is like having a workbench and getting to use a common object across your functions and classes that you define. And so, for example, if you modify your function foo() to include an argument, like so:



            a = 3 # This is globally defined

            def foo(a):
            a = 3 * a
            return a

            print(foo(a))
            9


            Changing the global value of a to something like 2 will give you 6 as the answer. We 'return' an object because it is locally defined within the scope of a function. In this example above, foo() performs the local operation 3 * a and defines it locally to a itself and returns it. And so you can also skip the global variable a when executing foo() and define it locally within the function scope:



            print(foo(6)) # Locally defined
            18

            print(a)
            3 # Returns global variable


            Classes on the other hand need to be declared and that has been very nicely explained by members (see above).







            share|improve this answer














            share|improve this answer



            share|improve this answer








            edited Nov 25 at 13:25

























            answered Nov 25 at 7:27









            Shiv_90

            7210




            7210












            • Thank you for your answer, your point about global variables being like a workbench available across all functions and classes really helped clarify this, as did about variables being locally defined versus globally defined. This was very helpful.
              – Matt
              Nov 25 at 8:54










            • Thank you. And welcome to SO. Your question was very good and will hopefully stay as a very nice tutorial to classes and methods!
              – Shiv_90
              Nov 25 at 13:24




















            • Thank you for your answer, your point about global variables being like a workbench available across all functions and classes really helped clarify this, as did about variables being locally defined versus globally defined. This was very helpful.
              – Matt
              Nov 25 at 8:54










            • Thank you. And welcome to SO. Your question was very good and will hopefully stay as a very nice tutorial to classes and methods!
              – Shiv_90
              Nov 25 at 13:24


















            Thank you for your answer, your point about global variables being like a workbench available across all functions and classes really helped clarify this, as did about variables being locally defined versus globally defined. This was very helpful.
            – Matt
            Nov 25 at 8:54




            Thank you for your answer, your point about global variables being like a workbench available across all functions and classes really helped clarify this, as did about variables being locally defined versus globally defined. This was very helpful.
            – Matt
            Nov 25 at 8:54












            Thank you. And welcome to SO. Your question was very good and will hopefully stay as a very nice tutorial to classes and methods!
            – Shiv_90
            Nov 25 at 13:24






            Thank you. And welcome to SO. Your question was very good and will hopefully stay as a very nice tutorial to classes and methods!
            – Shiv_90
            Nov 25 at 13:24




















            draft saved

            draft discarded




















































            Thanks for contributing an answer to Stack Overflow!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid



            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.


            To learn more, see our tips on writing great answers.





            Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


            Please pay close attention to the following guidance:


            • Please be sure to answer the question. Provide details and share your research!

            But avoid



            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.


            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53465251%2fwhy-do-you-not-have-to-return-objects-in-python%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            Popular posts from this blog

            Quarter-circle Tiles

            build a pushdown automaton that recognizes the reverse language of a given pushdown automaton?

            Mont Emei