变量和基本数据类型,深浅拷贝问题

变量

什么是变量

量:衡量/计量/记录某种状态                变:记录下来的某种状态是可以发生变化的

为何要用变量

为了让计算机能够像人一样去识别世间万物,更接近于人的思想            如何识别,就是把事物的特征记录下来=>变量的定义

如何用变量

变量的使用必须遵循:先定义,后引用

定义变量

x=10
name = 'joek'
age=18
salary=15k

定义一个变量分为三部分

变量名:变量名是访问到值的唯一方式      赋值符号:将值的内存地址"赋值"给变量名        变量的值:记录状态

变量名的命名规范:   

大前提:变量名的命名应该对值有描述性的功能        变量名只能是 字母、数字或下划线的任意组合       变量名的第一个字符不能是数字        关键字不能声明为变量名

变量名的命名风格

 驼峰体: OldboyOfAge=73       下划线纯小写式 :  oldboy_of_age=73            在python中变量名的命名推荐使用下划线

运行python程序的三个阶段

python3 D:\test.py
先启动python解释器     python解释器将python文件由硬盘读入内存     python解释器解释执行刚刚读入内存的代码,开始识别python语法

引用计数的概念

引用计数:计算值被关联了多少个变量名
引用计算一旦为零就是垃圾,会被python的垃圾回收机制自动清理
引用技术增加
 x=10
 y=x

引用技术减少
x=10
del x     解除变量名与值10内存地址的绑定关系

变量值具备三个特征(id,tpye,value)

1. id: 变量值的唯一编号,内存地址不同id则不同         2. type:类型             3. value 值

x=10
y=x
print(id(x),id(y))

age=10

print(id(age))
print(type(age))
print(age)

is与==  :      is身份运算:比较的是id是否相等               ==判断值是否相等

x=10
y=x
print(id(x),id(y))
print(x is y) #id相等,值一定相等
print(x == y)
'''
1839623936 1839623936
True
True
'''

值相等id不一定相等(变量补充里会有更加详细的说明)

x=111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
>>> y=111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
>>> id(x)
2181129522824
>>> id(y)
2181129523040
>>> x is y
False
>>> x == y
True

常量(一般约定俗称用大写字母)

BOY_OF_AGE=73
BOY_OF_AGE=74
print(BOY_OF_AGE)

变量的实质

Python变量区别于其他编程语言的申明&赋值方式,采用的是创建&指向的类似于指针的方式实现的。即Python中的变量实际上是对值或者对象的一个指针(简单的说他们是值得一个名字)

对于传统语言,先在内存中申明一个p的变量,然后将1存入变量p所在内存。执行加法操作的时候得到2的结果,将2这个数值再次存入到p所在内存地址中。可见整个执行过程中,变化的是变量p所在内存地址上的值

然而Python实际上是现在执行内存中创建了一个1的对象,并将p指向了它。在执行加法操作的时候,实际上通过加法操作得到了一个2的新对象,并将p指向这个新的对象。可见整个执行过程中,变化的是p指向的内存地址

变量的查找顺序

解析器按照下面的顺序查找一个变量

Local - 本地函数(show_filename)内部,通过任何方式赋值的,而且没有被global关键字声明为全局变量的filename变量;
Enclosing - 直接外围空间(上层函数wrapper)的本地作用域,查找filename变量(如果有多层嵌套,则由内而外逐层查找,直至最外层的函数);
Global - 全局空间(模块enclosed.py),在模块顶层赋值的filename变量;
Builtin - 内置模块(__builtin__)中预定义的变量名中查找filename变量;

在任何一层先找到了符合要求的变量,则不再向更外层查找。如果直到Builtin层仍然没有找到符合要求的变量,则抛出NameError异常。这就是变量名解析的:LEGB法则

变量补充

小整数对象池

整数在程序中的使用非常广泛,Python为了优化速度,使用了小整数对象池, 避免为整数频繁申请和销毁内存空间。
Python 对小整数的定义是 [-5, 256] 这些整数对象是提前建立好的,不会被垃圾回收。在一个 Python 的程序中,无论这个整数处于LEGB中的哪个位置,
所有位于这个范围内的整数使用的都是同一个对象。同理,单个字母也是这样的

ps:不能在pycharm下运行,后面会说为什么

a = -5
b = -5

a is b
True

a = 256
b = 256

a is b
True

a = 1000
b = 1000

a is b
False

intern机制 处理空格
一个单词的复用机会大,所以创建一次,有空格,创建多次,但是字符串长度大于20,就不是创建一次了

a = "abc"
b = "abc"

a is b
True

a = "helloworld"
b = "helloworld"

a is b
True

a = "hello world"
b = "hello world"

a is b
False

