Python Variable Declaration
Asked Answered
L

7

114

I want to clarify how variables are declared in Python.

  1. I have seen variable declaration as
class writer:
     path = ""

sometimes, there is no explicit declaration but just initialization using __init__:

def __init__(self, name):
    self.name = name

I understand the purpose of __init__, but is it advisable to declare variable in any other functions?

  1. How can I create a variable to hold a custom type?
class writer:
    path = "" # string value
    customObj = ??
Laue answered 13/6, 2012 at 2:54 Comment(10)
And, concerning the 2nd question: in Python, variables don't have type: values do. So any variable can hold your custom objects.Kooky
It will help if you stop thinking of names/idendifiers as being variables. They are references to objectsChafin
@gnibbler Or names for them...Katherine
@detly, I think names is a bad choice. Things usually have just one name whereas an object may have multiple referencesChafin
@gnibbler True. I remember seeing a nifty pictorial explanation, with boxes and labels, but I can't find it right now.Katherine
@Katherine python.net/~goodger/projects/pycon/2007/idiomatic/…Jell
@JohnLaRooy I'm inclined to disagree with that statement on account of Henry McCarty alias Henry Antrim alias Kid Antrim alias William H. Bonney a.k.a Billy the Kid. And, Tellus alias Gaia alias Terra alias Mother Earth alias Earth a.k.a Third Rock From the Sun.Revolutionize
@JohnLaRooy think of math class. Teacher: "let x be three. Let y be three". Student: "no, you can't have two names for the same thing." I think not.Mcpeak
@JohnClements, but python doesn't work like math. If you want to understand python you need to know that objects with a __name__ attribute have a "name". Not all objects have a __name__ attribute, but you can still have references to them. If we start calling a "reference" a "name" we're doing beginners a disservice down the track.Chafin
See also: stackoverflow.com/questions/664294Futhark
F
237

Okay, first things first.

There is no such thing as "variable declaration" or "variable initialization" in Python.

There is simply what we call "assignment", but should probably just call "naming".

Assignment means "this name on the left-hand side now refers to the result of evaluating the right-hand side, regardless of what it referred to before (if anything)".

foo = 'bar' # the name 'foo' is now a name for the string 'bar'
foo = 2 * 3 # the name 'foo' stops being a name for the string 'bar',
# and starts being a name for the integer 6, resulting from the multiplication

As such, Python's names (a better term than "variables", arguably) don't have associated types; the values do. You can re-apply the same name to anything regardless of its type, but the thing still has behaviour that's dependent upon its type. The name is simply a way to refer to the value (object). This answers your second question: You don't create variables to hold a custom type. You don't create variables to hold any particular type. You don't "create" variables at all. You give names to objects.

Second point: Python follows a very simple rule when it comes to classes, that is actually much more consistent than what languages like Java, C++ and C# do: everything declared inside the class block is part of the class. So, functions (def) written here are methods, i.e. part of the class object (not stored on a per-instance basis), just like in Java, C++ and C#; but other names here are also part of the class. Again, the names are just names, and they don't have associated types, and functions are objects too in Python. Thus:

class Example:
    data = 42
    def method(self): pass

Classes are objects too, in Python.

