写在前面:
由于之前有一定的编程基础,所以对python也有一定的理解,所以这篇博客并不是完全按照给的框架来写的,临时有点事,所以后期写的有点粗糙,请见谅,希望后期有时间来优化。
文章目录
一. 变量和对象
在Python中一切都是对象,变量总是存放对象引用。当没有变量指向对象时,这个对象便进入了垃圾收集过程。Python的“动态类型”机制,负责检查变量的对象引用适用操作。如果该对象不适用该操作,则会直接报错。一句话变量无类型,对象有类型
1.变量和对象
Python中一切都是对象,赋值的作用就是让变量指针指向某个对象,也就是说变量中存放的对象的引用,而对象的引用是指向这个对象。
我的理解就是对象就是其他静态语言中说的变量的内容,也就是实际占用内存空间的一些东西,python中所有东西都是占有内存空间的,也可以理解为所有出现的东西都是具有实际作用的,不像指针的作用就是找到某个具体的东西,也就是摒除了指针这种东西(指针也要占用内存空间的),这也是python的简化之处,其中变量就是对象的引用(总要有一个东西来帮忙找到具体东西所在的内存位置,没有指针就只能用引用了),通俗的来理解引用就是“标签”,或者说是“导向牌”,理解为实际东西的内存地址,标签是可以改变的,今天是A的标签,明天也可是B的标签。
python 中,类型属于对象,变量是没有类型的
a = [1,2,3]
a = 'aha'
[1,2,3] 是 List 类型,“aha” 是 String 类型,而变量 a 是没有类型,她仅仅是一个对象的引用(一个指针),可以是指向 List 类型对象,也可以是指向 String 类型对象。
2.python中的赋值“=”
x = "blue"
y="green"
z=x
python执行第一句时,在heap中首先创建str对象,其文本内容为blue,同时还创建变量名为x的对象引用,x引用的就是这个str对象;
第二句类似,创建变量y指向str对象;第三句创建变量z的新对象引用,并将其指向对象引用x指向的相同对象。
所以Python中赋值操作符号“=”的作用是,将对象引用和内存中的某个对象进行绑定。如果对象已经存在,就进行简单的重新绑定,以便引用“=”右边的对象;如果对象引用尚未存在,就首先创建对象,然后将对象引用和对象进行绑定。这很类似与c中的指针的概念。
通俗来说就是Python中”=“:等号两边一个是变量,一个是对象,就把变量和对象进行绑定,两边都是变量的话就是这两个变量都指向同一个对象,都和同一个对象进行绑定。
>>> list_a = [1,2,3,'x','y']
>>>> list_b = list_a
>>> list_b
[1, 2, 3, 'x', 'y']
修改一下list_b中的值,然后分别查看list_b和list_a列表的值
>>> list_b[2] = 'new'
>>> list_b
[1, 2, 'new', 'x', 'y']
>>> list_a
[1, 2, 'new', 'x', 'y']
可以看出修改list_b列表中的值后,list_a列表中的值也跟着变了,这是因为list_a和list_b都指向同一内存空间地址。说明了Python中,任何变量存储并非等号“=”后的值,而是给“=”后的值分配的内存空间的地址值。这就就是我们说的“引用”。
3.list复制
>>> list_a = [1,3,4,5]
将list_a非引用的复制给list_b
>>> list_b = list_a[:]
>>> list_b
[1, 3, 4, 5]
>>> id(list_a)
39444688
>>> id(list_b)
39444768
>>> list_b[1] = 888
>>> list_b
[1, 888, 4, 5]
>>> list_a
[1, 3, 4, 5]
所以真正的非引用式的list复制格式是这样的:
list_dest = list_src[:]
4. id(),==,is的差别
- id():获取对象在内存中的地址
- is:比对2个变量的对象引用(对象在内存中的地址,即id() 获得的值)是否相同。如果相同则返回True,否则返回False。换句话说,就是比对2个变量的对象引用是否指向同一个对象。
- ==:对比2个变量指向对象的内容是否相同。
l1 = [1, 2, 3]
l2 = [1, 2, 3]
print l1 == l2 <span style="font-family: Arial, Helvetica, sans-serif;">#两个变量指向对象值相等,故返回true</span>
print l1 is l2 <span style="font-family: Arial, Helvetica, sans-serif;">#l1和l2貌似指向同一个对象[1, 2, 3],但在内存中其实是两块不相关的东西,故返回false</span>
l3 = l1
print l3 is l1 #l3和l1指向同一个对象,故返回true
l3[0] = 4
print l1 #[4, 2, 3]
print l3 #[4, 2, 3]
print l2 #[1, 2, 3]
a = 100
b = 100
print a is b #不同于list对象,返回true
5.动态类型机制
Python使用“动态类型”机制,也就是说,在Python程序中,任何时候可以根据需要,某个对象引用都可以重新绑定到另一个不同的对象上(不要求是相同的类型),这和其他强化型语言如(C++,Java)不太一样,只允许重新绑定相同类型的对象上。在Python中,因为有“动态类型”机制,所以一个对象引用可以执行不同类型的对象适用的方法。当一个对象不存在任何对象引用的时候,就进入了垃圾收集的过程。(Python自动回收机制)
二. 函数
1.定义
函数是组织好的,可重复使用的,用来实现单一,或相关联功能的代码段。
我的理解就是函数就是功能的代名词,每用一个函数就实现了一个功能,因为python提供了很多内建函数和很多库,所以python语言很简单,我幻想中的编程的最后就是所有能用到的功能都写成了函数,这样以后码农只要一本函数大全就能干好码代码的工作了。
2. 定义一个函数
语法:
def 函数名(参数列表):
函数体
光使用已经定义好的函数还是不够,所以有时候我们还需要自己造轮子
默认情况下,参数值和参数名称是按函数声明中定义的顺序匹配起来的
3.参数
3. 1 参数类型
- 必需参数
必需参数须以正确的顺序传入函数。调用时的数量必须和声明时的一样。 - 关键字参数
关键字参数和函数调用关系紧密,函数调用使用关键字参数来确定传入的参数值
使用关键字参数允许函数调用时参数的顺序与声明时不一致,因为 Python 解释器能够用参数名匹配参数值。 - 默认参数
调用函数时,如果没有传递参数,则会使用默认参数 - 不定长参数
你可能需要一个函数能处理比当初声明时更多的参数。这些参数叫做不定长参数,和上述 2 种参数不同,声明时不会命名
def functionname([formal_args,] *var_args_tuple ):
"函数_文档字符串"
function_suite
return [expression]
加了星号 * 的参数会以元组(tuple)的形式导入,存放所有未命名的变量参数。
3.2 参数传递
- 传不可变对象
类似 c++ 的值传递,如 整数、字符串、元组。如fun(a),传递的只是a的值,没有影响a对象本身。比如在 fun(a)内部修改 a 的值,只是修改另一个复制的对象,不会影响 a 本身。
def ChangeInt( a ):
a = 10
b = 2
ChangeInt(b)
print( b ) # 结果是 2
int 对象 2,指向它的变量是 b,在传递给 ChangeInt 函数时,按传值的方式复制了变量 b,a 和 b 都指向了同一个 Int 对象,在 a=10 时,则新生成一个 int 值对象 10,并让 a 指向它
- 传可变对象
类似 c++ 的引用传递,如 列表,字典。如 fun(la),则是将 la 真正的传过去,修改后fun外部的la也会受影响
def changeme( mylist ):
"修改传入的列表"
mylist.append([1,2,3,4])
print ("函数内取值: ", mylist)
return
# 调用changeme函数
mylist = [10,20,30]
changeme( mylist )
print ("函数外取值: ", mylist)
传入函数的和在末尾添加新内容的对象用的是同一个引用。故输出结果如下:
函数内取值: [10, 20, 30, [1, 2, 3, 4]]
函数外取值: [10, 20, 30, [1, 2, 3, 4]]
4.作用域
变量的作用域决定了在哪一部分程序可以访问哪个特定的变量名称
- Python 中,程序的变量并不是在哪个位置都可以访问的,访问权限决定于这个变量是在哪里赋值的。
- Python的作用域一共有4种,分别是:L (Local) 局部作用域 —> E (Enclosing) 闭包函数外的函数中 —> G (Global) 全局作用域 —> B (Built-in) 内置作用域(内置函数所在模块的范围)
- 以 L –> E –> G –>B 的规则查找,即:在局部找不到,便会去局部外的局部找(例如闭包),再找不到就会去全局找,再者去内置中找。
g_count = 0 # 全局作用域
def outer():
o_count = 1 # 闭包函数外的函数中
def inner():
i_count = 2 # 局部作用域
4.1全局变量和局部变量
-
定义在函数内部的变量拥有一个局部作用域,定义在函数外的拥有全局作用域。
-
局部变量只能在其被声明的函数内部访问,而全局变量可以在整个程序范围内访问。调用函数时,所有在函数内声明的变量名称都将被加入到作用域中。
4.2 global 和 nonlocal 关键字
- 当内部作用域想修改外部作用域的变量时,就要用到global和nonlocal关键字了
- 如果要修改嵌套作用域(enclosing 作用域,外层非全局作用域)中的变量则需要 nonlocal 关键字了
5.return函数
return [表达式] 语句用于退出函数,选择性地向调用方返回一个表达式。不带参数值的return语句返回None。之前的例子都没有示范如何返回数值