s1 = "abcd"
s2 = "abcd"
print(s1 is s2)
# True
s1 = "a" * 20
s2 = "a" * 20
print(s1 is s2)
# True
s1 = "a" * 21
s2 = "a" * 21
print(s1 is s2)
# False
s1 = "ab" * 10
s2 = "ab" * 10
print(s1 is s2)
# True
s1 = "ab" * 11
s2 = "ab" * 11
print(s1 is s2)
# False

大整数对象池

说明:终端是每次执行一次,所以每次的大整数都重新创建,而在pycharm中,每次运行是所有代码都加载都内存中,属于一个整体,所以
这个时候会有一个大整数对象池,即处于一个代码块的大整数是同一个对象

#没有在pycharm下运行
a = 1000
b = 1000

a is b
False

a = -1888
b = -1888

a is b
False

#在pycharm下运行
c1和d1处于一个代码块,所以相等
而c1.b和c2.b分别有自己的代码块,所以不相等。

c1 = 1000
d1 = 1000
print(c1 is d1)  # True

class C1(object):
    a = 100
    b = 100
    c = 1000
    d = 1000

class C2(object):
    a = 100
    b = 1000

print(C1.a is C1.b)  # True
print(C1.a is C2.a)  # True
print(C1.c is C1.d)  # True
print(C1.b is C2.b)  # False 

数据类型

什么是数据类型

变量值即我们存放的数据,数据类型及变量值的类型

变量值为何要区分类型

因为变量值使用记录现实世界中事物的特征,针对不同的特征就应该用不同类型的值去标识

整型int: 年龄\身份证号\电话号码\等级
age=18 
print(id(age),type(age),age)

浮点型float:薪资\身高\体重
salary=3.1 #salary=float(3.1)
print(id(salary),type(salary),salary) 

字符串类型str: 名字\家庭住址\单个爱好\性别等等描述性质的特征
定义:在引号(单引号\双引号\三引号)内包含一串字符

name1='egon'
name2="egon"
name3="""egon"""
print(type(name1))
print(type(name2))
print(type(name3))
msg='my name is "egon"' 
print(msg)

msg1='hello'
msg2='world'
res=msg1 + msg2
print(res,type(res))
print(msg1)
print('='*100)
print(msg2)
View Code

列表list: 记录多个值,比如人的多个爱好,一个班级多个学生的性别
定义:在[]内用逗号分隔开多个任意类型的值

l=[1,3.1,'aa',['a','b','c',['aaaa','bbbb']]]
print(l)
print(l[0])
print(l[2])
print(l[3][1])
print(l[3][3][0])
View Code

字典dict: 记录多个key:value值

定义:在{}内用逗号分隔开多个key:value的值,其中value可以是任意数据类型,
而key通常应该是字符串类型

info={
'name':'egon',
'age':18,
'sex':'male',
'level':10,
'hobbies':['music','read','dancing']
} #info=dict(...)
print(type(info))
print(info['level'])
print(info['age'])
print(info['hobbies'][1])

emp_info={
name':'egon',
'hobbies':['play','sleep'],
'company_info':{
'name':'Oldboy',
'type':'education',
'emp_num':40,
 }
}
print(emp_info['company_info']['name'])

 
View Code

布尔类型bool: True/False,用来标识条件是否成立

age=18
print(age > 30)
print(age < 30)
View Code

所有类型的值都自带布尔值: 当数据类型的值为0,None,空时,布尔值为False,除此以外都为True

print(bool(0))
print(bool(None))
print(bool(''))
print(bool([]))
print(bool({}))
print(bool(1))

if None:
  print('条件成立了11确实大于10的')
View Code

深拷贝和浅拷贝问题

什么是深浅拷贝(浅拷贝只拷贝最外层,深拷贝有多少层都拷贝)

深拷贝是对于一个对象所有层次的拷贝(递归)copy.deepcopy

浅拷贝是对于一个对象的顶层拷贝;通俗的理解是:拷贝了引用,并没有拷贝内容.copy.copy      要理解此时引用的意思,不要理解错了

复习:可变类型和不可变类型

不可变类型:整型,长整型,浮点数,复数,布尔,字符串,元组
可变类型:列表,字典

深浅拷贝有什么区别

1、如果用copy.copy、copy.deepcopy对一个全部都是不可变类型的数据进行拷贝,那么它们结果相同,都是引用指向;
2、如果拷贝的是一个拥有不可变类型的数据,即使元组是最顶层,那么deepcopy依然是深拷贝,而copy.copy还是指向
3、基本上只要不是我们自已手动调用的deepcopy方法都是浅拷贝,切片拷贝,字典拷贝都是浅拷贝,而有些内置函数可以生成拷贝(list),属于深拷贝:a = list(range(10))b = list(a) 

更加详细的深浅拷贝分析请参考:https://www.cnblogs.com/Eva-J/p/5534037.html

 

posted @ 2018-09-13 16:45  丶无根生  阅读(206)  评论(0编辑  收藏  举报