変数
いまさら説明するまでのことでもありませんが、変数とはデータの入れ物です。しかしPythonはC/C++やJavaなどと比べ違いがあります。
型宣言が不要

//C/C++
   int a = 123;
 

#Python
   a = 123
 
Pythonの方が簡単に記述できます。C/C++ではintにしようかshortにしようか?型宣言で悩むことがありますが、Pythonではありません。

C/C++では必要のなかったグローバル変数にglobal宣言が必要になります。

# -*- coding: utf-8 -*-
g_nAge = 28

def foo():
    g_nAge = 45
    print('foo:' , g_nAge)

def main():
    foo()
    print ('main', g_nAge)

if __name__ == "__main__":
    main()
結果

foo: 45
main 28

foo()でg_nAgeを45にしています。しかし、main()では28で初期値から変化していません。これはどういうことか?謎っぽい。C/C++ではこのようなことはありません。Python特有のことです。どういることか?
foo()で
g_nAge = 45
としていますが、グローバル変数g_nAgeに45を代入しているのではなくローカル変数g_nAgeを作成して45を代入します。グローバル変数g_nAge を書き換えていません。
foo()でグローバル変数g_nAgeを書き換えるには

# -*- coding: utf-8 -*-
g_nAge = 28

def foo():
    global g_nAge
    g_nAge = 45
    print('foo:' , g_nAge)

def main():
    foo()
    print ('main', g_nAge)

if __name__ == "__main__":
    main()
global g_nAge を記述することでg_nAgeをローカル変数として作成しないでグローバル変数のg_nAgeを使うと宣言します。結果は、

foo: 45
main 45
期待通りになりました。

変数はオブジェクト
オブジェクトと言われても何のこっちゃ?ですね。雲をつかむような話です。それではオブジェクトと以前のC言語による環境ではどうなっていたでしょうか?
文字列を定義して
char msg[] = "abc";
これをいろいろと使うには、
strXXXXのライブラリ関数で処理をします。文字列msgを処理するための関数strXXXは調べる必要があります。書籍やヘルプをみて調べるのは結構時間がかかります。 それに対しオブジェクトはデータとそれを操作する関数(メソッド)が一体となっているのでインテリセンスがデータを操作するメソッドを表示してくれます。

文字列strにピリオドを打つと文字列に関するメソッドがインテリセンスで表示されます。今回はreplaceを使ってみます。

# -*- coding: utf-8 -*-

def main():
    str = 'abc'
    print(str)
    str = str.replace('a', 'XYZ', 1) 
    print(str)
if __name__ == "__main__":
    main()
実行結果は

abc
XYZbc
aがXZに置き換えられました。

変数の七変化
Pythonの変数は型宣言をしません。これはタイプが楽な反面気を付けないと痛い目にあいます。

# -*- coding: utf-8 -*-

def main():
    str_a = 'Hello'
    print(str_a)

    str_a = 256
    print(str_a)

if __name__ == "__main__":
    main()
実行結果

Hello
256

文字型変数str_aにHelloを代入して表示する。ここまでは初歩の初歩です。
次にtr_aに256を代入して表示する。これも期待通りの表示をしています。しかし、この256は文字列なのでしょうか?整数型なおでしょうか?変数はオブジェクトであると先ほどに説明しました。調べてみます。

 # -*- coding: utf-8 -*-

def main():
    str_a = 'Hello'
    print(str_a)
    attr = str_a.__getattribute__
    print(attr)

    str_a = 256
    print(str_a)
    attr = str_a.__getattribute__
    print(attr)

if __name__ == "__main__":
    main()

結果は、

Hello
<method-wrapper '__getattribute__' of str object at 0x0000023C1E89A570>
256
<method-wrapper '__getattribute__' of int object at 0x00007FFFCD9090F0>

Helloは文字型は当然ですが、256は整数型になっています。
文字型から整数型に変化です。さらに整数型から他の型になんぼでも変化できます。これは次のような間違いが容易におこります。特に複数人で開発をするとき、年齢を入れる変数に誤って名前を入れてしまった。間違ったデータに代入してもその人作った関数では正解となる。しかし、重要なデータを壊してしまった。というが案外あります。C言語などでは整数型に文字列を代入するとコンパイルエラーになるのですぐわかります。

特にグローバル変数には注意が必要です。