一直没能系统性的看看Python,都是用一点学一点,遇到不熟悉的部分效率就很低。
最近终于有时间看看《Python菜鸟教程》和《python编程从入门到实践》,这两部分是很好的入门资料和书籍,感觉新手读完这两就能解决平时80%的问题了。Python也很繁杂,师父领进门,修行靠个人,大体有了把握,遇到实际问题再细致攻克,自认为是效率最高的模式,一口吃个胖子的方法并不可取。
《Python菜鸟教程》:Python3 基础语法 | 菜鸟教程
Python 入门指南 — Python tutorial 3.6.3 documentation
《python编程从入门到实践》:某宝搜索,我愿称为 “python圣经”
1. python import 导入两个模块同时有同一名称的方法如何调用 ?
python import 导入两个模块同时有同一名称的方法如何调用 ? - myrj - 博客园
2. 不同于C++、Java,python中的变量不需要提前声明,即python是动态语言,变量没有变量类型一说,变量名只是一个引用,引用的对象才有所谓的类型——数据类型。标准的数据类型有6种,可用两个标准衡量(区分):(1)数据类型本身是否为可变数据;(2)数据类型的元素是否是可变数据
数据类型本身是否可变 | 数据类型元素是否接受可变数据类型 | |
Number(数字) | 否(不可变类型) | 无元素 |
String(字符串) | 否(不可变类型) | 无元素 |
Tuple(元组) | 否(不可变类型) | 是 |
List(列表) | 是(可变类型) | 是 |
Dictionary(字典) | 是(可变类型) | 键(key)必须使用不可变类型 值(value)任意数据类型均可 |
Set(集合) | 是(可变类型) | 否 |
注:Set(集合)不能接受可变数据类型,即集合的元素只能是Number(数字)、String(字符串)、Tuple(元组),但常常需要使集合的元素是另外的集合,因而需要用到 frozenset(s) ,将可变集合类型变为不可变集合类型以此解决。
3. 变量是对象的引用,此处延伸下变量和对象之间的关系,截取自文后笔记(Python3 基本数据类型 | 菜鸟教程):
- 赋值操作,本质是创建引用
- 变量是变量,对象是对象,当将某个对象赋值给某个变量时,可以认为是创建了变量对该对象的引用
- 变量没有数据类型之说,只有对象有,即变量不是直接代表对象或对象占用的内存空间
- Python中,变量无需提前声明,无需指定其数据类型,其表现完全是动态的,其所为的数据类型决定于当前该变量所引用的对象的数据类型
- 所谓变量对对象的引用,本质是创建了变量指向对象内存空间的指针
- 对象内存空间,一般最起码有类型和当前被引用次数这两个信息,类型记录了该对象的数据类型,被引用次数记录了该对象内存空间被变量引用的次数
- 当某对象的被引用次数为0时,Python便会自动回收该对象内存空间
比如下面的
a=10 a='122' a=[1,2,3] del a
此时,a在不同的赋值代码行中,引用的对象类型不同,相当于在不断改变a引用的对象,最后当把a变量删除时,其实本质只是删除了a变量名,但由于a引用的[1,2,3]对象,因为a被删除,其被引用次数变为0,也就自动被Python回收,最终表现就是del a时,[1,2,3]也被删除了。
另外一个小知识是,Python为提升代码执行和内存分配效率,会对一些常用的对象提前创建好,并常驻内存,比如下面:
id(4) #不管运行多少次该代码,其返回的值均不变,因为python会保持一些常用的数字常驻内存,不会每次都重新分配内存空间 id('hello world') #每次运行,返回的值均会发生变化,因为每次运行,相当于都在重新分配内存空间
注:当出现一行多个赋值的时候,如 x = y = ['aaa', 'bbb'] ,其实只是对列表对象创建了多个引用而已,并未实际创建多个对象。所以当改变其中一个引用的某值时,x[0] = 'ccc',那么 y[0] 也会相应改变为 'ccc'
4. 变量(引用)与对象的关系
判断变量是否对应同一个对象,可用 is 判断,var1 is var2; is本质是通过对象的内存id号判断的,即判断变量是否引用同一个对象。
对于python的六种标准数据类型,若数值完全相同,那么只有数字和元组类型的数据id号是相同的。其他类型数据,即使数值完全相同,但具有不同的id。
list1=[1000,3,5] list2=[1000,3,5] print(list1 is list2) tuple1=(1000,3,5) tuple2=(1000,3,5) print(tuple1 is tuple2) str1 = 'aaa' str2 = 'bbb' print(str1 is str2) num1 = 10000 num2 = 10000 print(num1 is num2) dict1={1:1000,2:3,3:5} dict2={1:1000,2:3,3:5} print(dict1 is dict2) set1 = {'aaa', 'bbb'} set2 = {'aaa', 'bbb'} print(set1 is set2)
分别对应列表、元组、字符串、数字、字典、集合类型的数据,判断结果为:
False
True
False
True
False
False
5. 逻辑运算符 and 和 or
and 从左到右计算表达式,若所有值均为真,则返回最后一个真值;若存在假,则返回第一个假值;
or 也是从左到有计算表达式,若有真值,则返回第一个为真的值;若全为假值,则返回最后一个假值。
其中数字 0 是假,其他都是真;字符 "" 是假,其他都是真。
6. python中的进制问题
python中默认输入输出都是十进制
输入进制改变:
二进制 | 0b a = 0b111100 |
八进制 | 0o a = 0o77 |
十六进制 | 0x a = 0xFF |
输出进制改变:
二进制 | bin(a) |
八进制 | oct(a) |
十六进制 | hex(a) |
7. max()函数
max(x, y[, z...]):Number|Sequence 入参类型不能混入。要么全Number(int|float|complex|bool),要么全序列,但注意传入的序列类型应保持一致,即要么全传列表,要么全传元组。
入参是序列的话: 单序列入参,返回序列中最大的一个数值多序列入参, 按索引顺序,逐一对比各序列的当前索引位的 “值”,直到遇见最大值立即停止对比,并返回最大值所在的序列(也就是说,多序列入参,返回值依旧是一个序列,而不是数值)
注:如果出现max函数中元素完全相等的情况,那么max函数默认返回第一个对象。
8. round()函数中的坑
Python 中关于 round 函数的小坑 | 菜鸟教程
9. 对象的id问题
python中的对象是关注的焦点,变量名只是变量的一个引用。
变量在内存的存储位置由id标识。
对于不可变数据类型,当其值相同时,其id就相同;对于可变数据类型,其id总是不同的,即使其值相同。
站在python的角度,其实也好理解,如果可变数据类型当值相同,id也相同时,就会出现,两个变量同时引用一个可变内存的情况,那么当其中一个引用改变该类型的某个数据时,那么另一个引用也会被迫改变,这是我们不愿意看到的。但对于不可变类型,其值本身不接受更改,便不存在这个问题。
注:1.python没有自增操作符,可通过a=a+1实现;2.在交互式环境中,编译器会有一个小整数池的概念,会把(-5,256)间的数预先创建好,而当a和b超过这个范围的时候,两个变量就会指向不同的对象了。但在平时的脚本式编程环境(IDE)中,则没有这一说法。
10. 浅拷贝深拷贝问题
根本区别:深拷贝会把可变对象也拷贝一份,而浅拷贝不会。
Python 直接赋值、浅拷贝和深度拷贝解析 | 菜鸟教程
Python 深拷贝和浅拷贝的区别_Rp_的博客-优快云博客_python深拷贝和浅拷贝的区别
11. python基础数据类型转换
其中,转换为string时候,要求元素均为字符类型,否则join会报错。解决:
print(''.join('%s' % item for item in list))
print(''.join('%s' % item for item in tuple))
12. tuple数据类型的元素修改
tuple元组自身是不可变类型数据,不接受元素的修改。因而若想修改元组元素,可先将元组转换为列表,更改完成后,再转换为元组:
tmp = ('aaa', 1, ['aaa', 1]) tmp = list(tmp) tmp[0] = 9 # 修改元素语句 tmp = tuple(tmp) print(tmp)
13. 创建dict时,慎用fromkeys()方法
list_ = [1,2,3]
d = dict.fromkeys(list_ , [])
这样创建得到的字典是:
{1:[] , 2:[] , 3:[]}
但这样三个列表的地址是一样的,修改任意一个列表的值会导致所有列表的值都发生改变。
可以用一下方法来解决:
d = {key : [] for key in list_}
14. 多个循环时
当某个循环内仍存在多个循环的时候,要特别注意 for i in ... 中 i 的使用,习惯性的都用 i 表达循环是十分不好的习惯,因为多个循环嵌套时, i 值间会相互覆盖,导致时序错乱,出现难以预料的错误。建议:使用 i, j, m, n 等,并清楚知道每个循环数的作用和意义。
15. 函数中的参数传递问题
若在函数内执行赋值操作,则会生成新的对象,函数中操作的对象就会发生变化。
根据传入参数对象的不同,可分为传不可变对象和可变对象。(注:python 的变量不存在变量类型一说,变量是对对象的引用,只有对象有类型)
若传入不可变对象,相当于是C++中的值传递,若在传入后的函数中改变变量值,实际上并不会影响原始参数(传入前的变量对应值),如:
def change(a):
print(id(a)) # 指向的是同一个对象
a=10
print(id(a)) # 一个新对象
a=1
print(id(a))
change(a)
主函数中 a 的 id 值,在执行函数前后不变
若传入可变对象,相当于是C++中的引用传递,在函数中对对象的改变会影响原始参数
#=======================================================
def changeme( mylist ):
"修改传入的列表"
mylist.append([1,2,3,4])
print ("函数内取值: ", mylist)
return
# 调用changeme函数
mylist = [10,20,30]
changeme( mylist )
print ("函数外取值: ", mylist)
主函数中的 mylist ,在执行函数前后会改变
16. lambda 表达式的合法用例是在不分配函数的情况下使用函数,即只是临时使用函数而不需要重复分配
如:sorted(players, key=lambda player: player.rank)
17. python函数中变量作用域
变量的访问以 L(Local) –> E(Enclosing) –> G(Global) –>B(Built-in) 的规则查找
局部 —> 局部外的局部 (如闭包) —> 全局 —> 内建
一个典型示例程序为:
num = 20 # 全局变量
def outer():
num = 10 # 局部变量
def inner():
global num # 获取全局变量,注:如果不在函数中修改变量值,只读取时可省略声明
print (num)
num = 100 # 修改变量值
print (num)
inner()
print(num) # 此时会优先输出局部变量值 10
outer()
print (num) # 输出修改后的全局变量
18.