So now we have created an object named Example, which represents the class of all things that are Examples. This object has two user-supplied attributes (In C++, "members"; in C#, "fields or properties or methods"; in Java, "fields or methods"). One of them is named data, and it stores the integer value 42. The other is named method, and it stores a function object. (There are several more attributes that Python adds automatically.)

These attributes still aren't really part of the object, though. Fundamentally, an object is just a bundle of more names (the attribute names), until you get down to things that can't be divided up any more. Thus, values can be shared between different instances of a class, or even between objects of different classes, if you deliberately set that up.

Let's create an instance:

x = Example()

Now we have a separate object named x, which is an instance of Example. The data and method are not actually part of the object, but we can still look them up via x because of some magic that Python does behind the scenes. When we look up method, in particular, we will instead get a "bound method" (when we call it, x gets passed automatically as the self parameter, which cannot happen if we look up Example.method directly).

What happens when we try to use x.data?

When we examine it, it's looked up in the object first. If it's not found in the object, Python looks in the class.

However, when we assign to x.data, Python will create an attribute on the object. It will not replace the class' attribute.

This allows us to do object initialization. Python will automatically call the class' __init__ method on new instances when they are created, if present. In this method, we can simply assign to attributes to set initial values for that attribute on each object:

class Example:
    name = "Ignored"
    def __init__(self, name):
        self.name = name
    # rest as before

Now we must specify a name when we create an Example, and each instance has its own name. Python will ignore the class attribute Example.name whenever we look up the .name of an instance, because the instance's attribute will be found first.

One last caveat: modification (mutation) and assignment are different things!

In Python, strings are immutable. They cannot be modified. When you do:

a = 'hi '
b = a
a += 'mom'

You do not change the original 'hi ' string. That is impossible in Python. Instead, you create a new string 'hi mom', and cause a to stop being a name for 'hi ', and start being a name for 'hi mom' instead. We made b a name for 'hi ' as well, and after re-applying the a name, b is still a name for 'hi ', because 'hi ' still exists and has not been changed.

But lists can be changed:

a = [1, 2, 3]
b = a
a += [4]

Now b is [1, 2, 3, 4] as well, because we made b a name for the same thing that a named, and then we changed that thing. We did not create a new list for a to name, because Python simply treats += differently for lists.

This matters for objects because if you had a list as a class attribute, and used an instance to modify the list, then the change would be "seen" in all other instances. This is because (a) the data is actually part of the class object, and not any instance object; (b) because you were modifying the list and not doing a simple assignment, you did not create a new instance attribute hiding the class attribute.

Futhark answered 13/6, 2012 at 4:43 Comment(9)
This is why we call them 'identifiers'. :-)Albinus
@Karl_Knechtel in your string example in the end, what happens to 'hi' if we never name it as 'b'? Is this a memory leak?Willdon
@Willdon : no; Python uses garbage collection to free unreachable objectsMcpeak
> There is no such thing as "variable declaration" - I believe this might not be strictly true nowadays, since you can actually do something: type in Python without assigning anything to it. The next paragraph after this statement might also need some rewording because of that.Imes
I guess one would call this "name annotation" (It's called AnnAssign in AST), but I'm not sure how is it different from the general programming concept of declaring something.Imes
"since you can actually do something: type in Python without assigning anything to it." The thing is, it doesn't actually have an effect, except on function parameters (in which case it adds to the __annotations__ metadata for the function object). Doing x: int in global scope doesn't modify the globals dict, and doing inside a function doesn't change the function's compiled code or its metadata (e.g. the function's .__code__.co_nlocals isn't increased).Futhark
But sure, I suppose you could still call that a "declaration", it's just completely unnecessary (it only exists for the benefit of third-party tooling).Futhark
So how do you guarantee there are no typos? If I start with field = 6 and inadvertently type feild = 42 at some point, what's going to barf?Monophony
@Monophony You don't; those just become two separate variables naming separate values (rather than re-binding the first one). The problem caused by this (if any) depends on the rest of the code.Futhark
C
40

This might be 6 years late, but in Python 3.5 and above, you can give a hint about a variable type like this:

variable_name: type_name

or this:

variable_name # type: shinyType

This hint has no effect in the core Python interpreter, but many tools will use it to aid the programmer in writing correct code.

So in your case(if you have a CustomObject class defined), you can do:

customObj: CustomObject

See this or that for more info.

Cobweb answered 4/7, 2018 at 14:35 Comment(4)
That's not a declaration in the traditional sense, though, it's a hint, which static type checkers and IDEs might point out, but will still run and fail.Ecstatics
@Ecstatics It doesn't fail, though. What do you mean by "fail"?Cobweb
What I mean is if you do a: int and then do a='hello, world!' it will not fail, so it isn't declaring a to be an int and only ever an int. I should have said "it won't fail", my bad. If you did a: int, a='hello, world!', a=a+1 then that should fail at compilation in a static typed language.Ecstatics
In short: the line variable_name: type_name is only used by third-party type checkers. It has no effect on how (the reference implementation, at least) Python bytecode-compiles the code, and no effect at runtime.Futhark
K
24

There's no need to declare new variables in Python. If we're talking about variables in functions or modules, no declaration is needed. Just assign a value to a name where you need it: mymagic = "Magic". Variables in Python can hold values of any type, and you can't restrict that.

Your question specifically asks about classes, objects and instance variables though. The idiomatic way to create instance variables is in the __init__ method and nowhere else — while you could create new instance variables in other methods, or even in unrelated code, it's just a bad idea. It'll make your code hard to reason about or to maintain.

So for example:

class Thing(object):

    def __init__(self, magic):
        self.magic = magic

Easy. Now instances of this class have a magic attribute:

thingo = Thing("More magic")
# thingo.magic is now "More magic"

Creating variables in the namespace of the class itself leads to different behaviour altogether. It is functionally different, and you should only do it if you have a specific reason to. For example:

class Thing(object):

    magic = "Magic"

    def __init__(self):
        pass

Now try:

thingo = Thing()
Thing.magic = 1
# thingo.magic is now 1

Or:

class Thing(object):

    magic = ["More", "magic"]

    def __init__(self):
        pass

thing1 = Thing()
thing2 = Thing()
thing1.magic.append("here")
# thing1.magic AND thing2.magic is now ["More", "magic", "here"]

This is because the namespace of the class itself is different to the namespace of the objects created from it. I'll leave it to you to research that a bit more.

The take-home message is that idiomatic Python is to (a) initialise object attributes in your __init__ method, and (b) document the behaviour of your class as needed. You don't need to go to the trouble of full-blown Sphinx-level documentation for everything you ever write, but at least some comments about whatever details you or someone else might need to pick it up.

Katherine answered 13/6, 2012 at 3:38 Comment(0)
D
18

For scoping purpose, I use:

custom_object = None
Define answered 22/6, 2017 at 15:29 Comment(0)
R
1

Variables have scope, so yes it is appropriate to have variables that are specific to your function. You don't always have to be explicit about their definition; usually you can just use them. Only if you want to do something specific to the type of the variable, like append for a list, do you need to define them before you start using them. Typical example of this.

list = []
for i in stuff:
  list.append(i)

By the way, this is not really a good way to setup the list. It would be better to say:

list = [i for i in stuff] # list comprehension

...but I digress.

Your other question. The custom object should be a class itself.

class CustomObject(): # always capitalize the class name...this is not syntax, just style.
  pass
customObj = CustomObject()
Rottenstone answered 13/6, 2012 at 3:12 Comment(0)
M
0

As of Python 3, you can explicitly declare variables by type.

For instance, to declare an integer one can do it as follows:

x: int = 3

or:

def f(x: int):
    return x

see this question for more detailed info about it: Explicitly declaring a variable type in Python

Magnification answered 10/6, 2021 at 12:54 Comment(2)
What does this add over O. Aroesti's answer?Futhark
well....have you tried following the link I included at the end?Crosswise
A
-1

Here is a simple way to declare the variable in Python:

syntax :

variable_name = value

Example :

Name = "Rohan Kumar Bhoi"
ABC = 5
x = "Hello World !"

To print the value of a variable, simply use the print function and pass the variable name.

Example :

print(Name)

output :

Rohan Kumar Bhoi

Name = "Rohan Kumar Bhoi"
print(Name)

#output : Rohan Kumar Bhoi

Visit This Link to get more Information : computertipstricks.tech

Aerotherapeutics answered 1/6, 2023 at 7:47 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.