views:

565

answers:

5

Are there any declaration keywords in python, like local, global, private, public etc. I know it's type free but how do you know if this statement:

x = 5;
  • Creates a new variable.

or

  • Sets an existing one.
+15  A: 

An important thing to understand about Python is there are no variables, only "names".

In your example, you have an object "5" and you are creating a name "x" that references the object "5".

If later you do:

x = "Some string"

that is still perfectly valid. Name "x" is now pointing to object "Some string".

It's not a conflict of types because the name itself doesn't have a type, only the object.

If you try x = 5 + "Some string" you will get a type error because you can't add two incompatible types.

In other words, it's not type free. Python objects are strongly typed.

Here are some very good discussions about Python typing:

Edit: to finish tying this in with your question, a name can reference an existing object or a new one.

# Create a new int object
>>> x = 500
# Another name to same object
>>> y = x
# Create another new int object    
>>> x = 600
# y still references original object
>>> print y
500
# This doesn't update x, it creates a new object and x becomes
# a reference to the new int object (which is int because that
# is the defined result of adding to int objects).
>>> x = x + y
>>> print x
1100
# Make original int object 500 go away
>>> del y

Edit 2: The most complete discussion of the difference between mutable objects (that can be changed) and immutable objects (that cannot be changed) in the the official documentation of the Python Data Model.

Van Gale
These are good points but I think missing the question. The asker wants to ensure that they are not overwriting an existing object (like the "var" statement in javascript). They aren't trying to assign a type.
TM
Yes, you're right, and I meant to address that by leading in with the necessary intro to Python objects :) Editing my answer to finish that.
Van Gale
Actually integers are immutable there for `x = 500` could bind an existing integer object to `x` instead of creating a new one (`id(500) == id(x)`; id(250+250) may be equal id(x); `L=[]; id(L) != id([])). Literals for immutable objects (integers, strings) could be considered as fancy names.
J.F. Sebastian
+2  A: 

It doesn't look like the asker is trying to assign a type, just to specify that this a declaration, not an assignment.

Looks like you are looking for something like javascript has:

var x = 5;

The concept of the declaration keyword in javascript is to ensure that you are making a new object in the current scope and are not simply changing some other variable of the same name.

Python does not have this feature. The programmer has to make sure that he or she is not reassigning preexisting names.

TM
this will throw an exception if x is not in use already.
hop
My mistake! Corrected the problem.
TM
This is multiply wrong. If x isn't defined, you get NameError: name 'x' is not defined. If x is set to 0, False, [], (), "", set(), or other False value in a boolean context, it will fall through to the else block.
recursive
@recursive... you must have an old version of the page. I fixed about 5 minutes before your comment.
TM
+8  A: 

It's worth mentioning that there is a global keyword, so if you want to refer to the global x:

x = 4
def foo():
    x = 7 # x is local to your function

You need to do this:

x = 4
def foo():
    global x # let python know you want to use the top-level x
    x = 7
Dana
+7  A: 

I really like the understanding that Van Gale is providing, but it doesn't really answer the question of, "how do you know if this statement: creates a new variable or sets an existing variable?"

If you want to know how to recognize it when looking at code, you simply look for a previous assignment. Avoid global variables, which is good practice anyway, and you'll be all set.

Programmatically, you could try to reference the variable, and see if you get a "Name Error" exception

try:
    x
except NameError:
    # x doesn't exist, do something
else:
    # x exists, do something else

I've never needed to do this... and I doubt you will really need to either.

soapbox alert !!!

Even though Python looks kinda loosey-goosey to someone who is used to having to type the class name (or type) over and over and over... it's actually exactly as strict as you want to make it.

If you want strict types, you would do it explictly:

assert(isinstance(variable, type))

Decorators exist to do this in a very convenient way for function calls...

Before long, you might just come to the conclusion that static type checking (at compile time) doesn't actually make your code that much better. There's only a small benefit for the cost of having to have redundant type information all over the place.

I'm currently working in actionscript, and typing things like:

var win:ThingPicker = PopUpManager.createPopUp(fEmotionsButton, 
       ThingPicker, false) as ThingPicker;

which in python would look like:

win = createPopup(parent, ThingPicker)

And I can see, looking at the actionscript code, that there's simply no benefit to the static type-checking. The variable's lifetime is so short that I would have to be completely drunk to do the wrong thing with it... and have the compiler save me by pointing out a type error.

Jim Carroll
+1: thanks Jim. I hadn't caught that Joan could be asking about whether a name was already referencing an object, but if that's the case I second S. Lott's question, why? After more time to think about it I wish I had lead off with the mutability discussion instead of linking at the end.
Van Gale
@Van: Why? Can you tell me why not?
Joan Venge
@Joan: even Jim in his answer said it, "I've never needed to do this." And the reason is what I poorly explained in my answer.
Van Gale
Thanks I see. But how do you know if there is no global variable named x, y, or z already defined?
Joan Venge
@Joan: Python has lots of namespaces... in practice the variable you are thinking of as global is really in a module's namespace. The only place global really comes up is if you're at an interactive python prompt. In that case, you can just type >>> x (return) and see if you get a NameError.
Jim Carroll
@Jim +1 although I don't know that I would ever user assert anywhere... ever.
orokusaki
It's true... assert is kind of like an 'exploding comment' that you would not want to leave armed in production code... unless it was notifying people of a condition that was critical and needed to stop everything.
Jim Carroll
A: 

I just realized there's a more direct answer too:

x = 5

def test():
    print 'x' in globals()

if __name__ == "__main__":
    test()

So if 'variablename' in globals(): the statement is an assignment otherwise the statement is a declaration

Jim Carroll