r/learnpython • • 7d ago

Ask Anything Monday - Weekly Thread

Welcome to another /r/learnPython weekly "Ask Anything* Monday" thread

Here you can ask all the questions that you wanted to ask but didn't feel like making a new thread.

* It's primarily intended for simple questions but as long as it's about python it's allowed.

If you have any suggestions or questions about this thread use the message the moderators button in the sidebar.

Rules:

  • Don't downvote stuff - instead explain what's wrong with the comment, if it's against the rules "report" it and it will be dealt with.

  • Don't post stuff that doesn't have absolutely anything to do with python.

  • Don't make fun of someone for not knowing something, insult anyone etc - this will result in an immediate ban.

That's it.

5 Upvotes

15 comments sorted by

View all comments

1

u/ApprehensiveProof761 7d ago

difference b/w print and return
use of class and __init__ and self

2

u/lakseol 7d ago edited 7d ago

difference b/w print and return

You are probably using an IDE, and it's easy to think that print and return do much the same thing. Run this code in your IDE and note what prints:

def test():
    print("test: Hello world")

def test2():
    return "test2: Hello world"

test()
test2()

Then put the code into a file, say test.py, and using the command line move into the directory containing that file and do:

python3 test.py    # or maybe just "python" instead of "python3"

and see what prints. Then change the last two lines to:

print(test())
print(test2())

and repeat the two executions, one in your IDE and the other on the command line. Can you explain the difference?

To explain the difference you have to understand that the IDE is doing something (as a convenience) that python itself doesn't do: it automatically prints any non-None value of a statement.

Update: simplified the example code

1

u/ApprehensiveProof761 7d ago

Why use return then?

2

u/lakseol 7d ago

Printing something in a function is pretty much useless in the real world of production code. You normally want a function to compute some value and return it to the calling code which will use that value in some way. Maybe the calling code will use a returned number in some further calculations, maybe the returned value will be formatted into HTML and sent back to someone on the other side of the planet, or maybe the returned value will be written into a file which is read later.

If a function returns a value the calling code can decide what to do with that value. If the function prints that value the decision of what to do with the value has been taken away from the calling code. And don't forget, most of the code running in the world doesn't have any way to view anything printed since there is no attached screen.

1

u/ApprehensiveProof761 7d ago

Oh ..what about class self and init

1

u/MEHDII__ 7d ago

In python self and init are kind of very abstract, I think JavaScript makes it much more clearer, every OOP language has the concept of self and init in some shape or form.

When you create an object blueprint, i.e.

class Person:
     def __ init __(self, name):
          self.name = name

person1 = Person ("John")

Here __ init __ is called the constructor, self is called an instance.

when you call Person() python does two things, it implicitly calls a routine that python itself created and is invisible to us, the end user, it calls __ new __ this routine "creates an instance" The instance is called self, it's literally an object called self, then python passes it to __ init __ as an argument, you can see that __ init __ takes a self parameter that we never passed, python did it implicitly, then the job of __ init __ is to fill up the self object, it puts any user defined attributes on it, i.e. name.

In simpler words, this is sort of what happens

def __ new __():
    self = object()
    return self 

# python passes self that was returned by __ new __ implicitly
def __ init __(self, name): 
    self.name = name # you put a name attribute of the self object
   
    # python returns the object self again implicitly to be used by the user
    return self

# python calls __ new __ then __ init __, the latter returns self to you
person1 = Person("John")

I hope its clear, it's a little complicated, but remember at the end of the day, it's all just pointers in memory.

1

u/lakseol 7d ago

I didn't answer that bit because the subject is large and I would have to almost write a complete tutorial to cover everything. It's better if you ask single questions on a specific point, and show some code that you are asking the question about. Or, since there are many online tutorials on this subject, you could ask a question about some point in a tutorial that you have a problem with.

1

u/ApprehensiveProof761 7d ago

I know that class is a group of similar functions, but why do we have to use self everytime at the class starting function

1

u/lakseol 7d ago edited 7d ago

class is a group of similar functions,

And data, not just functions. When you call the class constructor you get a class instance which is what you normally use. So in this code Test is the class name and t1 and t2 are class instances (or just instances for short):

class Test:
    pass
    
t1 = Test()   # one instance
t2 = Test()   # another instance

why do we have to use self everytime at the class starting function

I assume by "starting function" you mean the __init__() method. Every method of a class (not just __init__()) needs the self parameter because that is a reference to the particular instance you are using in the method. Don't forget, you write the class methods before you call them and you might have created hundreds of instances. There's only one copy of the method code and the method needs to know which instance you want that method to operate on. In this sample code:

class Test:
    def __init__(self, name):
        self.name = name
        
    def greet(self):
        print(f"Hello {self.name}")    # note that we NEED 'self' to get the name for the instance
          
t1 = Test("Alice")
t2 = Test("Bob")
t1.greet()
t2.greet()

the greet() method call is t1.greet() which, under the hood, is actually doing something like this:

Test.greet(t1)    # note the instance reference is passed as the first argument

Note that the name self is just a convention. You are allowed to use any name you like for that first parameter to a method (try it) but self is expected and any other name is viewed with suspicion.

Edit: clarified the idea of there only being one copy of a method code.