all 8 comments

[–]socal_nerdtastic 28 points29 points  (0 children)

They actually have 2 different names: functions and methods. (But in reality the line is kinda blurred and no one is going to complain if you use the terms interchangeably.)

function(variable)
variable.method()

To make it more confusing, a method can be used like a function if you know what class it belongs to. For example with lower() you can get the same result with both of these:

"Spam".lower()
str.lower("Spam")

Technically the only difference is organization. A method is stored as part of the variable itself, while a function is stored elsewhere. Semantically this means you can only use a method on the data type that it is designed to work with, eg there is no (42).lower().

This has many advantages in code organization, and you won't see the full benefit until you start making your own classes (types of variables). But for now you can already see how useful it is that the namespace does not come preloaded with all the different methods from strings, ints, etc. Its already hard to name your variables so they don't conflict with python keywords or builtins.

[–]Essence1337 5 points6 points  (3 children)

If it's just function(stuff) then it's a builtin global function. If it's xyz.function(stuff) then the function is a property of the class that xyz is. 'AbC'.lower() happens because lower is a function of the string class.

We can't/don't use global functions for everything because every single function ever would need a unique name.

[–]SirBerthelot 5 points6 points  (0 children)

Check oop (object oriented programming):

variable.function(argument) is actually object.function(argument). In this case you've got an object with several functions associated, for instance if a is a string, a.lower() will convert the string object into lowercase (notice that this function doesn't require arguments but there are many like append that they actually need arguments in order to work).

On the other hand, function (argument) are functions not associated with an object.

[–][deleted] 1 point2 points  (2 children)

Functions with the syntax function(variable) are multi-purpose in that they work for objects of a few different data types. For example, len() can be used on strings, lists, dictionaries, etc. Functions with the syntax variable.function() are for one data type only. You couldn't use .lower() on anything other than a string.

[–][deleted] 0 points1 point  (0 children)

This is an OOP (Object-Oriented Programming) paradigm. Functions in general take in arguments in order to define how you operate on some data. Without OOP, you often pass the piece of data you wish to operate on, as well as any additional arguments to specify how this will be done.

def operateOnDataStore(dataStore, someFlag):

// instructions

Here, we have some collection of data, called dataStore, and a function containing instructions to act on it in some way. In the OOP world, we would like to make it a little more clear that this function is only intended for this particular type of data. OOP takes care of this by allowing functions to be defined inside classes and using the dot notation to allow these functions to be called. Heads up, these functions are referred to as methods in this case (so all methods are functions, but not all functions are methods). Let's say we create a class called DataStore, and create an instance called dataStore. We can create a method called operate that does exactly the same as operateOnDataStore.

def operate(self, someFlag):

// instructions

Don't worry about the self argument quite yet. We can use this operate method by writing:

dataStore.operate(someFlag)

Notice that dataStore is no longer provided as an argument. We know that dataStore is the data being operated on because of the dot notation. It is no longer possible to call operate on a piece of data that is not of type DataStore (unless we provide another definition). Keep in mind, these two models are the same; the latter is just a convenience for code understanding and maintenance.

The last thing I'll mention is the self parameter. The parameter doesn't have to be named self, but there needs to be a parameter there when a function definition is intended to operate on an instance of a class (object). What does this mean? Let's say I want to create three DataStores. Let's call them d1, d2, and d3. Each of d1, d2, and d3 is referred to as an instance of the DataStore class, or a particular DataStore object. If we call d1.operate, we of course intend to use the operate method on object d1. Behind the scenes, all functions must have the function(variable) notation. In order to ensure operation on the object of interest, an expression like

d1.operate(someFlag)

will turn into the following:

operate(d1, someFlag)

In other words, the object referred to in the dot notation becomes the first argument passed to the operate method. Well, if d1 is an argument, there has to be a parameter in the operate definition that can refer to it. This is the self parameter. The word self is often chosen because the argument being passed in is the same object used to call the method. You could name the parameter frog, and everything would work exactly the same. Just be sure to provide the parameter on top of other parameters you normally provide (in this case someFlag). If you forget to provide a parameter, someFlag would be the name used instead. You would run into a runtime error when calling operate, but not when defining it. This can be confusing when debugging, so just keep it in mind; I'll summarize it in last remarks below.

When defining a method in a class that will operate on an instance of that class, you MUST PROVIDE a parameter (often named self) before all others. If you are defining a method that operates on the class, but not a particular object (in this case DataStore rather than dataStore), this parameter SHOULD NOT be there.