1
00:00:00,000 --> 00:00:06,990
Functions in Python are the primary unit of reusable code, even in objects.

2
00:00:07,000 --> 00:00:11,990
Object methods are simply functions that are properties of the objects.

3
00:00:12,000 --> 00:00:14,990
So let's look at how we define a function.

4
00:00:15,000 --> 00:00:22,990
We'll make a working copy of functions .py, call it functions-working.py and

5
00:00:23,000 --> 00:00:27,990
we'll go ahead and open that up and here we have a very simple function.

6
00:00:28,000 --> 00:00:33,990
It's called testfunc and it has one line of code in it.

7
00:00:34,000 --> 00:00:38,990
So if we run this, we see that that function gets run because it's

8
00:00:39,000 --> 00:00:40,990
getting called from main.

9
00:00:41,000 --> 00:00:43,990
Now, a few things to notice in this file.

10
00:00:44,000 --> 00:00:47,990
First of all, main is getting called down here.

11
00:00:48,000 --> 00:00:52,990
So main is a function just like any other function and it's simply getting

12
00:00:53,000 --> 00:00:54,990
called from the end of the file.

13
00:00:55,000 --> 00:00:57,990
The reason it's getting called from the end of the file is so that it can use

14
00:00:58,000 --> 00:01:01,990
things that are defined after it, like for instance, testfunc.

15
00:01:02,000 --> 00:01:10,990
If instead of calling main from the end of the file, if there is simply a call

16
00:01:11,000 --> 00:01:12,990
to testfunc from the top.

17
00:01:13,000 --> 00:01:13,990
that would not work.

18
00:01:14,000 --> 00:01:17,990
We'll save that and run it and you see we get NameError because name testfunc is

19
00:01:18,000 --> 00:01:22,990
not defined at the point where it was called.

20
00:01:23,000 --> 00:01:28,990
So in order for that to be defined first, we put it in a function and we call

21
00:01:29,000 --> 00:01:32,990
that function from the end. And so that's one of the reasons that we have this

22
00:01:33,000 --> 00:01:41,990
pattern at the end of the file that calls main and then main is defined at the top.

23
00:01:42,000 --> 00:01:48,990
It's also worth noting that we have to have some content in the suite after the colon.

24
00:01:49,000 --> 00:01:52,990
So if this were like this, def testfunc():

25
00:01:53,000 --> 00:01:58,990
like that and save it and run it, we're going to get an error, IndentationError.

26
00:01:59,000 --> 00:02:02,990
So it thinks that I have intended to put this inside the function, which would

27
00:02:03,000 --> 00:02:05,990
not work, because there is no body of the function.

28
00:02:06,000 --> 00:02:08,990
So there has to be something there.

29
00:02:09,000 --> 00:02:13,990
So if you're looking for a way to simply have a stub, if you're outlining some code

30
00:02:14,000 --> 00:02:17,990
and you just want to have a function definition without any body, there is

31
00:02:18,000 --> 00:02:22,990
the pass statement, which is essentially a NOOP.

32
00:02:23,000 --> 00:02:26,990
Save this and run it and now it works just fine, there's nothing happens, but

33
00:02:27,000 --> 00:02:31,990
pass is legal content that doesn't actually do anything.

34
00:02:32,000 --> 00:02:35,990
So you'll see that sometimes when people are working with things or explaining

35
00:02:36,000 --> 00:02:41,990
things or creating a code in Python. It's a placeholder. It's a stub.

36
00:02:42,000 --> 00:02:50,990
It's just there to make it syntactically correct but it doesn't actually do anything.

37
00:02:51,000 --> 00:02:56,990
If I want to pass an argument to my function, I can do that by putting an

38
00:02:57,000 --> 00:03:05,990
argument name here, call it number, and then I can print that out over here.

39
00:03:06,000 --> 00:03:09,990
So if I save this and run it, you see we have This is a test function 42.

