# Variables and Memory Part 2

### Mutable & Immutable

Python是一门动态类型语言，变量的类型依赖解释器的类型推导，可以通过关键字`type`来查看变量类型

``````a=10
type(a) #<class 'int'>
``````

``````a = "hello"
type(a) #<class 'str'>
``````

``````print(hex(id(a))) #x10c28eb90
a = 15
print(hex(id(a))) #0x10851fc30
``````

Immutable Mutable
Numbers(int, float, Booleans, etc) Lists
Strings Sets
Tuples Dictionaries
Frozen Sets User-Defined Classes
User-Defined Classes

``````#1 list是mutable的
my_list = [1,2,3]
print(hex(id(my_list))) #0x10ae13f48
my_list.append(4)
print(hex(id(my_list))) #0x10ae13f48
#2 string是immutable的
my_str = "123"
print(hex(id(my_str))) #0x10da15030
my_str += "4"
print(hex(id(my_str))) #0x10da15068
``````

### Shared References and Memory

``````a = 10  #0x10ac99130
b = a #0x10ac99130
``````

``````
#a,b同样指向同一片内存区域
a = 10 #0x10375e130
b = 10 #0x10375e130
```
```
``````
a=None #0x101031148
b=None #0x101031148
```
```

Python中的`None`对象也是共享内存的，所有被赋值为`None`的变量，它们所指向的内存地址相同

`None`表示某个变量的值为”empty”，类似JavaScript中的`Undefined`，也可以理解为该变量并没有被赋值。Python中，`None`是一个具体的Object，被Memory Manager管理

``````
a = [1,2,3]
b = a
a.append(4)
b #[1,2,3,4]
```
```
``````
a = [1,2,3] #0x103a74348
b = [1,2,3] #0x103a74488
```
```

### Variable Equality

Python中有两种Equality，一种是内存地址相同（identity），用`is`来表示，另一种是使用`==`表示两个对象的”值”（内部state）是否相同（equality），与之相对应的不等关系则用`is not``!=`表示。我们看几个例子

``````
a=10
b=a
a is b #true
a == b #true
```
```
``````
a = [1,2,3]
b = [1,2,3]
a is b #false
a == b #true
```
```
``````
a=10
b=10.0
a is b #false
a == b #true
```
```
``````
a = None
b = None
a is None #true
a == b #true
```
```

### Everything is Object

Python中所有的变量有自己的类型，它们的类型都是某种class，就连`class`本身也是某个class的实例，因此可以说Python中的所有变量都是Object。

``````def square(a):
return a**2

type(square) #<class 'function'>
print(hex(id(square))) #0x1011b4268
f = square
f is square #ture
``````

``````>>> help(int)
class int(object)
|  int([x]) -> integer
|  int(x, base=10) -> integer
|
|  Convert a number or string to an integer, or return 0 if no arguments
|  are given.  If x is a number, return x.__int__().  For floating point
|  numbers, this truncates towards zero.
|
|  If x is not a number or if base is given, then x must be a string,
|  bytes, or bytearray instance representing an integer literal in the
|  given base.  The literal can be preceded by '+' or '-' and be surrounded
|  by whitespace.  The base defaults to 10.  Valid bases are 0 and 2-36.
|  Base 0 means to interpret the base from the string as an integer literal.
|  >>> int('0b100', base=0)
|  4
...
``````

``````c = int()
c #0
c = int(10)
c #10
c = int('101',base=2) #二进制数
c #5
``````

## 变量的编译器优化

### Interning

``````a = 10 #0x10375e130
b = 10 #0x10375e130

a=500 #0x1015ed110
b=500 #0x1015ed030
``````

``````a = -5 #0x10107af50
b = -5 #0x10107af50

a = -6 #0x1015ed110
b = -6 #0x1015ed030
``````

``````a = 'some_long_string'
b = 'some_long_string'
a is b # true
``````

identifier是指只包含数字，字母，下划线的字符串

``````a = 'hello world'
b = 'hello world'
a is b #false
a == b #true
``````

``````import sys
a = sys.intern('the quick brown fox')
b = sys.intern('the quick brown fox')
a is b #true
``````

### Peephole

Peephole是Python编译器的另一项优化技术，他可以对一些常量表达式进行提前求值，并将结果缓存，例如

``````def my_func():
a = 24*60  #1440
b = (1,3)*5 #(1,3,1,3,1,3,1,3,1,3)
c = 'abc'*3 #abcabcabc
d = 'ab'*11
e = 'the quick brown fox' * 5
f = ['a','b']*3
``````

``````(None,
1440,
(1, 3, 1, 3, 1, 3, 1, 3, 1, 3),
'abcabcabc',
'ababababababababababab',
'the quick brown foxthe quick brown foxthe quick brown foxthe quick brown foxthe quick brown fox',
'a', 'b', 3
)
``````

``````if e in [1,2,3]:
``````

``````
#using array
def my_func(e):
for e in [1,2,3]:
pass
```
```
``````
#using set
def my_func(e):
for e in {1,2,3}:
pass
```
```

``````#using tuple
(None, (1, 2, 3))

#using set
(None, frozenset({1, 2, 3}))
``````

``````import string
import time
letters = string.ascii_letters
char_list = list(letters)
char_tuple = tuple(letters)
char_set = set(letters)
print(char_list)

def membership_test(n,container):
for i in range(n):
if 'z' in container:
pass

#test array
start = time.perf_counter()
membership_test(1000000,char_list) #一百万次
end = time.perf_counter()
print('list:',end-start) #list: 0.461002645

#test tuple
start = time.perf_counter()
membership_test(1000000,char_tuple)
end = time.perf_counter()
print('tuple:',end-start) #tuple: 0.44785893200000004

#test set
start = time.perf_counter()
membership_test(1000000,char_set)
end = time.perf_counter()
print('set:',end-start) #set: 0.04525098400000005
``````

（全文完）