5

I have a simple function, which I shall call myFunction. It takes two parameters, performs some calculations on them, and returns the result.

I also have a class, MyClass, which has a constructor that has a header like this:

__init__(self, bar, fun=myFunction):

When I try to run anything in this class, I get the following error:

MyClass
    def __init__(self, bar, fun=myFunction):
NameError: name 'myFunction' is not defined

If I remove this class, I can use myFun in the Python Shell, so what's the deal?

Tadeck
  • 132,510
  • 28
  • 152
  • 198
user1123936
  • 181
  • 3
  • 4
  • 14
  • Please mark proper answer as a solution. We choose solutions that way, not by telling what is the solution by editing the question. – Tadeck Jun 22 '12 at 23:55

2 Answers2

13

You haven't shown the actual code so it's hard to be sure, but I bet myFunction is defined after MyClass. The default value expression is evaluated when the __init__ method is defined, so myFunction must be defined at that point. Defining it later is too late.

Ned Batchelder
  • 364,293
  • 75
  • 561
  • 662
  • Wow, you're right. All I did was cut and paste myFunction so that it is above MyClass in that file, and now everything is fine. Python is weird. Thanks. – user1123936 Jun 22 '12 at 23:50
  • +1 Exactly. To achieve similar effect, you can assign `None` (or anything else, but it must be defined) as default argument and later compare and eventually assign the `myFunction` function (this assignment will be evaluated when the method is actually called). – Tadeck Jun 22 '12 at 23:51
  • 1
    @user1123936: Python is one of the simplest (not meaning it is not powerful), easiest, most consistent programming languages I have ever known. Probably he is first in all of the above, so if you could mention something better, I would be very grateful :) Really. – Tadeck Jun 22 '12 at 23:54
  • @user1123936 the problem is that Python tries to read the file down and parses everything *without* executing until it can't anymore (because it needs to do some sort of calculation to parse the rest). I don't know the exact rationale behind it, but it makes intuitive sense as a tradeoff: you want to be able to dynamically execute and change your code on the fly *without* compiling, but you also want to be able to optimize it where possible. – Jeff Tratner Jun 23 '12 at 00:19
  • @JeffTratner Python **does** execute as it reads. `def` *is a statement*. The `def my_function(): ...` block *is executed* when Python encounters it. The result of this execution is to create an object representing the code of the function, and assign it the name `my_function`. – Karl Knechtel Jun 23 '12 at 00:24
  • @JeffTratner: you are a bit confused about the semantics of Python files. A Python file is a series of statements. Each statement is executed in turn from the top of the file to the end. Period. `def` and `class` are both statements. They are just assignment statements with special syntax to define functions and classes. – Ned Batchelder Jun 23 '12 at 00:25
  • @NedBatchelder Thanks for the clarification. I thought there was something about how Python keeps reading down until it hits some "difficult" calculation, which is why some python scripts can reference things before they are defined. Is that never true? I feel like I've seen code that does this. – Jeff Tratner Jun 23 '12 at 01:20
  • You can never use a name before it's defined. Note that you can define a function that uses a name before the name is defined, because the name isn't used until the function is invoked. – Ned Batchelder Jun 23 '12 at 01:28
  • @NedBatchelder so basically, you can use not-yet-defined names within a function scope/block, but outside of that, every identifier/name must be defined before being used? – Jeff Tratner Jun 23 '12 at 01:38
  • Now I'm having a similar problem, I think. I declared a static variable: `bar = 0` at the top of my file. When I try to access it in a function it says it's not defined yet. `UnboundLocalError: local variable 'bar' reverenced before assignment` Any ideas? – user1123936 Jun 23 '12 at 01:52
  • @user1123936: I'll take another guess: you are trying to assign to `bar` inside the function, which makes it local throughout the function, so your first check of the value is accessing an UnboundLocal. Read up on the `global` statement. – Ned Batchelder Jun 23 '12 at 01:56
  • Thanks, that fixed everything. – user1123936 Jun 23 '12 at 02:05
-6

myFunction is a variable, not a value so you can't use it as a default parameter.

Maybe you could use a lambda function as the default parameter instead of the name of a declared function.

nickgroenke
  • 1,472
  • 9
  • 12
  • I did this exact same thing in another project though. MyClass and myFunction are actually both copied and pasted from there. – user1123936 Jun 22 '12 at 23:44
  • 3
    -1: Of course you are wrong (here: "_...is a variable, not a value so you can't use it as a default parameter..."). You can use anything you like as a default argument, but it (the assignment of this to the default argument) will be evaluated when the function (the one that has mentioned default argument) will be defined. – Tadeck Jun 22 '12 at 23:50