40
00:03:10,000 --> 00:03:15,990
So the number is getting passed in during the function call and the number is

41
00:03:16,000 --> 00:03:20,990
getting picked up in this variable, which is defined in the function definition,

42
00:03:21,000 --> 00:03:24,990
and then I can use that in the body of the function itself.

43
00:03:25,000 --> 00:03:30,990
I could have another number and I could even have one more and I could pass

44
00:03:31,000 --> 00:03:40,990
those and I could use them down here.

45
00:03:41,000 --> 00:03:42,990
I save this and run it.

46
00:03:43,000 --> 00:03:44,990
Then we get all of those numbers.

47
00:03:45,000 --> 00:03:48,990
Because these are defined, they must be passed.

48
00:03:49,000 --> 00:03:57,990
If I don't pass all of them and I try to run that, you see I get a TypeError,

49
00:03:58,000 --> 00:04:01,990
testfunc() takes exactly 3 positional arguments (1 given).

50
00:04:02,000 --> 00:04:06,990
You might want to have some optional arguments and you can accomplish this by

51
00:04:07,000 --> 00:04:11,990
giving them default values.

52
00:04:12,000 --> 00:04:16,990
You give them default values by assigning values in the function definition.

53
00:04:17,000 --> 00:04:22,990
So now these arguments are optional and yet they'll still work inside the function.

54
00:04:23,000 --> 00:04:27,990
So if I save that and I run it, you see I've got the 43 and the 75 from in here

55
00:04:28,000 --> 00:04:32,990
and the 42 from there, but if I put a different number up here for the second one

56
00:04:33,000 --> 00:04:37,990
and I save that and I run it, then we get that value.

57
00:04:38,000 --> 00:04:43,990
Then the default value is not used and instead the value passed is used.

58
00:04:44,000 --> 00:04:47,990
The reason for this is that all the function arguments must have values

59
00:04:48,000 --> 00:04:52,990
assigned, so that when that function is called, what happens is predictable, not

60
00:04:53,000 --> 00:04:56,990
just to you the programmer but also to the compiler.

61
00:04:57,000 --> 00:04:59,990
And so they all must be initialized in one way or another.

62
00:05:00,000 --> 00:05:03,990
If you don't want it to have a default value but you still want the parameter to

63
00:05:04,000 --> 00:05:07,990
be optional, then you'll assign it explicitly the value None.

64
00:05:08,000 --> 00:05:12,990
And now when I save this and I run it, I'll have the value 16 there because I

65
00:05:13,000 --> 00:05:18,990
passed it, but now I cannot have that there and I can save it and I run it and

66
00:05:19,000 --> 00:05:21,990
I get the value None.

67
00:05:22,000 --> 00:05:25,990
None is a special value that you can actually test for.

68
00:05:26,000 --> 00:05:34,990
I can say, if another None, it's a singleton object and so identity is a good way

69
00:05:35,000 --> 00:05:41,990
to test for it. print. Or I can assign something to it. I can say another = 112

70
00:05:42,000 --> 00:05:48,990
and now when I save and I run, I get 112 here because I tested for None and

71
00:05:49,000 --> 00:05:55,990
that test was successful. But if I put something in here, 61, let's save that

72
00:05:56,000 --> 00:05:57,990
and run it, then we have the 61.

73
00:05:58,000 --> 00:06:02,990
So function arguments must be initialized in one way or another.

74
00:06:03,000 --> 00:06:06,990
Either they are going to be required or, if you want them to be optional, you

75
00:06:07,000 --> 00:06:08,990
have to assign them default values.

76
00:06:09,000 --> 00:06:13,990
The default value can be none and you can test for none, but it must be

77
00:06:14,000 --> 00:06:15,990
explicitly assigned.

78
00:06:16,000 --> 00:06:20,990
So that's fundamentally how you define a function and how you pass the

79
00:06:21,000 --> 00:06:31,000
arguments in Python.

